Merge pull request #9888 from murgatroid99/electron_uv_fix

Fix missing wakeups when using the libuv iomgr under Electron
diff --git a/.gitignore b/.gitignore
index 618c9ba..56e4b6d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
 cython_debug/
 python_build/
 python_format_venv/
+python_pylint_venv/
 .coverage*
 .eggs
 htmlcov/
@@ -32,7 +33,7 @@
 # python compiled objects
 *.pyc
 
-#eclipse project files
+# eclipse project files
 .cproject
 .project
 .settings
@@ -111,3 +112,6 @@
 bazel-grpc
 bazel-out
 bazel-testlogs
+
+# Debug output
+gdb.txt
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..da2081b
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,34 @@
+[MESSAGES CONTROL]
+
+#TODO: Enable missing-docstring
+#TODO: Enable too-few-public-methods
+#TODO: Enable too-many-arguments
+#TODO: Enable no-init
+#TODO: Enable duplicate-code
+#TODO: Enable invalid-name
+#TODO: Enable suppressed-message
+#TODO: Enable locally-disabled
+#TODO: Enable protected-access
+#TODO: Enable no-name-in-module
+#TODO: Enable unused-argument
+#TODO: Enable fixme
+#TODO: Enable wrong-import-order
+#TODO: Enable no-value-for-parameter
+#TODO: Enable cyclic-import
+#TODO: Enable unused-variable
+#TODO: Enable redefined-outer-name
+#TODO: Enable unused-import
+#TODO: Enable too-many-instance-attributes
+#TODO: Enable broad-except
+#TODO: Enable too-many-locals
+#TODO: Enable too-many-lines
+#TODO: Enable redefined-variable-type
+#TODO: Enable next-method-called
+#TODO: Enable import-error
+#TODO: Enable useless-else-on-loop
+#TODO: Enable too-many-return-statements
+#TODO: Enable too-many-nested-blocks
+#TODO: Enable super-init-not-called
+#TODO: Enable no-self-use
+
+disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,no-self-use
diff --git a/BUILD b/BUILD
index 5419251..ca0a1c5 100644
--- a/BUILD
+++ b/BUILD
@@ -63,7 +63,7 @@
     deps = [
         "census",
         "grpc_base",
-        "grpc_lb_policy_grpclb",
+        "grpc_lb_policy_grpclb_secure",
         "grpc_lb_policy_pick_first",
         "grpc_lb_policy_round_robin",
         "grpc_load_reporting",
@@ -127,7 +127,6 @@
         "src/cpp/server/secure_server_credentials.cc",
     ],
     hdrs = [
-        "include/grpc++/impl/codegen/core_codegen.h",
         "src/cpp/client/secure_credentials.h",
         "src/cpp/common/secure_auth_context.h",
         "src/cpp/server/secure_server_credentials.h",
@@ -140,6 +139,7 @@
         "grpc++_base",
         "grpc++_codegen_base",
         "grpc++_codegen_base_src",
+        "grpc++_codegen_proto",
     ],
 )
 
@@ -284,9 +284,15 @@
         "src/core/ext/census/resource.h",
         "src/core/ext/census/rpc_metric_id.h",
         "src/core/ext/census/trace_context.h",
+        "src/core/ext/census/trace_label.h",
+        "src/core/ext/census/trace_propagation.h",
+        "src/core/ext/census/trace_status.h",
+        "src/core/ext/census/trace_string.h",
+        "src/core/ext/census/tracing.h",
     ],
     external_deps = [
         "nanopb",
+        "libssl",
     ],
     language = "c",
     public_hdrs = [
@@ -352,6 +358,7 @@
         "src/core/lib/support/env.h",
         "src/core/lib/support/mpscq.h",
         "src/core/lib/support/murmur_hash.h",
+        "src/core/lib/support/spinlock.h",
         "src/core/lib/support/stack_lockfree.h",
         "src/core/lib/support/string.h",
         "src/core/lib/support/string_windows.h",
@@ -499,6 +506,8 @@
         "src/core/lib/slice/percent_encoding.c",
         "src/core/lib/slice/slice.c",
         "src/core/lib/slice/slice_buffer.c",
+        "src/core/lib/slice/slice_hash_table.c",
+        "src/core/lib/slice/slice_intern.c",
         "src/core/lib/slice/slice_string_helpers.c",
         "src/core/lib/surface/alarm.c",
         "src/core/lib/surface/api_trace.c",
@@ -518,14 +527,16 @@
         "src/core/lib/surface/server.c",
         "src/core/lib/surface/validate_metadata.c",
         "src/core/lib/surface/version.c",
+        "src/core/lib/transport/bdp_estimator.c",
         "src/core/lib/transport/byte_stream.c",
         "src/core/lib/transport/connectivity_state.c",
-        "src/core/lib/transport/mdstr_hash_table.c",
+        "src/core/lib/transport/error_utils.c",
         "src/core/lib/transport/metadata.c",
         "src/core/lib/transport/metadata_batch.c",
         "src/core/lib/transport/pid_controller.c",
         "src/core/lib/transport/service_config.c",
         "src/core/lib/transport/static_metadata.c",
+        "src/core/lib/transport/status_conversion.c",
         "src/core/lib/transport/timeout_encoding.c",
         "src/core/lib/transport/transport.c",
         "src/core/lib/transport/transport_op_string.c",
@@ -555,6 +566,7 @@
         "src/core/lib/iomgr/endpoint.h",
         "src/core/lib/iomgr/endpoint_pair.h",
         "src/core/lib/iomgr/error.h",
+        "src/core/lib/iomgr/error_internal.h",
         "src/core/lib/iomgr/ev_epoll_linux.h",
         "src/core/lib/iomgr/ev_poll_posix.h",
         "src/core/lib/iomgr/ev_posix.h",
@@ -607,6 +619,7 @@
         "src/core/lib/json/json_reader.h",
         "src/core/lib/json/json_writer.h",
         "src/core/lib/slice/percent_encoding.h",
+        "src/core/lib/slice/slice_hash_table.h",
         "src/core/lib/slice/slice_internal.h",
         "src/core/lib/slice/slice_string_helpers.h",
         "src/core/lib/surface/api_trace.h",
@@ -620,14 +633,18 @@
         "src/core/lib/surface/init.h",
         "src/core/lib/surface/lame_client.h",
         "src/core/lib/surface/server.h",
+        "src/core/lib/surface/validate_metadata.h",
+        "src/core/lib/transport/bdp_estimator.h",
         "src/core/lib/transport/byte_stream.h",
         "src/core/lib/transport/connectivity_state.h",
-        "src/core/lib/transport/mdstr_hash_table.h",
+        "src/core/lib/transport/error_utils.h",
+        "src/core/lib/transport/http2_errors.h",
         "src/core/lib/transport/metadata.h",
         "src/core/lib/transport/metadata_batch.h",
         "src/core/lib/transport/pid_controller.h",
         "src/core/lib/transport/service_config.h",
         "src/core/lib/transport/static_metadata.h",
+        "src/core/lib/transport/status_conversion.h",
         "src/core/lib/transport/timeout_encoding.h",
         "src/core/lib/transport/transport.h",
         "src/core/lib/transport/transport_impl.h",
@@ -640,6 +657,7 @@
         "include/grpc/byte_buffer.h",
         "include/grpc/byte_buffer_reader.h",
         "include/grpc/compression.h",
+        "include/grpc/load_reporting.h",
         "include/grpc/grpc.h",
         "include/grpc/grpc_posix.h",
         "include/grpc/grpc_security_constants.h",
@@ -655,7 +673,6 @@
 
 grpc_cc_library(
     name = "grpc_client_channel",
-    language = "c",
     srcs = [
         "src/core/ext/client_channel/channel_connectivity.c",
         "src/core/ext/client_channel/client_channel.c",
@@ -664,11 +681,14 @@
         "src/core/ext/client_channel/connector.c",
         "src/core/ext/client_channel/default_initial_connect_string.c",
         "src/core/ext/client_channel/http_connect_handshaker.c",
+        "src/core/ext/client_channel/http_proxy.c",
         "src/core/ext/client_channel/initial_connect_string.c",
         "src/core/ext/client_channel/lb_policy.c",
         "src/core/ext/client_channel/lb_policy_factory.c",
         "src/core/ext/client_channel/lb_policy_registry.c",
         "src/core/ext/client_channel/parse_address.c",
+        "src/core/ext/client_channel/proxy_mapper.c",
+        "src/core/ext/client_channel/proxy_mapper_registry.c",
         "src/core/ext/client_channel/resolver.c",
         "src/core/ext/client_channel/resolver_factory.c",
         "src/core/ext/client_channel/resolver_registry.c",
@@ -681,11 +701,14 @@
         "src/core/ext/client_channel/client_channel_factory.h",
         "src/core/ext/client_channel/connector.h",
         "src/core/ext/client_channel/http_connect_handshaker.h",
+        "src/core/ext/client_channel/http_proxy.h",
         "src/core/ext/client_channel/initial_connect_string.h",
         "src/core/ext/client_channel/lb_policy.h",
         "src/core/ext/client_channel/lb_policy_factory.h",
         "src/core/ext/client_channel/lb_policy_registry.h",
         "src/core/ext/client_channel/parse_address.h",
+        "src/core/ext/client_channel/proxy_mapper.h",
+        "src/core/ext/client_channel/proxy_mapper_registry.h",
         "src/core/ext/client_channel/resolver.h",
         "src/core/ext/client_channel/resolver_factory.h",
         "src/core/ext/client_channel/resolver_registry.h",
@@ -693,6 +716,7 @@
         "src/core/ext/client_channel/subchannel_index.h",
         "src/core/ext/client_channel/uri_parser.h",
     ],
+    language = "c",
     deps = [
         "grpc_base",
     ],
@@ -719,11 +743,13 @@
     name = "grpc_lb_policy_grpclb",
     srcs = [
         "src/core/ext/lb_policy/grpclb/grpclb.c",
+        "src/core/ext/lb_policy/grpclb/grpclb_channel.c",
         "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
         "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
     ],
     hdrs = [
         "src/core/ext/lb_policy/grpclb/grpclb.h",
+        "src/core/ext/lb_policy/grpclb/grpclb_channel.h",
         "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
         "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
     ],
@@ -738,6 +764,31 @@
 )
 
 grpc_cc_library(
+    name = "grpc_lb_policy_grpclb_secure",
+    srcs = [
+        "src/core/ext/lb_policy/grpclb/grpclb.c",
+        "src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c",
+        "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
+        "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
+    ],
+    hdrs = [
+        "src/core/ext/lb_policy/grpclb/grpclb.h",
+        "src/core/ext/lb_policy/grpclb/grpclb_channel.h",
+        "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
+        "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
+    ],
+    external_deps = [
+        "nanopb",
+    ],
+    language = "c",
+    deps = [
+        "grpc_base",
+        "grpc_client_channel",
+        "grpc_secure",
+    ],
+)
+
+grpc_cc_library(
     name = "grpc_lb_policy_pick_first",
     srcs = [
         "src/core/ext/lb_policy/pick_first/pick_first.c",
@@ -820,6 +871,7 @@
         "src/core/lib/security/credentials/plugin/plugin_credentials.c",
         "src/core/lib/security/credentials/ssl/ssl_credentials.c",
         "src/core/lib/security/transport/client_auth_filter.c",
+        "src/core/lib/security/transport/lb_targets_info.c",
         "src/core/lib/security/transport/secure_endpoint.c",
         "src/core/lib/security/transport/security_connector.c",
         "src/core/lib/security/transport/security_handshaker.c",
@@ -843,6 +895,7 @@
         "src/core/lib/security/credentials/plugin/plugin_credentials.h",
         "src/core/lib/security/credentials/ssl/ssl_credentials.h",
         "src/core/lib/security/transport/auth_filters.h",
+        "src/core/lib/security/transport/lb_targets_info.h",
         "src/core/lib/security/transport/secure_endpoint.h",
         "src/core/lib/security/transport/security_connector.h",
         "src/core/lib/security/transport/security_handshaker.h",
@@ -880,7 +933,6 @@
         "src/core/ext/transport/chttp2/transport/huffsyms.c",
         "src/core/ext/transport/chttp2/transport/incoming_metadata.c",
         "src/core/ext/transport/chttp2/transport/parsing.c",
-        "src/core/ext/transport/chttp2/transport/status_conversion.c",
         "src/core/ext/transport/chttp2/transport/stream_lists.c",
         "src/core/ext/transport/chttp2/transport/stream_map.c",
         "src/core/ext/transport/chttp2/transport/varint.c",
@@ -900,11 +952,9 @@
         "src/core/ext/transport/chttp2/transport/hpack_encoder.h",
         "src/core/ext/transport/chttp2/transport/hpack_parser.h",
         "src/core/ext/transport/chttp2/transport/hpack_table.h",
-        "src/core/ext/transport/chttp2/transport/http2_errors.h",
         "src/core/ext/transport/chttp2/transport/huffsyms.h",
         "src/core/ext/transport/chttp2/transport/incoming_metadata.h",
         "src/core/ext/transport/chttp2/transport/internal.h",
-        "src/core/ext/transport/chttp2/transport/status_conversion.h",
         "src/core/ext/transport/chttp2/transport/stream_map.h",
         "src/core/ext/transport/chttp2/transport/varint.h",
     ],
@@ -930,22 +980,21 @@
 )
 
 grpc_cc_library(
-  name = "grpc_transport_chttp2_client_connector",
-  hdrs = [
-   "src/core/ext/transport/chttp2/client/chttp2_connector.h",
-  ],
-  srcs = [
-   "src/core/ext/transport/chttp2/client/chttp2_connector.c",
-  ],
-  language = "c",
-  deps = [
-   "grpc_transport_chttp2",
-   "grpc_base",
-   "grpc_client_channel",
-  ],
+    name = "grpc_transport_chttp2_client_connector",
+    srcs = [
+        "src/core/ext/transport/chttp2/client/chttp2_connector.c",
+    ],
+    hdrs = [
+        "src/core/ext/transport/chttp2/client/chttp2_connector.h",
+    ],
+    language = "c",
+    deps = [
+        "grpc_base",
+        "grpc_client_channel",
+        "grpc_transport_chttp2",
+    ],
 )
 
-
 grpc_cc_library(
     name = "grpc_transport_chttp2_client_insecure",
     srcs = [
@@ -1027,7 +1076,8 @@
         "src/core/ext/transport/cronet/transport/cronet_transport.c",
     ],
     hdrs = [
-        "third_party/Cronet/bidirectional_stream_c.h",
+        "src/core/ext/transport/cronet/transport/cronet_transport.h",
+        "third_party/objective_c/Cronet/bidirectional_stream_c.h",
     ],
     language = "c",
     public_hdrs = [
@@ -1078,11 +1128,16 @@
         "src/cpp/common/channel_filter.cc",
         "src/cpp/common/completion_queue_cc.cc",
         "src/cpp/common/core_codegen.cc",
+        "src/cpp/common/resource_quota_cc.cc",
         "src/cpp/common/rpc_method.cc",
         "src/cpp/common/version_cc.cc",
         "src/cpp/server/async_generic_service.cc",
         "src/cpp/server/create_default_thread_pool.cc",
         "src/cpp/server/dynamic_thread_pool.cc",
+        "src/cpp/server/health/default_health_check_service.cc",
+        "src/cpp/server/health/health.pb.c",
+        "src/cpp/server/health/health_check_service.cc",
+        "src/cpp/server/health/health_check_service_server_builder_option.cc",
         "src/cpp/server/server_builder.cc",
         "src/cpp/server/server_cc.cc",
         "src/cpp/server/server_context.cc",
@@ -1099,6 +1154,8 @@
         "src/cpp/client/create_channel_internal.h",
         "src/cpp/common/channel_filter.h",
         "src/cpp/server/dynamic_thread_pool.h",
+        "src/cpp/server/health/default_health_check_service.h",
+        "src/cpp/server/health/health.pb.h",
         "src/cpp/server/thread_pool_interface.h",
         "src/cpp/thread_manager/thread_manager.h",
     ],
@@ -1110,9 +1167,11 @@
         "include/grpc++/completion_queue.h",
         "include/grpc++/create_channel.h",
         "include/grpc++/create_channel_posix.h",
+        "include/grpc++/ext/health_check_service_server_builder_option.h",
         "include/grpc++/generic/async_generic_service.h",
         "include/grpc++/generic/generic_stub.h",
         "include/grpc++/grpc++.h",
+        "include/grpc++/health_check_service_interface.h",
         "include/grpc++/impl/call.h",
         "include/grpc++/impl/client_unary_call.h",
         "include/grpc++/impl/codegen/core_codegen.h",
@@ -1172,6 +1231,7 @@
         "include/grpc++/impl/codegen/core_codegen_interface.h",
         "include/grpc++/impl/codegen/create_auth_context.h",
         "include/grpc++/impl/codegen/grpc_library.h",
+        "include/grpc++/impl/codegen/metadata_map.h",
         "include/grpc++/impl/codegen/method_handler_impl.h",
         "include/grpc++/impl/codegen/rpc_method.h",
         "include/grpc++/impl/codegen/rpc_service_method.h",
@@ -1180,6 +1240,7 @@
         "include/grpc++/impl/codegen/server_context.h",
         "include/grpc++/impl/codegen/server_interface.h",
         "include/grpc++/impl/codegen/service_type.h",
+        "include/grpc++/impl/codegen/slice.h",
         "include/grpc++/impl/codegen/status.h",
         "include/grpc++/impl/codegen/status_code_enum.h",
         "include/grpc++/impl/codegen/status_helper.h",
@@ -1218,6 +1279,9 @@
 
 grpc_cc_library(
     name = "grpc++_config_proto",
+    external_deps = [
+        "protobuf",
+    ],
     language = "c++",
     public_hdrs = [
         "include/grpc++/impl/codegen/config_protobuf.h",
@@ -1235,3 +1299,22 @@
         "grpc++_codegen_base",
     ],
 )
+
+grpc_cc_library(
+    name = "grpc++_reflection",
+    srcs = [
+        "src/cpp/ext/proto_server_reflection.cc",
+        "src/cpp/ext/proto_server_reflection_plugin.cc",
+    ],
+    hdrs = [
+        "src/cpp/ext/proto_server_reflection.h",
+    ],
+    language = "c++",
+    public_hdrs = [
+        "include/grpc++/ext/proto_server_reflection_plugin.h",
+    ],
+    deps = [
+        ":grpc++",
+        "//src/proto/grpc/reflection/v1alpha:reflection_proto",
+    ],
+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6951c33..94d578e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -42,7 +42,7 @@
 cmake_minimum_required(VERSION 2.8)
 
 set(PACKAGE_NAME      "grpc")
-set(PACKAGE_VERSION   "1.1.2")
+set(PACKAGE_VERSION   "1.2.0-dev")
 set(PACKAGE_STRING    "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 set(PACKAGE_TARNAME   "${PACKAGE_NAME}-${PACKAGE_VERSION}")
 set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
@@ -69,12 +69,29 @@
 set(gRPC_GFLAGS_PROVIDER "module" CACHE STRING "Provider of gflags library")
 set_property(CACHE gRPC_GFLAGS_PROVIDER PROPERTY STRINGS "module" "package")
 
+set(gRPC_BENCHMARK_PROVIDER "module" CACHE STRING "Provider of benchmark library")
+set_property(CACHE gRPC_BENCHMARK_PROVIDER PROPERTY STRINGS "module" "package")
+
 set(gRPC_USE_PROTO_LITE OFF CACHE BOOL "Use the protobuf-lite library")
 
+if(UNIX)
+  if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+    set(_gRPC_PLATFORM_LINUX ON)
+  elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+    set(_gRPC_PLATFORM_MAC ON)
+  else()
+    set(_gRPC_PLATFORM_POSIX ON)
+  endif()
+endif()
+if(WIN32)
+  set(_gRPC_PLATFORM_WINDOWS ON)
+endif()
+
+set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+
 if (MSVC)
+  include(cmake/msvc_static_runtime.cmake)
   add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS)
-  # needed to compile boringssl
-  add_definitions(/wd4464 /wd4623 /wd4668 /wd4701 /wd4702 /wd4777 /wd5027)
   # needed to compile protobuf
   add_definitions(/wd4065 /wd4506)
   # TODO(jtattermusch): revisit C4267 occurrences throughout the code
@@ -158,6 +175,7 @@
     set(BORINGSSL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/boringssl)
   endif()
   if(EXISTS "${BORINGSSL_ROOT_DIR}/CMakeLists.txt")
+    set(OPENSSL_NO_ASM ON)  # make boringssl buildable with Visual Studio
     add_subdirectory(${BORINGSSL_ROOT_DIR} third_party/boringssl)
     if(TARGET ssl)
       set(_gRPC_SSL_LIBRARIES ssl)
@@ -193,11 +211,35 @@
   set(_gRPC_FIND_GFLAGS "if(NOT gflags_FOUND)\n  find_package(gflags)\nendif()")
 endif()
 
+if("${gRPC_BENCHMARK_PROVIDER}" STREQUAL "module")
+  if(NOT BENCHMARK_ROOT_DIR)
+    set(BENCHMARK_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/benchmark)
+  endif()
+  if(EXISTS "${BENCHMARK_ROOT_DIR}/CMakeLists.txt")
+      add_subdirectory(${BENCHMARK_ROOT_DIR} third_party/benchmark)
+      if(TARGET benchmark)
+          set(_gRPC_BENCHMARK_LIBRARIES benchmark)
+      endif()
+  else()
+      message(WARNING "gRPC_BENCHMARK_PROVIDER is \"module\" but BENCHMARK_ROOT_DIR is wrong")
+  endif()
+elseif("${gRPC_BENCHMARK_PROVIDER}" STREQUAL "package")
+  find_package(benchmark)
+  if(TARGET benchmark::benchmark)
+    set(_gRPC_BENCHMARK_LIBRARIES benchmark::benchmark)
+  endif()
+  set(_gRPC_FIND_BENCHMARK "if(NOT benchmark_FOUND)\n  find_package(benchmark)\nendif()")
+endif()
+
 if(NOT MSVC)
-  set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -std=c11")
+  set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -std=c99")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 endif()
 
+if(UNIX)
+  set(_gRPC_ALLTARGETS_LIBRARIES dl rt m pthread)
+endif()
+
 if(WIN32 AND MSVC)
   set(_gRPC_BASELIB_LIBRARIES wsock32 ws2_32)
 endif()
@@ -256,6 +298,380 @@
   endforeach()
 endfunction()
 
+add_custom_target(plugins
+  DEPENDS
+  grpc_cpp_plugin
+  grpc_csharp_plugin
+  grpc_node_plugin
+  grpc_objective_c_plugin
+  grpc_php_plugin
+  grpc_python_plugin
+  grpc_ruby_plugin
+)
+
+add_custom_target(tools_c
+  DEPENDS
+  gen_hpack_tables
+  gen_legal_metadata_characters
+  gen_percent_encoding_tables
+  grpc_create_jwt
+  grpc_print_google_default_creds_token
+  grpc_verify_jwt
+)
+
+add_custom_target(tools_cxx
+  DEPENDS
+)
+
+add_custom_target(tools
+  DEPENDS tools_c tools_cxx)
+
+if (gRPC_BUILD_TESTS)
+add_custom_target(buildtests_c)
+add_dependencies(buildtests_c alarm_test)
+add_dependencies(buildtests_c algorithm_test)
+add_dependencies(buildtests_c alloc_test)
+add_dependencies(buildtests_c alpn_test)
+add_dependencies(buildtests_c bad_server_response_test)
+add_dependencies(buildtests_c bdp_estimator_test)
+add_dependencies(buildtests_c bin_decoder_test)
+add_dependencies(buildtests_c bin_encoder_test)
+add_dependencies(buildtests_c census_context_test)
+add_dependencies(buildtests_c census_resource_test)
+add_dependencies(buildtests_c census_trace_context_test)
+add_dependencies(buildtests_c channel_create_test)
+add_dependencies(buildtests_c chttp2_hpack_encoder_test)
+add_dependencies(buildtests_c chttp2_stream_map_test)
+add_dependencies(buildtests_c chttp2_varint_test)
+add_dependencies(buildtests_c combiner_test)
+add_dependencies(buildtests_c compression_test)
+add_dependencies(buildtests_c concurrent_connectivity_test)
+add_dependencies(buildtests_c connection_refused_test)
+add_dependencies(buildtests_c dns_resolver_connectivity_test)
+add_dependencies(buildtests_c dns_resolver_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c dualstack_socket_test)
+endif()
+add_dependencies(buildtests_c endpoint_pair_test)
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c ev_epoll_linux_test)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c fd_conservation_posix_test)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c fd_posix_test)
+endif()
+add_dependencies(buildtests_c fling_client)
+add_dependencies(buildtests_c fling_server)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c fling_stream_test)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c fling_test)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c goaway_server_test)
+endif()
+add_dependencies(buildtests_c gpr_avl_test)
+add_dependencies(buildtests_c gpr_backoff_test)
+add_dependencies(buildtests_c gpr_cmdline_test)
+add_dependencies(buildtests_c gpr_cpu_test)
+add_dependencies(buildtests_c gpr_env_test)
+add_dependencies(buildtests_c gpr_histogram_test)
+add_dependencies(buildtests_c gpr_host_port_test)
+add_dependencies(buildtests_c gpr_log_test)
+add_dependencies(buildtests_c gpr_mpscq_test)
+add_dependencies(buildtests_c gpr_spinlock_test)
+add_dependencies(buildtests_c gpr_stack_lockfree_test)
+add_dependencies(buildtests_c gpr_string_test)
+add_dependencies(buildtests_c gpr_sync_test)
+add_dependencies(buildtests_c gpr_thd_test)
+add_dependencies(buildtests_c gpr_time_test)
+add_dependencies(buildtests_c gpr_tls_test)
+add_dependencies(buildtests_c gpr_useful_test)
+add_dependencies(buildtests_c grpc_auth_context_test)
+add_dependencies(buildtests_c grpc_b64_test)
+add_dependencies(buildtests_c grpc_byte_buffer_reader_test)
+add_dependencies(buildtests_c grpc_channel_args_test)
+add_dependencies(buildtests_c grpc_channel_stack_test)
+add_dependencies(buildtests_c grpc_completion_queue_test)
+add_dependencies(buildtests_c grpc_completion_queue_threading_test)
+add_dependencies(buildtests_c grpc_credentials_test)
+add_dependencies(buildtests_c grpc_fetch_oauth2)
+add_dependencies(buildtests_c grpc_invalid_channel_args_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c grpc_json_token_test)
+endif()
+add_dependencies(buildtests_c grpc_jwt_verifier_test)
+add_dependencies(buildtests_c grpc_security_connector_test)
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c handshake_client)
+endif()
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c handshake_server)
+endif()
+add_dependencies(buildtests_c hpack_parser_test)
+add_dependencies(buildtests_c hpack_table_test)
+add_dependencies(buildtests_c http_parser_test)
+add_dependencies(buildtests_c httpcli_format_request_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c httpcli_test)
+endif()
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c httpscli_test)
+endif()
+add_dependencies(buildtests_c init_test)
+add_dependencies(buildtests_c invalid_call_argument_test)
+add_dependencies(buildtests_c json_rewrite)
+add_dependencies(buildtests_c json_rewrite_test)
+add_dependencies(buildtests_c json_stream_error_test)
+add_dependencies(buildtests_c json_test)
+add_dependencies(buildtests_c lame_client_test)
+add_dependencies(buildtests_c lb_policies_test)
+add_dependencies(buildtests_c load_file_test)
+add_dependencies(buildtests_c memory_profile_client)
+add_dependencies(buildtests_c memory_profile_server)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c memory_profile_test)
+endif()
+add_dependencies(buildtests_c message_compress_test)
+add_dependencies(buildtests_c mlog_test)
+add_dependencies(buildtests_c multiple_server_queues_test)
+add_dependencies(buildtests_c murmur_hash_test)
+add_dependencies(buildtests_c no_server_test)
+add_dependencies(buildtests_c percent_encoding_test)
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c pollset_set_test)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c resolve_address_posix_test)
+endif()
+add_dependencies(buildtests_c resolve_address_test)
+add_dependencies(buildtests_c resource_quota_test)
+add_dependencies(buildtests_c secure_channel_create_test)
+add_dependencies(buildtests_c secure_endpoint_test)
+add_dependencies(buildtests_c sequential_connectivity_test)
+add_dependencies(buildtests_c server_chttp2_test)
+add_dependencies(buildtests_c server_test)
+add_dependencies(buildtests_c set_initial_connect_string_test)
+add_dependencies(buildtests_c slice_buffer_test)
+add_dependencies(buildtests_c slice_string_helpers_test)
+add_dependencies(buildtests_c slice_test)
+add_dependencies(buildtests_c sockaddr_resolver_test)
+add_dependencies(buildtests_c sockaddr_utils_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c socket_utils_test)
+endif()
+add_dependencies(buildtests_c status_conversion_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c tcp_client_posix_test)
+endif()
+add_dependencies(buildtests_c tcp_client_uv_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c tcp_posix_test)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c tcp_server_posix_test)
+endif()
+add_dependencies(buildtests_c tcp_server_uv_test)
+add_dependencies(buildtests_c time_averaged_stats_test)
+add_dependencies(buildtests_c timeout_encoding_test)
+add_dependencies(buildtests_c timer_heap_test)
+add_dependencies(buildtests_c timer_list_test)
+add_dependencies(buildtests_c transport_connectivity_state_test)
+add_dependencies(buildtests_c transport_metadata_test)
+add_dependencies(buildtests_c transport_pid_controller_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c transport_security_test)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c udp_server_test)
+endif()
+add_dependencies(buildtests_c uri_parser_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c wakeup_fd_cv_test)
+endif()
+add_dependencies(buildtests_c public_headers_must_be_c89)
+add_dependencies(buildtests_c badreq_bad_client_test)
+add_dependencies(buildtests_c connection_prefix_bad_client_test)
+add_dependencies(buildtests_c head_of_line_blocking_bad_client_test)
+add_dependencies(buildtests_c headers_bad_client_test)
+add_dependencies(buildtests_c initial_settings_frame_bad_client_test)
+add_dependencies(buildtests_c large_metadata_bad_client_test)
+add_dependencies(buildtests_c server_registered_method_bad_client_test)
+add_dependencies(buildtests_c simple_request_bad_client_test)
+add_dependencies(buildtests_c unknown_frame_bad_client_test)
+add_dependencies(buildtests_c window_overflow_bad_client_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c bad_ssl_cert_server)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c bad_ssl_cert_test)
+endif()
+add_dependencies(buildtests_c h2_census_test)
+add_dependencies(buildtests_c h2_compress_test)
+add_dependencies(buildtests_c h2_fakesec_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c h2_fd_test)
+endif()
+add_dependencies(buildtests_c h2_full_test)
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c h2_full+pipe_test)
+endif()
+add_dependencies(buildtests_c h2_full+trace_test)
+add_dependencies(buildtests_c h2_http_proxy_test)
+add_dependencies(buildtests_c h2_load_reporting_test)
+add_dependencies(buildtests_c h2_oauth2_test)
+add_dependencies(buildtests_c h2_proxy_test)
+add_dependencies(buildtests_c h2_sockpair_test)
+add_dependencies(buildtests_c h2_sockpair+trace_test)
+add_dependencies(buildtests_c h2_sockpair_1byte_test)
+add_dependencies(buildtests_c h2_ssl_test)
+add_dependencies(buildtests_c h2_ssl_cert_test)
+add_dependencies(buildtests_c h2_ssl_proxy_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c h2_uds_test)
+endif()
+add_dependencies(buildtests_c h2_census_nosec_test)
+add_dependencies(buildtests_c h2_compress_nosec_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c h2_fd_nosec_test)
+endif()
+add_dependencies(buildtests_c h2_full_nosec_test)
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c h2_full+pipe_nosec_test)
+endif()
+add_dependencies(buildtests_c h2_full+trace_nosec_test)
+add_dependencies(buildtests_c h2_http_proxy_nosec_test)
+add_dependencies(buildtests_c h2_load_reporting_nosec_test)
+add_dependencies(buildtests_c h2_proxy_nosec_test)
+add_dependencies(buildtests_c h2_sockpair_nosec_test)
+add_dependencies(buildtests_c h2_sockpair+trace_nosec_test)
+add_dependencies(buildtests_c h2_sockpair_1byte_nosec_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_c h2_uds_nosec_test)
+endif()
+add_dependencies(buildtests_c api_fuzzer_one_entry)
+add_dependencies(buildtests_c client_fuzzer_one_entry)
+add_dependencies(buildtests_c hpack_parser_fuzzer_test_one_entry)
+add_dependencies(buildtests_c http_request_fuzzer_test_one_entry)
+add_dependencies(buildtests_c http_response_fuzzer_test_one_entry)
+add_dependencies(buildtests_c json_fuzzer_test_one_entry)
+add_dependencies(buildtests_c nanopb_fuzzer_response_test_one_entry)
+add_dependencies(buildtests_c nanopb_fuzzer_serverlist_test_one_entry)
+add_dependencies(buildtests_c percent_decode_fuzzer_one_entry)
+add_dependencies(buildtests_c percent_encode_fuzzer_one_entry)
+add_dependencies(buildtests_c server_fuzzer_one_entry)
+add_dependencies(buildtests_c ssl_server_fuzzer_one_entry)
+add_dependencies(buildtests_c uri_fuzzer_test_one_entry)
+
+add_custom_target(buildtests_cxx)
+add_dependencies(buildtests_cxx alarm_cpp_test)
+add_dependencies(buildtests_cxx async_end2end_test)
+add_dependencies(buildtests_cxx auth_property_iterator_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_call_create)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_chttp2_hpack)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_closure)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_cq)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_error)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_fullstack)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_metadata)
+endif()
+add_dependencies(buildtests_cxx channel_arguments_test)
+add_dependencies(buildtests_cxx channel_filter_test)
+add_dependencies(buildtests_cxx cli_call_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx client_crash_test)
+endif()
+add_dependencies(buildtests_cxx client_crash_test_server)
+add_dependencies(buildtests_cxx codegen_test_full)
+add_dependencies(buildtests_cxx codegen_test_minimal)
+add_dependencies(buildtests_cxx credentials_test)
+add_dependencies(buildtests_cxx cxx_byte_buffer_test)
+add_dependencies(buildtests_cxx cxx_slice_test)
+add_dependencies(buildtests_cxx cxx_string_ref_test)
+add_dependencies(buildtests_cxx cxx_time_test)
+add_dependencies(buildtests_cxx end2end_test)
+add_dependencies(buildtests_cxx filter_end2end_test)
+add_dependencies(buildtests_cxx generic_end2end_test)
+add_dependencies(buildtests_cxx golden_file_test)
+add_dependencies(buildtests_cxx grpc_cli)
+add_dependencies(buildtests_cxx grpc_tool_test)
+add_dependencies(buildtests_cxx grpclb_api_test)
+add_dependencies(buildtests_cxx grpclb_test)
+add_dependencies(buildtests_cxx health_service_end2end_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx http2_client)
+endif()
+add_dependencies(buildtests_cxx hybrid_end2end_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx interop_client)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx interop_server)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx interop_test)
+endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx json_run_localhost)
+endif()
+add_dependencies(buildtests_cxx metrics_client)
+add_dependencies(buildtests_cxx mock_test)
+add_dependencies(buildtests_cxx noop-benchmark)
+add_dependencies(buildtests_cxx proto_server_reflection_test)
+add_dependencies(buildtests_cxx proto_utils_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx qps_interarrival_test)
+endif()
+add_dependencies(buildtests_cxx qps_json_driver)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx qps_openloop_test)
+endif()
+add_dependencies(buildtests_cxx qps_worker)
+add_dependencies(buildtests_cxx reconnect_interop_client)
+add_dependencies(buildtests_cxx reconnect_interop_server)
+add_dependencies(buildtests_cxx round_robin_end2end_test)
+add_dependencies(buildtests_cxx secure_auth_context_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx secure_sync_unary_ping_pong_test)
+endif()
+add_dependencies(buildtests_cxx server_builder_plugin_test)
+add_dependencies(buildtests_cxx server_context_test_spouse_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx server_crash_test)
+endif()
+add_dependencies(buildtests_cxx server_crash_test_client)
+add_dependencies(buildtests_cxx shutdown_test)
+add_dependencies(buildtests_cxx status_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx streaming_throughput_test)
+endif()
+add_dependencies(buildtests_cxx stress_test)
+add_dependencies(buildtests_cxx thread_manager_test)
+add_dependencies(buildtests_cxx thread_stress_test)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx writes_per_rpc_test)
+endif()
+
+add_custom_target(buildtests
+  DEPENDS buildtests_c buildtests_cxx)
+endif (gRPC_BUILD_TESTS)
+
 
 add_library(gpr
   src/core/lib/profiling/basic_timers.c
@@ -304,6 +720,17 @@
   src/core/lib/support/wrap_memcpy.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(gpr PROPERTIES COMPILE_PDB_NAME "gpr"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/gpr.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(gpr
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -311,10 +738,14 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
+target_link_libraries(gpr
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+)
 
 foreach(_hdr
   include/grpc/support/alloc.h
@@ -378,6 +809,17 @@
   test/core/util/test_config.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(gpr_test_util PROPERTIES COMPILE_PDB_NAME "gpr_test_util"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/gpr_test_util.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(gpr_test_util
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -385,11 +827,13 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_test_util
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
 )
 
@@ -482,6 +926,8 @@
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
+  src/core/lib/slice/slice_intern.c
   src/core/lib/slice/slice_string_helpers.c
   src/core/lib/surface/alarm.c
   src/core/lib/surface/api_trace.c
@@ -501,14 +947,16 @@
   src/core/lib/surface/server.c
   src/core/lib/surface/validate_metadata.c
   src/core/lib/surface/version.c
+  src/core/lib/transport/bdp_estimator.c
   src/core/lib/transport/byte_stream.c
   src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/mdstr_hash_table.c
+  src/core/lib/transport/error_utils.c
   src/core/lib/transport/metadata.c
   src/core/lib/transport/metadata_batch.c
   src/core/lib/transport/pid_controller.c
   src/core/lib/transport/service_config.c
   src/core/lib/transport/static_metadata.c
+  src/core/lib/transport/status_conversion.c
   src/core/lib/transport/timeout_encoding.c
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport_op_string.c
@@ -529,7 +977,6 @@
   src/core/ext/transport/chttp2/transport/huffsyms.c
   src/core/ext/transport/chttp2/transport/incoming_metadata.c
   src/core/ext/transport/chttp2/transport/parsing.c
-  src/core/ext/transport/chttp2/transport/status_conversion.c
   src/core/ext/transport/chttp2/transport/stream_lists.c
   src/core/ext/transport/chttp2/transport/stream_map.c
   src/core/ext/transport/chttp2/transport/varint.c
@@ -551,6 +998,7 @@
   src/core/lib/security/credentials/plugin/plugin_credentials.c
   src/core/lib/security/credentials/ssl/ssl_credentials.c
   src/core/lib/security/transport/client_auth_filter.c
+  src/core/lib/security/transport/lb_targets_info.c
   src/core/lib/security/transport/secure_endpoint.c
   src/core/lib/security/transport/security_connector.c
   src/core/lib/security/transport/security_handshaker.c
@@ -571,11 +1019,14 @@
   src/core/ext/client_channel/connector.c
   src/core/ext/client_channel/default_initial_connect_string.c
   src/core/ext/client_channel/http_connect_handshaker.c
+  src/core/ext/client_channel/http_proxy.c
   src/core/ext/client_channel/initial_connect_string.c
   src/core/ext/client_channel/lb_policy.c
   src/core/ext/client_channel/lb_policy_factory.c
   src/core/ext/client_channel/lb_policy_registry.c
   src/core/ext/client_channel/parse_address.c
+  src/core/ext/client_channel/proxy_mapper.c
+  src/core/ext/client_channel/proxy_mapper_registry.c
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
@@ -588,6 +1039,7 @@
   src/core/ext/transport/chttp2/client/insecure/channel_create.c
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
   src/core/ext/lb_policy/grpclb/grpclb.c
+  src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c
   src/core/ext/lb_policy/grpclb/load_balancer_api.c
   src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
   third_party/nanopb/pb_common.c
@@ -616,6 +1068,17 @@
   src/core/plugin_registry/grpc_plugin_registry.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc PROPERTIES COMPILE_PDB_NAME "grpc"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -623,6 +1086,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
@@ -631,6 +1095,7 @@
   ${_gRPC_BASELIB_LIBRARIES}
   ${_gRPC_SSL_LIBRARIES}
   ${_gRPC_ZLIB_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
 )
 
@@ -641,6 +1106,7 @@
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
@@ -769,6 +1235,8 @@
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
+  src/core/lib/slice/slice_intern.c
   src/core/lib/slice/slice_string_helpers.c
   src/core/lib/surface/alarm.c
   src/core/lib/surface/api_trace.c
@@ -788,14 +1256,16 @@
   src/core/lib/surface/server.c
   src/core/lib/surface/validate_metadata.c
   src/core/lib/surface/version.c
+  src/core/lib/transport/bdp_estimator.c
   src/core/lib/transport/byte_stream.c
   src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/mdstr_hash_table.c
+  src/core/lib/transport/error_utils.c
   src/core/lib/transport/metadata.c
   src/core/lib/transport/metadata_batch.c
   src/core/lib/transport/pid_controller.c
   src/core/lib/transport/service_config.c
   src/core/lib/transport/static_metadata.c
+  src/core/lib/transport/status_conversion.c
   src/core/lib/transport/timeout_encoding.c
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport_op_string.c
@@ -819,7 +1289,6 @@
   src/core/ext/transport/chttp2/transport/huffsyms.c
   src/core/ext/transport/chttp2/transport/incoming_metadata.c
   src/core/ext/transport/chttp2/transport/parsing.c
-  src/core/ext/transport/chttp2/transport/status_conversion.c
   src/core/ext/transport/chttp2/transport/stream_lists.c
   src/core/ext/transport/chttp2/transport/stream_map.c
   src/core/ext/transport/chttp2/transport/varint.c
@@ -832,11 +1301,14 @@
   src/core/ext/client_channel/connector.c
   src/core/ext/client_channel/default_initial_connect_string.c
   src/core/ext/client_channel/http_connect_handshaker.c
+  src/core/ext/client_channel/http_proxy.c
   src/core/ext/client_channel/initial_connect_string.c
   src/core/ext/client_channel/lb_policy.c
   src/core/ext/client_channel/lb_policy_factory.c
   src/core/ext/client_channel/lb_policy_registry.c
   src/core/ext/client_channel/parse_address.c
+  src/core/ext/client_channel/proxy_mapper.c
+  src/core/ext/client_channel/proxy_mapper_registry.c
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
@@ -859,6 +1331,7 @@
   src/core/lib/security/credentials/plugin/plugin_credentials.c
   src/core/lib/security/credentials/ssl/ssl_credentials.c
   src/core/lib/security/transport/client_auth_filter.c
+  src/core/lib/security/transport/lb_targets_info.c
   src/core/lib/security/transport/secure_endpoint.c
   src/core/lib/security/transport/security_connector.c
   src/core/lib/security/transport/security_handshaker.c
@@ -871,9 +1344,22 @@
   src/core/lib/tsi/ssl_transport_security.c
   src/core/lib/tsi/transport_security.c
   src/core/ext/transport/chttp2/client/chttp2_connector.c
+  src/core/ext/load_reporting/load_reporting.c
+  src/core/ext/load_reporting/load_reporting_filter.c
   src/core/plugin_registry/grpc_cronet_plugin_registry.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc_cronet PROPERTIES COMPILE_PDB_NAME "grpc_cronet"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_cronet.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc_cronet
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -881,6 +1367,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
@@ -888,6 +1375,7 @@
 target_link_libraries(grpc_cronet
   ${_gRPC_BASELIB_LIBRARIES}
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
 )
 
@@ -898,6 +1386,7 @@
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
@@ -952,6 +1441,7 @@
   test/core/end2end/fixtures/http_proxy.c
   test/core/end2end/fixtures/proxy.c
   test/core/iomgr/endpoint_tests.c
+  test/core/util/debugger_macros.c
   test/core/util/grpc_profiler.c
   test/core/util/memory_counters.c
   test/core/util/mock_endpoint.c
@@ -962,6 +1452,7 @@
   test/core/util/port_uv.c
   test/core/util/port_windows.c
   test/core/util/slice_splitter.c
+  test/core/util/trickle_endpoint.c
   src/core/lib/channel/channel_args.c
   src/core/lib/channel/channel_stack.c
   src/core/lib/channel/channel_stack_builder.c
@@ -1046,6 +1537,8 @@
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
+  src/core/lib/slice/slice_intern.c
   src/core/lib/slice/slice_string_helpers.c
   src/core/lib/surface/alarm.c
   src/core/lib/surface/api_trace.c
@@ -1065,19 +1558,32 @@
   src/core/lib/surface/server.c
   src/core/lib/surface/validate_metadata.c
   src/core/lib/surface/version.c
+  src/core/lib/transport/bdp_estimator.c
   src/core/lib/transport/byte_stream.c
   src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/mdstr_hash_table.c
+  src/core/lib/transport/error_utils.c
   src/core/lib/transport/metadata.c
   src/core/lib/transport/metadata_batch.c
   src/core/lib/transport/pid_controller.c
   src/core/lib/transport/service_config.c
   src/core/lib/transport/static_metadata.c
+  src/core/lib/transport/status_conversion.c
   src/core/lib/transport/timeout_encoding.c
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport_op_string.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc_test_util PROPERTIES COMPILE_PDB_NAME "grpc_test_util"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_test_util.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc_test_util
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -1085,11 +1591,13 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_test_util
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
   grpc
@@ -1102,6 +1610,7 @@
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
@@ -1141,6 +1650,7 @@
   test/core/end2end/fixtures/http_proxy.c
   test/core/end2end/fixtures/proxy.c
   test/core/iomgr/endpoint_tests.c
+  test/core/util/debugger_macros.c
   test/core/util/grpc_profiler.c
   test/core/util/memory_counters.c
   test/core/util/mock_endpoint.c
@@ -1151,8 +1661,20 @@
   test/core/util/port_uv.c
   test/core/util/port_windows.c
   test/core/util/slice_splitter.c
+  test/core/util/trickle_endpoint.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc_test_util_unsecure PROPERTIES COMPILE_PDB_NAME "grpc_test_util_unsecure"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_test_util_unsecure.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc_test_util_unsecure
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -1160,11 +1682,13 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_test_util_unsecure
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
   gpr_test_util
   grpc_unsecure
@@ -1261,6 +1785,8 @@
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
+  src/core/lib/slice/slice_intern.c
   src/core/lib/slice/slice_string_helpers.c
   src/core/lib/surface/alarm.c
   src/core/lib/surface/api_trace.c
@@ -1280,14 +1806,16 @@
   src/core/lib/surface/server.c
   src/core/lib/surface/validate_metadata.c
   src/core/lib/surface/version.c
+  src/core/lib/transport/bdp_estimator.c
   src/core/lib/transport/byte_stream.c
   src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/mdstr_hash_table.c
+  src/core/lib/transport/error_utils.c
   src/core/lib/transport/metadata.c
   src/core/lib/transport/metadata_batch.c
   src/core/lib/transport/pid_controller.c
   src/core/lib/transport/service_config.c
   src/core/lib/transport/static_metadata.c
+  src/core/lib/transport/status_conversion.c
   src/core/lib/transport/timeout_encoding.c
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport_op_string.c
@@ -1309,7 +1837,6 @@
   src/core/ext/transport/chttp2/transport/huffsyms.c
   src/core/ext/transport/chttp2/transport/incoming_metadata.c
   src/core/ext/transport/chttp2/transport/parsing.c
-  src/core/ext/transport/chttp2/transport/status_conversion.c
   src/core/ext/transport/chttp2/transport/stream_lists.c
   src/core/ext/transport/chttp2/transport/stream_map.c
   src/core/ext/transport/chttp2/transport/varint.c
@@ -1326,11 +1853,14 @@
   src/core/ext/client_channel/connector.c
   src/core/ext/client_channel/default_initial_connect_string.c
   src/core/ext/client_channel/http_connect_handshaker.c
+  src/core/ext/client_channel/http_proxy.c
   src/core/ext/client_channel/initial_connect_string.c
   src/core/ext/client_channel/lb_policy.c
   src/core/ext/client_channel/lb_policy_factory.c
   src/core/ext/client_channel/lb_policy_registry.c
   src/core/ext/client_channel/parse_address.c
+  src/core/ext/client_channel/proxy_mapper.c
+  src/core/ext/client_channel/proxy_mapper_registry.c
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
@@ -1342,6 +1872,7 @@
   src/core/ext/load_reporting/load_reporting.c
   src/core/ext/load_reporting/load_reporting_filter.c
   src/core/ext/lb_policy/grpclb/grpclb.c
+  src/core/ext/lb_policy/grpclb/grpclb_channel.c
   src/core/ext/lb_policy/grpclb/load_balancer_api.c
   src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
   third_party/nanopb/pb_common.c
@@ -1366,6 +1897,17 @@
   src/core/plugin_registry/grpc_unsecure_plugin_registry.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc_unsecure PROPERTIES COMPILE_PDB_NAME "grpc_unsecure"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_unsecure.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc_unsecure
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -1373,12 +1915,14 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_unsecure
   ${_gRPC_BASELIB_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
 )
 
@@ -1389,6 +1933,7 @@
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
@@ -1435,6 +1980,17 @@
   test/core/util/reconnect_server.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(reconnect_server PROPERTIES COMPILE_PDB_NAME "reconnect_server"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/reconnect_server.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(reconnect_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -1442,11 +1998,13 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(reconnect_server
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   test_tcp_server
   grpc_test_util
   grpc
@@ -1462,6 +2020,17 @@
   test/core/util/test_tcp_server.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(test_tcp_server PROPERTIES COMPILE_PDB_NAME "test_tcp_server"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/test_tcp_server.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(test_tcp_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -1469,11 +2038,13 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(test_tcp_server
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -1509,6 +2080,10 @@
   src/cpp/server/async_generic_service.cc
   src/cpp/server/create_default_thread_pool.cc
   src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health.pb.c
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
   src/cpp/server/server_builder.cc
   src/cpp/server/server_cc.cc
   src/cpp/server/server_context.cc
@@ -1523,6 +2098,17 @@
   src/cpp/codegen/codegen_init.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc++ PROPERTIES COMPILE_PDB_NAME "grpc++"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc++
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -1530,14 +2116,17 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc++
   ${_gRPC_BASELIB_LIBRARIES}
   ${_gRPC_SSL_LIBRARIES}
   ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc
 )
 
@@ -1548,9 +2137,11 @@
   include/grpc++/completion_queue.h
   include/grpc++/create_channel.h
   include/grpc++/create_channel_posix.h
+  include/grpc++/ext/health_check_service_server_builder_option.h
   include/grpc++/generic/async_generic_service.h
   include/grpc++/generic/generic_stub.h
   include/grpc++/grpc++.h
+  include/grpc++/health_check_service_interface.h
   include/grpc++/impl/call.h
   include/grpc++/impl/client_unary_call.h
   include/grpc++/impl/codegen/core_codegen.h
@@ -1597,6 +2188,7 @@
   include/grpc++/impl/codegen/core_codegen_interface.h
   include/grpc++/impl/codegen/create_auth_context.h
   include/grpc++/impl/codegen/grpc_library.h
+  include/grpc++/impl/codegen/metadata_map.h
   include/grpc++/impl/codegen/method_handler_impl.h
   include/grpc++/impl/codegen/rpc_method.h
   include/grpc++/impl/codegen/rpc_service_method.h
@@ -1605,6 +2197,7 @@
   include/grpc++/impl/codegen/server_context.h
   include/grpc++/impl/codegen/server_interface.h
   include/grpc++/impl/codegen/service_type.h
+  include/grpc++/impl/codegen/slice.h
   include/grpc++/impl/codegen/status.h
   include/grpc++/impl/codegen/status_code_enum.h
   include/grpc++/impl/codegen/status_helper.h
@@ -1631,6 +2224,8 @@
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
+  include/grpc++/impl/codegen/proto_utils.h
+  include/grpc++/impl/codegen/config_protobuf.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
   get_filename_component(_path ${_path} PATH)
@@ -1671,6 +2266,10 @@
   src/cpp/server/async_generic_service.cc
   src/cpp/server/create_default_thread_pool.cc
   src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health.pb.c
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
   src/cpp/server/server_builder.cc
   src/cpp/server/server_cc.cc
   src/cpp/server/server_context.cc
@@ -1702,7 +2301,6 @@
   src/core/ext/transport/chttp2/transport/huffsyms.c
   src/core/ext/transport/chttp2/transport/incoming_metadata.c
   src/core/ext/transport/chttp2/transport/parsing.c
-  src/core/ext/transport/chttp2/transport/status_conversion.c
   src/core/ext/transport/chttp2/transport/stream_lists.c
   src/core/ext/transport/chttp2/transport/stream_map.c
   src/core/ext/transport/chttp2/transport/varint.c
@@ -1791,6 +2389,8 @@
   src/core/lib/slice/percent_encoding.c
   src/core/lib/slice/slice.c
   src/core/lib/slice/slice_buffer.c
+  src/core/lib/slice/slice_hash_table.c
+  src/core/lib/slice/slice_intern.c
   src/core/lib/slice/slice_string_helpers.c
   src/core/lib/surface/alarm.c
   src/core/lib/surface/api_trace.c
@@ -1810,14 +2410,16 @@
   src/core/lib/surface/server.c
   src/core/lib/surface/validate_metadata.c
   src/core/lib/surface/version.c
+  src/core/lib/transport/bdp_estimator.c
   src/core/lib/transport/byte_stream.c
   src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/mdstr_hash_table.c
+  src/core/lib/transport/error_utils.c
   src/core/lib/transport/metadata.c
   src/core/lib/transport/metadata_batch.c
   src/core/lib/transport/pid_controller.c
   src/core/lib/transport/service_config.c
   src/core/lib/transport/static_metadata.c
+  src/core/lib/transport/status_conversion.c
   src/core/lib/transport/timeout_encoding.c
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport_op_string.c
@@ -1829,11 +2431,14 @@
   src/core/ext/client_channel/connector.c
   src/core/ext/client_channel/default_initial_connect_string.c
   src/core/ext/client_channel/http_connect_handshaker.c
+  src/core/ext/client_channel/http_proxy.c
   src/core/ext/client_channel/initial_connect_string.c
   src/core/ext/client_channel/lb_policy.c
   src/core/ext/client_channel/lb_policy_factory.c
   src/core/ext/client_channel/lb_policy_registry.c
   src/core/ext/client_channel/parse_address.c
+  src/core/ext/client_channel/proxy_mapper.c
+  src/core/ext/client_channel/proxy_mapper_registry.c
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
@@ -1862,6 +2467,17 @@
   third_party/nanopb/pb_encode.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc++_cronet PROPERTIES COMPILE_PDB_NAME "grpc++_cronet"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_cronet.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc++_cronet
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -1869,13 +2485,17 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc++_cronet
   ${_gRPC_BASELIB_LIBRARIES}
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
   grpc_cronet
 )
@@ -1887,9 +2507,11 @@
   include/grpc++/completion_queue.h
   include/grpc++/create_channel.h
   include/grpc++/create_channel_posix.h
+  include/grpc++/ext/health_check_service_server_builder_option.h
   include/grpc++/generic/async_generic_service.h
   include/grpc++/generic/generic_stub.h
   include/grpc++/grpc++.h
+  include/grpc++/health_check_service_interface.h
   include/grpc++/impl/call.h
   include/grpc++/impl/client_unary_call.h
   include/grpc++/impl/codegen/core_codegen.h
@@ -1936,6 +2558,7 @@
   include/grpc++/impl/codegen/core_codegen_interface.h
   include/grpc++/impl/codegen/create_auth_context.h
   include/grpc++/impl/codegen/grpc_library.h
+  include/grpc++/impl/codegen/metadata_map.h
   include/grpc++/impl/codegen/method_handler_impl.h
   include/grpc++/impl/codegen/rpc_method.h
   include/grpc++/impl/codegen/rpc_service_method.h
@@ -1944,6 +2567,7 @@
   include/grpc++/impl/codegen/server_context.h
   include/grpc++/impl/codegen/server_interface.h
   include/grpc++/impl/codegen/service_type.h
+  include/grpc++/impl/codegen/slice.h
   include/grpc++/impl/codegen/status.h
   include/grpc++/impl/codegen/status_code_enum.h
   include/grpc++/impl/codegen/status_helper.h
@@ -1976,6 +2600,7 @@
   include/grpc/grpc.h
   include/grpc/grpc_posix.h
   include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
   include/grpc/slice.h
   include/grpc/slice_buffer.h
   include/grpc/status.h
@@ -2007,6 +2632,17 @@
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc++_proto_reflection_desc_db PROPERTIES COMPILE_PDB_NAME "grpc++_proto_reflection_desc_db"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_proto_reflection_desc_db.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 protobuf_generate_grpc_cpp(
   src/proto/grpc/reflection/v1alpha/reflection.proto
 )
@@ -2017,6 +2653,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
@@ -2025,6 +2662,8 @@
 )
 
 target_link_libraries(grpc++_proto_reflection_desc_db
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
 )
 
@@ -2049,6 +2688,17 @@
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc++_reflection PROPERTIES COMPILE_PDB_NAME "grpc++_reflection"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_reflection.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 protobuf_generate_grpc_cpp(
   src/proto/grpc/reflection/v1alpha/reflection.proto
 )
@@ -2059,12 +2709,15 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc++_reflection
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
 )
 
@@ -2089,35 +2742,21 @@
 
 if (gRPC_BUILD_TESTS)
 
-add_library(grpc++_test
-  src/cpp/test/server_context_test_spouse.cc
-)
-
-
-target_include_directories(grpc++_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(grpc++_test
-  grpc++
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
 add_library(grpc++_test_config
   test/cpp/util/test_config_cc.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc++_test_config PROPERTIES COMPILE_PDB_NAME "grpc++_test_config"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_test_config.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc++_test_config
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -2125,18 +2764,28 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
+target_link_libraries(grpc++_test_config
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+)
 
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 add_library(grpc++_test_util
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
@@ -2158,6 +2807,20 @@
   src/cpp/codegen/codegen_init.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc++_test_util PROPERTIES COMPILE_PDB_NAME "grpc++_test_util"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_test_util.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/health/v1/health.proto
+)
 protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/echo_messages.proto
 )
@@ -2174,6 +2837,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
@@ -2182,6 +2846,8 @@
 )
 
 target_link_libraries(grpc++_test_util
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   grpc_test_util
 )
@@ -2200,6 +2866,7 @@
   include/grpc++/impl/codegen/core_codegen_interface.h
   include/grpc++/impl/codegen/create_auth_context.h
   include/grpc++/impl/codegen/grpc_library.h
+  include/grpc++/impl/codegen/metadata_map.h
   include/grpc++/impl/codegen/method_handler_impl.h
   include/grpc++/impl/codegen/rpc_method.h
   include/grpc++/impl/codegen/rpc_service_method.h
@@ -2208,6 +2875,7 @@
   include/grpc++/impl/codegen/server_context.h
   include/grpc++/impl/codegen/server_interface.h
   include/grpc++/impl/codegen/service_type.h
+  include/grpc++/impl/codegen/slice.h
   include/grpc++/impl/codegen/status.h
   include/grpc++/impl/codegen/status_code_enum.h
   include/grpc++/impl/codegen/status_helper.h
@@ -2269,6 +2937,10 @@
   src/cpp/server/async_generic_service.cc
   src/cpp/server/create_default_thread_pool.cc
   src/cpp/server/dynamic_thread_pool.cc
+  src/cpp/server/health/default_health_check_service.cc
+  src/cpp/server/health/health.pb.c
+  src/cpp/server/health/health_check_service.cc
+  src/cpp/server/health/health_check_service_server_builder_option.cc
   src/cpp/server/server_builder.cc
   src/cpp/server/server_cc.cc
   src/cpp/server/server_context.cc
@@ -2283,6 +2955,17 @@
   src/cpp/codegen/codegen_init.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc++_unsecure PROPERTIES COMPILE_PDB_NAME "grpc++_unsecure"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_unsecure.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc++_unsecure
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -2290,13 +2973,16 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc++_unsecure
   ${_gRPC_BASELIB_LIBRARIES}
   ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
   grpc_unsecure
 )
@@ -2308,9 +2994,11 @@
   include/grpc++/completion_queue.h
   include/grpc++/create_channel.h
   include/grpc++/create_channel_posix.h
+  include/grpc++/ext/health_check_service_server_builder_option.h
   include/grpc++/generic/async_generic_service.h
   include/grpc++/generic/generic_stub.h
   include/grpc++/grpc++.h
+  include/grpc++/health_check_service_interface.h
   include/grpc++/impl/call.h
   include/grpc++/impl/client_unary_call.h
   include/grpc++/impl/codegen/core_codegen.h
@@ -2357,6 +3045,7 @@
   include/grpc++/impl/codegen/core_codegen_interface.h
   include/grpc++/impl/codegen/create_auth_context.h
   include/grpc++/impl/codegen/grpc_library.h
+  include/grpc++/impl/codegen/metadata_map.h
   include/grpc++/impl/codegen/method_handler_impl.h
   include/grpc++/impl/codegen/rpc_method.h
   include/grpc++/impl/codegen/rpc_service_method.h
@@ -2365,6 +3054,7 @@
   include/grpc++/impl/codegen/server_context.h
   include/grpc++/impl/codegen/server_interface.h
   include/grpc++/impl/codegen/service_type.h
+  include/grpc++/impl/codegen/slice.h
   include/grpc++/impl/codegen/status.h
   include/grpc++/impl/codegen/status_code_enum.h
   include/grpc++/impl/codegen/status_helper.h
@@ -2422,6 +3112,17 @@
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc_cli_libs PROPERTIES COMPILE_PDB_NAME "grpc_cli_libs"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_cli_libs.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 protobuf_generate_grpc_cpp(
   src/proto/grpc/reflection/v1alpha/reflection.proto
 )
@@ -2432,6 +3133,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
@@ -2440,6 +3142,8 @@
 )
 
 target_link_libraries(grpc_cli_libs
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_proto_reflection_desc_db
   grpc++
 )
@@ -2466,6 +3170,17 @@
   src/compiler/ruby_generator.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc_plugin_support PROPERTIES COMPILE_PDB_NAME "grpc_plugin_support"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_plugin_support.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(grpc_plugin_support
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -2473,12 +3188,16 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_plugin_support
   ${_gRPC_PROTOBUF_PROTOC_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
 )
 
 foreach(_hdr
@@ -2518,6 +3237,17 @@
   test/cpp/interop/http2_client.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(http2_client_main PROPERTIES COMPILE_PDB_NAME "http2_client_main"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/http2_client_main.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/empty.proto
 )
@@ -2534,6 +3264,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
@@ -2542,6 +3273,8 @@
 )
 
 target_link_libraries(http2_client_main
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -2561,6 +3294,17 @@
   test/cpp/interop/client_helper.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(interop_client_helper PROPERTIES COMPILE_PDB_NAME "interop_client_helper"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_client_helper.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/messages.proto
 )
@@ -2571,6 +3315,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
@@ -2579,6 +3324,8 @@
 )
 
 target_link_libraries(interop_client_helper
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -2607,6 +3354,17 @@
   test/cpp/interop/interop_client.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(interop_client_main PROPERTIES COMPILE_PDB_NAME "interop_client_main"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_client_main.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/empty.proto
 )
@@ -2623,6 +3381,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
@@ -2631,6 +3390,8 @@
 )
 
 target_link_libraries(interop_client_main
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   interop_client_helper
   grpc++_test_util
   grpc_test_util
@@ -2649,6 +3410,17 @@
   test/cpp/interop/server_helper.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(interop_server_helper PROPERTIES COMPILE_PDB_NAME "interop_server_helper"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_helper.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(interop_server_helper
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -2656,13 +3428,17 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(interop_server_helper
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -2690,6 +3466,17 @@
   test/cpp/interop/interop_server.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(interop_server_lib PROPERTIES COMPILE_PDB_NAME "interop_server_lib"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_lib.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/empty.proto
 )
@@ -2706,6 +3493,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
@@ -2714,6 +3502,8 @@
 )
 
 target_link_libraries(interop_server_lib
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   interop_server_helper
   grpc++_test_util
   grpc_test_util
@@ -2732,6 +3522,17 @@
   test/cpp/interop/interop_server_bootstrap.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(interop_server_main PROPERTIES COMPILE_PDB_NAME "interop_server_main"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_main.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(interop_server_main
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -2739,13 +3540,17 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(interop_server_main
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   interop_server_lib
 )
 
@@ -2786,6 +3591,17 @@
   test/cpp/util/benchmark_config.cc
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(qps PROPERTIES COMPILE_PDB_NAME "qps"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qps.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/messages.proto
 )
@@ -2808,6 +3624,7 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
@@ -2816,6 +3633,8 @@
 )
 
 target_link_libraries(qps
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc++_test_util
   grpc++
@@ -2823,1661 +3642,67 @@
 
 
 endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
 
-add_library(boringssl
-  src/boringssl/err_data.c
-  third_party/boringssl/crypto/aes/aes.c
-  third_party/boringssl/crypto/aes/mode_wrappers.c
-  third_party/boringssl/crypto/asn1/a_bitstr.c
-  third_party/boringssl/crypto/asn1/a_bool.c
-  third_party/boringssl/crypto/asn1/a_d2i_fp.c
-  third_party/boringssl/crypto/asn1/a_dup.c
-  third_party/boringssl/crypto/asn1/a_enum.c
-  third_party/boringssl/crypto/asn1/a_gentm.c
-  third_party/boringssl/crypto/asn1/a_i2d_fp.c
-  third_party/boringssl/crypto/asn1/a_int.c
-  third_party/boringssl/crypto/asn1/a_mbstr.c
-  third_party/boringssl/crypto/asn1/a_object.c
-  third_party/boringssl/crypto/asn1/a_octet.c
-  third_party/boringssl/crypto/asn1/a_print.c
-  third_party/boringssl/crypto/asn1/a_strnid.c
-  third_party/boringssl/crypto/asn1/a_time.c
-  third_party/boringssl/crypto/asn1/a_type.c
-  third_party/boringssl/crypto/asn1/a_utctm.c
-  third_party/boringssl/crypto/asn1/a_utf8.c
-  third_party/boringssl/crypto/asn1/asn1_lib.c
-  third_party/boringssl/crypto/asn1/asn1_par.c
-  third_party/boringssl/crypto/asn1/asn_pack.c
-  third_party/boringssl/crypto/asn1/f_enum.c
-  third_party/boringssl/crypto/asn1/f_int.c
-  third_party/boringssl/crypto/asn1/f_string.c
-  third_party/boringssl/crypto/asn1/t_bitst.c
-  third_party/boringssl/crypto/asn1/tasn_dec.c
-  third_party/boringssl/crypto/asn1/tasn_enc.c
-  third_party/boringssl/crypto/asn1/tasn_fre.c
-  third_party/boringssl/crypto/asn1/tasn_new.c
-  third_party/boringssl/crypto/asn1/tasn_typ.c
-  third_party/boringssl/crypto/asn1/tasn_utl.c
-  third_party/boringssl/crypto/asn1/x_bignum.c
-  third_party/boringssl/crypto/asn1/x_long.c
-  third_party/boringssl/crypto/base64/base64.c
-  third_party/boringssl/crypto/bio/bio.c
-  third_party/boringssl/crypto/bio/bio_mem.c
-  third_party/boringssl/crypto/bio/buffer.c
-  third_party/boringssl/crypto/bio/connect.c
-  third_party/boringssl/crypto/bio/fd.c
-  third_party/boringssl/crypto/bio/file.c
-  third_party/boringssl/crypto/bio/hexdump.c
-  third_party/boringssl/crypto/bio/pair.c
-  third_party/boringssl/crypto/bio/printf.c
-  third_party/boringssl/crypto/bio/socket.c
-  third_party/boringssl/crypto/bio/socket_helper.c
-  third_party/boringssl/crypto/bn/add.c
-  third_party/boringssl/crypto/bn/asm/x86_64-gcc.c
-  third_party/boringssl/crypto/bn/bn.c
-  third_party/boringssl/crypto/bn/bn_asn1.c
-  third_party/boringssl/crypto/bn/cmp.c
-  third_party/boringssl/crypto/bn/convert.c
-  third_party/boringssl/crypto/bn/ctx.c
-  third_party/boringssl/crypto/bn/div.c
-  third_party/boringssl/crypto/bn/exponentiation.c
-  third_party/boringssl/crypto/bn/gcd.c
-  third_party/boringssl/crypto/bn/generic.c
-  third_party/boringssl/crypto/bn/kronecker.c
-  third_party/boringssl/crypto/bn/montgomery.c
-  third_party/boringssl/crypto/bn/montgomery_inv.c
-  third_party/boringssl/crypto/bn/mul.c
-  third_party/boringssl/crypto/bn/prime.c
-  third_party/boringssl/crypto/bn/random.c
-  third_party/boringssl/crypto/bn/rsaz_exp.c
-  third_party/boringssl/crypto/bn/shift.c
-  third_party/boringssl/crypto/bn/sqrt.c
-  third_party/boringssl/crypto/buf/buf.c
-  third_party/boringssl/crypto/bytestring/asn1_compat.c
-  third_party/boringssl/crypto/bytestring/ber.c
-  third_party/boringssl/crypto/bytestring/cbb.c
-  third_party/boringssl/crypto/bytestring/cbs.c
-  third_party/boringssl/crypto/chacha/chacha.c
-  third_party/boringssl/crypto/cipher/aead.c
-  third_party/boringssl/crypto/cipher/cipher.c
-  third_party/boringssl/crypto/cipher/derive_key.c
-  third_party/boringssl/crypto/cipher/e_aes.c
-  third_party/boringssl/crypto/cipher/e_chacha20poly1305.c
-  third_party/boringssl/crypto/cipher/e_des.c
-  third_party/boringssl/crypto/cipher/e_null.c
-  third_party/boringssl/crypto/cipher/e_rc2.c
-  third_party/boringssl/crypto/cipher/e_rc4.c
-  third_party/boringssl/crypto/cipher/e_ssl3.c
-  third_party/boringssl/crypto/cipher/e_tls.c
-  third_party/boringssl/crypto/cipher/tls_cbc.c
-  third_party/boringssl/crypto/cmac/cmac.c
-  third_party/boringssl/crypto/conf/conf.c
-  third_party/boringssl/crypto/cpu-aarch64-linux.c
-  third_party/boringssl/crypto/cpu-arm-linux.c
-  third_party/boringssl/crypto/cpu-arm.c
-  third_party/boringssl/crypto/cpu-intel.c
-  third_party/boringssl/crypto/cpu-ppc64le.c
-  third_party/boringssl/crypto/crypto.c
-  third_party/boringssl/crypto/curve25519/curve25519.c
-  third_party/boringssl/crypto/curve25519/spake25519.c
-  third_party/boringssl/crypto/curve25519/x25519-x86_64.c
-  third_party/boringssl/crypto/des/des.c
-  third_party/boringssl/crypto/dh/check.c
-  third_party/boringssl/crypto/dh/dh.c
-  third_party/boringssl/crypto/dh/dh_asn1.c
-  third_party/boringssl/crypto/dh/params.c
-  third_party/boringssl/crypto/digest/digest.c
-  third_party/boringssl/crypto/digest/digests.c
-  third_party/boringssl/crypto/dsa/dsa.c
-  third_party/boringssl/crypto/dsa/dsa_asn1.c
-  third_party/boringssl/crypto/ec/ec.c
-  third_party/boringssl/crypto/ec/ec_asn1.c
-  third_party/boringssl/crypto/ec/ec_key.c
-  third_party/boringssl/crypto/ec/ec_montgomery.c
-  third_party/boringssl/crypto/ec/oct.c
-  third_party/boringssl/crypto/ec/p224-64.c
-  third_party/boringssl/crypto/ec/p256-64.c
-  third_party/boringssl/crypto/ec/p256-x86_64.c
-  third_party/boringssl/crypto/ec/simple.c
-  third_party/boringssl/crypto/ec/util-64.c
-  third_party/boringssl/crypto/ec/wnaf.c
-  third_party/boringssl/crypto/ecdh/ecdh.c
-  third_party/boringssl/crypto/ecdsa/ecdsa.c
-  third_party/boringssl/crypto/ecdsa/ecdsa_asn1.c
-  third_party/boringssl/crypto/engine/engine.c
-  third_party/boringssl/crypto/err/err.c
-  third_party/boringssl/crypto/evp/digestsign.c
-  third_party/boringssl/crypto/evp/evp.c
-  third_party/boringssl/crypto/evp/evp_asn1.c
-  third_party/boringssl/crypto/evp/evp_ctx.c
-  third_party/boringssl/crypto/evp/p_dsa_asn1.c
-  third_party/boringssl/crypto/evp/p_ec.c
-  third_party/boringssl/crypto/evp/p_ec_asn1.c
-  third_party/boringssl/crypto/evp/p_rsa.c
-  third_party/boringssl/crypto/evp/p_rsa_asn1.c
-  third_party/boringssl/crypto/evp/pbkdf.c
-  third_party/boringssl/crypto/evp/print.c
-  third_party/boringssl/crypto/evp/sign.c
-  third_party/boringssl/crypto/ex_data.c
-  third_party/boringssl/crypto/hkdf/hkdf.c
-  third_party/boringssl/crypto/hmac/hmac.c
-  third_party/boringssl/crypto/lhash/lhash.c
-  third_party/boringssl/crypto/md4/md4.c
-  third_party/boringssl/crypto/md5/md5.c
-  third_party/boringssl/crypto/mem.c
-  third_party/boringssl/crypto/modes/cbc.c
-  third_party/boringssl/crypto/modes/cfb.c
-  third_party/boringssl/crypto/modes/ctr.c
-  third_party/boringssl/crypto/modes/gcm.c
-  third_party/boringssl/crypto/modes/ofb.c
-  third_party/boringssl/crypto/newhope/error_correction.c
-  third_party/boringssl/crypto/newhope/newhope.c
-  third_party/boringssl/crypto/newhope/ntt.c
-  third_party/boringssl/crypto/newhope/poly.c
-  third_party/boringssl/crypto/newhope/precomp.c
-  third_party/boringssl/crypto/newhope/reduce.c
-  third_party/boringssl/crypto/obj/obj.c
-  third_party/boringssl/crypto/obj/obj_xref.c
-  third_party/boringssl/crypto/pem/pem_all.c
-  third_party/boringssl/crypto/pem/pem_info.c
-  third_party/boringssl/crypto/pem/pem_lib.c
-  third_party/boringssl/crypto/pem/pem_oth.c
-  third_party/boringssl/crypto/pem/pem_pk8.c
-  third_party/boringssl/crypto/pem/pem_pkey.c
-  third_party/boringssl/crypto/pem/pem_x509.c
-  third_party/boringssl/crypto/pem/pem_xaux.c
-  third_party/boringssl/crypto/pkcs8/p5_pbe.c
-  third_party/boringssl/crypto/pkcs8/p5_pbev2.c
-  third_party/boringssl/crypto/pkcs8/p8_pkey.c
-  third_party/boringssl/crypto/pkcs8/pkcs8.c
-  third_party/boringssl/crypto/poly1305/poly1305.c
-  third_party/boringssl/crypto/poly1305/poly1305_arm.c
-  third_party/boringssl/crypto/poly1305/poly1305_vec.c
-  third_party/boringssl/crypto/rand/deterministic.c
-  third_party/boringssl/crypto/rand/rand.c
-  third_party/boringssl/crypto/rand/urandom.c
-  third_party/boringssl/crypto/rand/windows.c
-  third_party/boringssl/crypto/rc4/rc4.c
-  third_party/boringssl/crypto/refcount_c11.c
-  third_party/boringssl/crypto/refcount_lock.c
-  third_party/boringssl/crypto/rsa/blinding.c
-  third_party/boringssl/crypto/rsa/padding.c
-  third_party/boringssl/crypto/rsa/rsa.c
-  third_party/boringssl/crypto/rsa/rsa_asn1.c
-  third_party/boringssl/crypto/rsa/rsa_impl.c
-  third_party/boringssl/crypto/sha/sha1.c
-  third_party/boringssl/crypto/sha/sha256.c
-  third_party/boringssl/crypto/sha/sha512.c
-  third_party/boringssl/crypto/stack/stack.c
-  third_party/boringssl/crypto/thread.c
-  third_party/boringssl/crypto/thread_none.c
-  third_party/boringssl/crypto/thread_pthread.c
-  third_party/boringssl/crypto/thread_win.c
-  third_party/boringssl/crypto/time_support.c
-  third_party/boringssl/crypto/x509/a_digest.c
-  third_party/boringssl/crypto/x509/a_sign.c
-  third_party/boringssl/crypto/x509/a_strex.c
-  third_party/boringssl/crypto/x509/a_verify.c
-  third_party/boringssl/crypto/x509/algorithm.c
-  third_party/boringssl/crypto/x509/asn1_gen.c
-  third_party/boringssl/crypto/x509/by_dir.c
-  third_party/boringssl/crypto/x509/by_file.c
-  third_party/boringssl/crypto/x509/i2d_pr.c
-  third_party/boringssl/crypto/x509/pkcs7.c
-  third_party/boringssl/crypto/x509/rsa_pss.c
-  third_party/boringssl/crypto/x509/t_crl.c
-  third_party/boringssl/crypto/x509/t_req.c
-  third_party/boringssl/crypto/x509/t_x509.c
-  third_party/boringssl/crypto/x509/t_x509a.c
-  third_party/boringssl/crypto/x509/x509.c
-  third_party/boringssl/crypto/x509/x509_att.c
-  third_party/boringssl/crypto/x509/x509_cmp.c
-  third_party/boringssl/crypto/x509/x509_d2.c
-  third_party/boringssl/crypto/x509/x509_def.c
-  third_party/boringssl/crypto/x509/x509_ext.c
-  third_party/boringssl/crypto/x509/x509_lu.c
-  third_party/boringssl/crypto/x509/x509_obj.c
-  third_party/boringssl/crypto/x509/x509_r2x.c
-  third_party/boringssl/crypto/x509/x509_req.c
-  third_party/boringssl/crypto/x509/x509_set.c
-  third_party/boringssl/crypto/x509/x509_trs.c
-  third_party/boringssl/crypto/x509/x509_txt.c
-  third_party/boringssl/crypto/x509/x509_v3.c
-  third_party/boringssl/crypto/x509/x509_vfy.c
-  third_party/boringssl/crypto/x509/x509_vpm.c
-  third_party/boringssl/crypto/x509/x509cset.c
-  third_party/boringssl/crypto/x509/x509name.c
-  third_party/boringssl/crypto/x509/x509rset.c
-  third_party/boringssl/crypto/x509/x509spki.c
-  third_party/boringssl/crypto/x509/x509type.c
-  third_party/boringssl/crypto/x509/x_algor.c
-  third_party/boringssl/crypto/x509/x_all.c
-  third_party/boringssl/crypto/x509/x_attrib.c
-  third_party/boringssl/crypto/x509/x_crl.c
-  third_party/boringssl/crypto/x509/x_exten.c
-  third_party/boringssl/crypto/x509/x_info.c
-  third_party/boringssl/crypto/x509/x_name.c
-  third_party/boringssl/crypto/x509/x_pkey.c
-  third_party/boringssl/crypto/x509/x_pubkey.c
-  third_party/boringssl/crypto/x509/x_req.c
-  third_party/boringssl/crypto/x509/x_sig.c
-  third_party/boringssl/crypto/x509/x_spki.c
-  third_party/boringssl/crypto/x509/x_val.c
-  third_party/boringssl/crypto/x509/x_x509.c
-  third_party/boringssl/crypto/x509/x_x509a.c
-  third_party/boringssl/crypto/x509v3/pcy_cache.c
-  third_party/boringssl/crypto/x509v3/pcy_data.c
-  third_party/boringssl/crypto/x509v3/pcy_lib.c
-  third_party/boringssl/crypto/x509v3/pcy_map.c
-  third_party/boringssl/crypto/x509v3/pcy_node.c
-  third_party/boringssl/crypto/x509v3/pcy_tree.c
-  third_party/boringssl/crypto/x509v3/v3_akey.c
-  third_party/boringssl/crypto/x509v3/v3_akeya.c
-  third_party/boringssl/crypto/x509v3/v3_alt.c
-  third_party/boringssl/crypto/x509v3/v3_bcons.c
-  third_party/boringssl/crypto/x509v3/v3_bitst.c
-  third_party/boringssl/crypto/x509v3/v3_conf.c
-  third_party/boringssl/crypto/x509v3/v3_cpols.c
-  third_party/boringssl/crypto/x509v3/v3_crld.c
-  third_party/boringssl/crypto/x509v3/v3_enum.c
-  third_party/boringssl/crypto/x509v3/v3_extku.c
-  third_party/boringssl/crypto/x509v3/v3_genn.c
-  third_party/boringssl/crypto/x509v3/v3_ia5.c
-  third_party/boringssl/crypto/x509v3/v3_info.c
-  third_party/boringssl/crypto/x509v3/v3_int.c
-  third_party/boringssl/crypto/x509v3/v3_lib.c
-  third_party/boringssl/crypto/x509v3/v3_ncons.c
-  third_party/boringssl/crypto/x509v3/v3_pci.c
-  third_party/boringssl/crypto/x509v3/v3_pcia.c
-  third_party/boringssl/crypto/x509v3/v3_pcons.c
-  third_party/boringssl/crypto/x509v3/v3_pku.c
-  third_party/boringssl/crypto/x509v3/v3_pmaps.c
-  third_party/boringssl/crypto/x509v3/v3_prn.c
-  third_party/boringssl/crypto/x509v3/v3_purp.c
-  third_party/boringssl/crypto/x509v3/v3_skey.c
-  third_party/boringssl/crypto/x509v3/v3_sxnet.c
-  third_party/boringssl/crypto/x509v3/v3_utl.c
-  third_party/boringssl/ssl/custom_extensions.c
-  third_party/boringssl/ssl/d1_both.c
-  third_party/boringssl/ssl/d1_lib.c
-  third_party/boringssl/ssl/d1_pkt.c
-  third_party/boringssl/ssl/d1_srtp.c
-  third_party/boringssl/ssl/dtls_method.c
-  third_party/boringssl/ssl/dtls_record.c
-  third_party/boringssl/ssl/handshake_client.c
-  third_party/boringssl/ssl/handshake_server.c
-  third_party/boringssl/ssl/s3_both.c
-  third_party/boringssl/ssl/s3_enc.c
-  third_party/boringssl/ssl/s3_lib.c
-  third_party/boringssl/ssl/s3_pkt.c
-  third_party/boringssl/ssl/ssl_aead_ctx.c
-  third_party/boringssl/ssl/ssl_asn1.c
-  third_party/boringssl/ssl/ssl_buffer.c
-  third_party/boringssl/ssl/ssl_cert.c
-  third_party/boringssl/ssl/ssl_cipher.c
-  third_party/boringssl/ssl/ssl_ecdh.c
-  third_party/boringssl/ssl/ssl_file.c
-  third_party/boringssl/ssl/ssl_lib.c
-  third_party/boringssl/ssl/ssl_rsa.c
-  third_party/boringssl/ssl/ssl_session.c
-  third_party/boringssl/ssl/ssl_stat.c
-  third_party/boringssl/ssl/t1_enc.c
-  third_party/boringssl/ssl/t1_lib.c
-  third_party/boringssl/ssl/tls13_both.c
-  third_party/boringssl/ssl/tls13_client.c
-  third_party/boringssl/ssl/tls13_enc.c
-  third_party/boringssl/ssl/tls13_server.c
-  third_party/boringssl/ssl/tls_method.c
-  third_party/boringssl/ssl/tls_record.c
+add_library(grpc_csharp_ext SHARED
+  src/csharp/ext/grpc_csharp_ext.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(grpc_csharp_ext PROPERTIES COMPILE_PDB_NAME "grpc_csharp_ext"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_csharp_ext.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
 
-target_include_directories(boringssl
+
+target_include_directories(grpc_csharp_ext
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
-target_link_libraries(boringssl
-  ${_gRPC_SSL_LIBRARIES}
+target_link_libraries(grpc_csharp_ext
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc
+  gpr
 )
 
 
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
 
-add_library(boringssl_test_util
-  third_party/boringssl/crypto/test/file_test.cc
-  third_party/boringssl/crypto/test/malloc.cc
-  third_party/boringssl/crypto/test/test_util.cc
-)
-
-
-target_include_directories(boringssl_test_util
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_test_util
-  ${_gRPC_SSL_LIBRARIES}
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_aes_test_lib
-  third_party/boringssl/crypto/aes/aes_test.cc
-)
-
-
-target_include_directories(boringssl_aes_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_aes_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_asn1_test_lib
-  third_party/boringssl/crypto/asn1/asn1_test.cc
-)
-
-
-target_include_directories(boringssl_asn1_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_asn1_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_base64_test_lib
-  third_party/boringssl/crypto/base64/base64_test.cc
-)
-
-
-target_include_directories(boringssl_base64_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_base64_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_bio_test_lib
-  third_party/boringssl/crypto/bio/bio_test.cc
-)
-
-
-target_include_directories(boringssl_bio_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_bio_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_bn_test_lib
-  third_party/boringssl/crypto/bn/bn_test.cc
-)
-
-
-target_include_directories(boringssl_bn_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_bn_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_bytestring_test_lib
-  third_party/boringssl/crypto/bytestring/bytestring_test.cc
-)
-
-
-target_include_directories(boringssl_bytestring_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_bytestring_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_chacha_test_lib
-  third_party/boringssl/crypto/chacha/chacha_test.cc
-)
-
-
-target_include_directories(boringssl_chacha_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_chacha_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_aead_test_lib
-  third_party/boringssl/crypto/cipher/aead_test.cc
-)
-
-
-target_include_directories(boringssl_aead_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_aead_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_cipher_test_lib
-  third_party/boringssl/crypto/cipher/cipher_test.cc
-)
-
-
-target_include_directories(boringssl_cipher_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_cipher_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_cmac_test_lib
-  third_party/boringssl/crypto/cmac/cmac_test.cc
-)
-
-
-target_include_directories(boringssl_cmac_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_cmac_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_constant_time_test_lib
-  third_party/boringssl/crypto/constant_time_test.c
-)
-
-
-target_include_directories(boringssl_constant_time_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_constant_time_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_ed25519_test_lib
-  third_party/boringssl/crypto/curve25519/ed25519_test.cc
-)
-
-
-target_include_directories(boringssl_ed25519_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ed25519_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_spake25519_test_lib
-  third_party/boringssl/crypto/curve25519/spake25519_test.cc
-)
-
-
-target_include_directories(boringssl_spake25519_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_spake25519_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_x25519_test_lib
-  third_party/boringssl/crypto/curve25519/x25519_test.cc
-)
-
-
-target_include_directories(boringssl_x25519_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_x25519_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_dh_test_lib
-  third_party/boringssl/crypto/dh/dh_test.cc
-)
-
-
-target_include_directories(boringssl_dh_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_dh_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_digest_test_lib
-  third_party/boringssl/crypto/digest/digest_test.cc
-)
-
-
-target_include_directories(boringssl_digest_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_digest_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_dsa_test_lib
-  third_party/boringssl/crypto/dsa/dsa_test.c
-)
-
-
-target_include_directories(boringssl_dsa_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_dsa_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_ec_test_lib
-  third_party/boringssl/crypto/ec/ec_test.cc
-)
-
-
-target_include_directories(boringssl_ec_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ec_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_example_mul_lib
-  third_party/boringssl/crypto/ec/example_mul.c
-)
-
-
-target_include_directories(boringssl_example_mul_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_example_mul_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_ecdh_test_lib
-  third_party/boringssl/crypto/ecdh/ecdh_test.cc
-)
-
-
-target_include_directories(boringssl_ecdh_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ecdh_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_ecdsa_sign_test_lib
-  third_party/boringssl/crypto/ecdsa/ecdsa_sign_test.cc
-)
-
-
-target_include_directories(boringssl_ecdsa_sign_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ecdsa_sign_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_ecdsa_test_lib
-  third_party/boringssl/crypto/ecdsa/ecdsa_test.cc
-)
-
-
-target_include_directories(boringssl_ecdsa_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ecdsa_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_ecdsa_verify_test_lib
-  third_party/boringssl/crypto/ecdsa/ecdsa_verify_test.cc
-)
-
-
-target_include_directories(boringssl_ecdsa_verify_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ecdsa_verify_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_err_test_lib
-  third_party/boringssl/crypto/err/err_test.cc
-)
-
-
-target_include_directories(boringssl_err_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_err_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_evp_extra_test_lib
-  third_party/boringssl/crypto/evp/evp_extra_test.cc
-)
-
-
-target_include_directories(boringssl_evp_extra_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_evp_extra_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_evp_test_lib
-  third_party/boringssl/crypto/evp/evp_test.cc
-)
-
-
-target_include_directories(boringssl_evp_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_evp_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_pbkdf_test_lib
-  third_party/boringssl/crypto/evp/pbkdf_test.cc
-)
-
-
-target_include_directories(boringssl_pbkdf_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_pbkdf_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_hkdf_test_lib
-  third_party/boringssl/crypto/hkdf/hkdf_test.c
-)
-
-
-target_include_directories(boringssl_hkdf_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_hkdf_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_hmac_test_lib
-  third_party/boringssl/crypto/hmac/hmac_test.cc
-)
-
-
-target_include_directories(boringssl_hmac_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_hmac_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_lhash_test_lib
-  third_party/boringssl/crypto/lhash/lhash_test.c
-)
-
-
-target_include_directories(boringssl_lhash_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_lhash_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_gcm_test_lib
-  third_party/boringssl/crypto/modes/gcm_test.cc
-)
-
-
-target_include_directories(boringssl_gcm_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_gcm_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_newhope_statistical_test_lib
-  third_party/boringssl/crypto/newhope/newhope_statistical_test.cc
-)
-
-
-target_include_directories(boringssl_newhope_statistical_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_newhope_statistical_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_newhope_test_lib
-  third_party/boringssl/crypto/newhope/newhope_test.cc
-)
-
-
-target_include_directories(boringssl_newhope_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_newhope_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_newhope_vectors_test_lib
-  third_party/boringssl/crypto/newhope/newhope_vectors_test.cc
-)
-
-
-target_include_directories(boringssl_newhope_vectors_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_newhope_vectors_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_obj_test_lib
-  third_party/boringssl/crypto/obj/obj_test.cc
-)
-
-
-target_include_directories(boringssl_obj_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_obj_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_pkcs12_test_lib
-  third_party/boringssl/crypto/pkcs8/pkcs12_test.cc
-)
-
-
-target_include_directories(boringssl_pkcs12_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_pkcs12_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_pkcs8_test_lib
-  third_party/boringssl/crypto/pkcs8/pkcs8_test.cc
-)
-
-
-target_include_directories(boringssl_pkcs8_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_pkcs8_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_poly1305_test_lib
-  third_party/boringssl/crypto/poly1305/poly1305_test.cc
-)
-
-
-target_include_directories(boringssl_poly1305_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_poly1305_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_refcount_test_lib
-  third_party/boringssl/crypto/refcount_test.c
-)
-
-
-target_include_directories(boringssl_refcount_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_refcount_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_rsa_test_lib
-  third_party/boringssl/crypto/rsa/rsa_test.cc
-)
-
-
-target_include_directories(boringssl_rsa_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_rsa_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_thread_test_lib
-  third_party/boringssl/crypto/thread_test.c
-)
-
-
-target_include_directories(boringssl_thread_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_thread_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_pkcs7_test_lib
-  third_party/boringssl/crypto/x509/pkcs7_test.c
-)
-
-
-target_include_directories(boringssl_pkcs7_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_pkcs7_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_x509_test_lib
-  third_party/boringssl/crypto/x509/x509_test.cc
-)
-
-
-target_include_directories(boringssl_x509_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_x509_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_tab_test_lib
-  third_party/boringssl/crypto/x509v3/tab_test.c
-)
-
-
-target_include_directories(boringssl_tab_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_tab_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_v3name_test_lib
-  third_party/boringssl/crypto/x509v3/v3name_test.c
-)
-
-
-target_include_directories(boringssl_v3name_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(boringssl_v3name_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(boringssl_ssl_test_lib
-  third_party/boringssl/ssl/ssl_test.cc
-)
-
-
-target_include_directories(boringssl_ssl_test_lib
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ssl_test_lib
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_test_util
-  boringssl
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(benchmark
-  third_party/benchmark/src/benchmark.cc
-  third_party/benchmark/src/benchmark_register.cc
-  third_party/benchmark/src/colorprint.cc
-  third_party/benchmark/src/commandlineflags.cc
-  third_party/benchmark/src/complexity.cc
-  third_party/benchmark/src/console_reporter.cc
-  third_party/benchmark/src/csv_reporter.cc
-  third_party/benchmark/src/json_reporter.cc
-  third_party/benchmark/src/reporter.cc
-  third_party/benchmark/src/sleep.cc
-  third_party/benchmark/src/string_util.cc
-  third_party/benchmark/src/sysinfo.cc
-  third_party/benchmark/src/timers.cc
-)
-
-
-target_include_directories(benchmark
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(benchmark
-  ${_gRPC_SSL_LIBRARIES}
-)
-
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_library(z
-  third_party/zlib/adler32.c
-  third_party/zlib/compress.c
-  third_party/zlib/crc32.c
-  third_party/zlib/deflate.c
-  third_party/zlib/gzclose.c
-  third_party/zlib/gzlib.c
-  third_party/zlib/gzread.c
-  third_party/zlib/gzwrite.c
-  third_party/zlib/infback.c
-  third_party/zlib/inffast.c
-  third_party/zlib/inflate.c
-  third_party/zlib/inftrees.c
-  third_party/zlib/trees.c
-  third_party/zlib/uncompr.c
-  third_party/zlib/zutil.c
-)
-
-
-target_include_directories(z
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(z
-  ${_gRPC_SSL_LIBRARIES}
-)
-
+if (gRPC_INSTALL)
+  install(TARGETS grpc_csharp_ext EXPORT gRPCTargets
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+  )
+endif()
 
-endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 add_library(bad_client_test
   test/core/bad_client/bad_client.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(bad_client_test PROPERTIES COMPILE_PDB_NAME "bad_client_test"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bad_client_test.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -4485,11 +3710,13 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(bad_client_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util_unsecure
   grpc_unsecure
   gpr_test_util
@@ -4504,6 +3731,17 @@
   test/core/bad_ssl/server_common.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(bad_ssl_test_server PROPERTIES COMPILE_PDB_NAME "bad_ssl_test_server"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bad_ssl_test_server.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(bad_ssl_test_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -4511,11 +3749,13 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(bad_ssl_test_server
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4552,6 +3792,7 @@
   test/core/end2end/tests/hpack_size.c
   test/core/end2end/tests/idempotent_request.c
   test/core/end2end/tests/invoke_large_request.c
+  test/core/end2end/tests/keepalive_timeout.c
   test/core/end2end/tests/large_metadata.c
   test/core/end2end/tests/load_reporting_hook.c
   test/core/end2end/tests/max_concurrent_streams.c
@@ -4580,6 +3821,17 @@
   test/core/end2end/tests/write_buffering_at_end.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(end2end_tests PROPERTIES COMPILE_PDB_NAME "end2end_tests"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/end2end_tests.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(end2end_tests
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -4587,12 +3839,14 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(end2end_tests
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4628,6 +3882,7 @@
   test/core/end2end/tests/hpack_size.c
   test/core/end2end/tests/idempotent_request.c
   test/core/end2end/tests/invoke_large_request.c
+  test/core/end2end/tests/keepalive_timeout.c
   test/core/end2end/tests/large_metadata.c
   test/core/end2end/tests/load_reporting_hook.c
   test/core/end2end/tests/max_concurrent_streams.c
@@ -4656,6 +3911,17 @@
   test/core/end2end/tests/write_buffering_at_end.c
 )
 
+if(WIN32 AND MSVC)
+  set_target_properties(end2end_nosec_tests PROPERTIES COMPILE_PDB_NAME "end2end_nosec_tests"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/end2end_nosec_tests.pdb
+      DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
 
 target_include_directories(end2end_nosec_tests
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -4663,11 +3929,13 @@
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
   PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${BENCHMARK}/include
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(end2end_nosec_tests
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util_unsecure
   grpc_unsecure
   gpr_test_util
@@ -4683,17 +3951,20 @@
   test/core/surface/alarm_test.c
 )
 
+
 target_include_directories(alarm_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(alarm_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4707,17 +3978,20 @@
   test/core/compression/algorithm_test.c
 )
 
+
 target_include_directories(algorithm_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(algorithm_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4731,17 +4005,20 @@
   test/core/support/alloc_test.c
 )
 
+
 target_include_directories(alloc_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(alloc_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -4753,17 +4030,20 @@
   test/core/transport/chttp2/alpn_test.c
 )
 
+
 target_include_directories(alpn_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(alpn_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4777,17 +4057,20 @@
   test/core/end2end/bad_server_response_test.c
 )
 
+
 target_include_directories(bad_server_response_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(bad_server_response_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   test_tcp_server
   grpc_test_util
   grpc
@@ -4798,21 +4081,51 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(bdp_estimator_test
+  test/core/transport/bdp_estimator_test.c
+)
+
+
+target_include_directories(bdp_estimator_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(bdp_estimator_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(bin_decoder_test
   test/core/transport/chttp2/bin_decoder_test.c
 )
 
+
 target_include_directories(bin_decoder_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(bin_decoder_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
 )
@@ -4824,17 +4137,20 @@
   test/core/transport/chttp2/bin_encoder_test.c
 )
 
+
 target_include_directories(bin_encoder_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(bin_encoder_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
 )
@@ -4846,17 +4162,20 @@
   test/core/census/context_test.c
 )
 
+
 target_include_directories(census_context_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(census_context_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4870,17 +4189,20 @@
   test/core/census/resource_test.c
 )
 
+
 target_include_directories(census_resource_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(census_resource_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4894,17 +4216,20 @@
   test/core/census/trace_context_test.c
 )
 
+
 target_include_directories(census_trace_context_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(census_trace_context_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4918,17 +4243,20 @@
   test/core/surface/channel_create_test.c
 )
 
+
 target_include_directories(channel_create_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(channel_create_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4942,41 +4270,20 @@
   test/core/transport/chttp2/hpack_encoder_test.c
 )
 
+
 target_include_directories(chttp2_hpack_encoder_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(chttp2_hpack_encoder_test
-  grpc_test_util
-  grpc
-  gpr_test_util
-  gpr
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(chttp2_status_conversion_test
-  test/core/transport/chttp2/status_conversion_test.c
-)
-
-target_include_directories(chttp2_status_conversion_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(chttp2_status_conversion_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -4990,17 +4297,20 @@
   test/core/transport/chttp2/stream_map_test.c
 )
 
+
 target_include_directories(chttp2_stream_map_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(chttp2_stream_map_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5014,17 +4324,20 @@
   test/core/transport/chttp2/varint_test.c
 )
 
+
 target_include_directories(chttp2_varint_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(chttp2_varint_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5038,17 +4351,20 @@
   test/core/iomgr/combiner_test.c
 )
 
+
 target_include_directories(combiner_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(combiner_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5062,17 +4378,20 @@
   test/core/compression/compression_test.c
 )
 
+
 target_include_directories(compression_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(compression_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5086,17 +4405,20 @@
   test/core/surface/concurrent_connectivity_test.c
 )
 
+
 target_include_directories(concurrent_connectivity_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(concurrent_connectivity_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5110,17 +4432,20 @@
   test/core/end2end/connection_refused_test.c
 )
 
+
 target_include_directories(connection_refused_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(connection_refused_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5134,17 +4459,20 @@
   test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
 )
 
+
 target_include_directories(dns_resolver_connectivity_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(dns_resolver_connectivity_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5158,17 +4486,20 @@
   test/core/client_channel/resolvers/dns_resolver_test.c
 )
 
+
 target_include_directories(dns_resolver_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(dns_resolver_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5177,28 +4508,33 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(dualstack_socket_test
   test/core/end2end/dualstack_socket_test.c
 )
 
+
 target_include_directories(dualstack_socket_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(dualstack_socket_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -5206,17 +4542,20 @@
   test/core/iomgr/endpoint_pair_test.c
 )
 
+
 target_include_directories(endpoint_pair_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(endpoint_pair_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5225,76 +4564,91 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
 
 add_executable(ev_epoll_linux_test
   test/core/iomgr/ev_epoll_linux_test.c
 )
 
+
 target_include_directories(ev_epoll_linux_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(ev_epoll_linux_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(fd_conservation_posix_test
   test/core/iomgr/fd_conservation_posix_test.c
 )
 
+
 target_include_directories(fd_conservation_posix_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(fd_conservation_posix_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(fd_posix_test
   test/core/iomgr/fd_posix_test.c
 )
 
+
 target_include_directories(fd_posix_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(fd_posix_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -5302,17 +4656,20 @@
   test/core/fling/client.c
 )
 
+
 target_include_directories(fling_client
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(fling_client
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5326,17 +4683,20 @@
   test/core/fling/server.c
 )
 
+
 target_include_directories(fling_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(fling_server
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5345,69 +4705,82 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(fling_stream_test
   test/core/fling/fling_stream_test.c
 )
 
+
 target_include_directories(fling_stream_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(fling_stream_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(fling_test
   test/core/fling/fling_test.c
 )
 
+
 target_include_directories(fling_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(fling_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 
 add_executable(gen_hpack_tables
   tools/codegen/core/gen_hpack_tables.c
 )
 
+
 target_include_directories(gen_hpack_tables
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gen_hpack_tables
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
   grpc
 )
@@ -5426,16 +4799,21 @@
   tools/codegen/core/gen_legal_metadata_characters.c
 )
 
+
 target_include_directories(gen_legal_metadata_characters
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
+target_link_libraries(gen_legal_metadata_characters
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+)
 
 
 if (gRPC_INSTALL)
@@ -5451,16 +4829,21 @@
   tools/codegen/core/gen_percent_encoding_tables.c
 )
 
+
 target_include_directories(gen_percent_encoding_tables
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
+target_link_libraries(gen_percent_encoding_tables
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+)
 
 
 if (gRPC_INSTALL)
@@ -5472,28 +4855,33 @@
 endif()
 
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(goaway_server_test
   test/core/end2end/goaway_server_test.c
 )
 
+
 target_include_directories(goaway_server_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(goaway_server_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -5501,17 +4889,20 @@
   test/core/support/avl_test.c
 )
 
+
 target_include_directories(gpr_avl_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_avl_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5523,17 +4914,20 @@
   test/core/support/backoff_test.c
 )
 
+
 target_include_directories(gpr_backoff_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_backoff_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5545,17 +4939,20 @@
   test/core/support/cmdline_test.c
 )
 
+
 target_include_directories(gpr_cmdline_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_cmdline_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5567,17 +4964,20 @@
   test/core/support/cpu_test.c
 )
 
+
 target_include_directories(gpr_cpu_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_cpu_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5589,17 +4989,20 @@
   test/core/support/env_test.c
 )
 
+
 target_include_directories(gpr_env_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_env_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5611,17 +5014,20 @@
   test/core/support/histogram_test.c
 )
 
+
 target_include_directories(gpr_histogram_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_histogram_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5633,17 +5039,20 @@
   test/core/support/host_port_test.c
 )
 
+
 target_include_directories(gpr_host_port_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_host_port_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5655,17 +5064,20 @@
   test/core/support/log_test.c
 )
 
+
 target_include_directories(gpr_log_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_log_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5677,17 +5089,45 @@
   test/core/support/mpscq_test.c
 )
 
+
 target_include_directories(gpr_mpscq_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_mpscq_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  gpr_test_util
+  gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
+add_executable(gpr_spinlock_test
+  test/core/support/spinlock_test.c
+)
+
+
+target_include_directories(gpr_spinlock_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(gpr_spinlock_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5699,17 +5139,20 @@
   test/core/support/stack_lockfree_test.c
 )
 
+
 target_include_directories(gpr_stack_lockfree_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_stack_lockfree_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5721,17 +5164,20 @@
   test/core/support/string_test.c
 )
 
+
 target_include_directories(gpr_string_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_string_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5743,17 +5189,20 @@
   test/core/support/sync_test.c
 )
 
+
 target_include_directories(gpr_sync_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_sync_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5765,17 +5214,20 @@
   test/core/support/thd_test.c
 )
 
+
 target_include_directories(gpr_thd_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_thd_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5787,17 +5239,20 @@
   test/core/support/time_test.c
 )
 
+
 target_include_directories(gpr_time_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_time_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5809,17 +5264,20 @@
   test/core/support/tls_test.c
 )
 
+
 target_include_directories(gpr_tls_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_tls_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5831,17 +5289,20 @@
   test/core/support/useful_test.c
 )
 
+
 target_include_directories(gpr_useful_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(gpr_useful_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -5853,17 +5314,20 @@
   test/core/security/auth_context_test.c
 )
 
+
 target_include_directories(grpc_auth_context_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_auth_context_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5877,17 +5341,20 @@
   test/core/security/b64_test.c
 )
 
+
 target_include_directories(grpc_b64_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_b64_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5901,17 +5368,20 @@
   test/core/surface/byte_buffer_reader_test.c
 )
 
+
 target_include_directories(grpc_byte_buffer_reader_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_byte_buffer_reader_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5925,17 +5395,20 @@
   test/core/channel/channel_args_test.c
 )
 
+
 target_include_directories(grpc_channel_args_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_channel_args_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5949,17 +5422,20 @@
   test/core/channel/channel_stack_test.c
 )
 
+
 target_include_directories(grpc_channel_stack_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_channel_stack_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5973,17 +5449,20 @@
   test/core/surface/completion_queue_test.c
 )
 
+
 target_include_directories(grpc_completion_queue_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_completion_queue_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -5997,17 +5476,20 @@
   test/core/surface/completion_queue_threading_test.c
 )
 
+
 target_include_directories(grpc_completion_queue_threading_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_completion_queue_threading_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6020,11 +5502,13 @@
   test/core/security/create_jwt.c
 )
 
+
 target_include_directories(grpc_create_jwt
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -6032,6 +5516,7 @@
 
 target_link_libraries(grpc_create_jwt
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc
   gpr
 )
@@ -6051,17 +5536,20 @@
   test/core/security/credentials_test.c
 )
 
+
 target_include_directories(grpc_credentials_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_credentials_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6075,17 +5563,20 @@
   test/core/security/fetch_oauth2.c
 )
 
+
 target_include_directories(grpc_fetch_oauth2
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_fetch_oauth2
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6099,17 +5590,20 @@
   test/core/surface/invalid_channel_args_test.c
 )
 
+
 target_include_directories(grpc_invalid_channel_args_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_invalid_channel_args_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6118,28 +5612,33 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(grpc_json_token_test
   test/core/security/json_token_test.c
 )
 
+
 target_include_directories(grpc_json_token_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_json_token_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -6147,17 +5646,20 @@
   test/core/security/jwt_verifier_test.c
 )
 
+
 target_include_directories(grpc_jwt_verifier_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_jwt_verifier_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6170,17 +5672,20 @@
   test/core/security/print_google_default_creds_token.c
 )
 
+
 target_include_directories(grpc_print_google_default_creds_token
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_print_google_default_creds_token
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc
   gpr
 )
@@ -6200,17 +5705,20 @@
   test/core/security/security_connector_test.c
 )
 
+
 target_include_directories(grpc_security_connector_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_security_connector_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6223,17 +5731,20 @@
   test/core/security/verify_jwt.c
 )
 
+
 target_include_directories(grpc_verify_jwt
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(grpc_verify_jwt
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc
   gpr
 )
@@ -6248,16 +5759,19 @@
 endif()
 
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
 
 add_executable(handshake_client
   test/core/handshake/client_ssl.c
 )
 
+
 target_include_directories(handshake_client
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -6265,24 +5779,29 @@
 
 target_link_libraries(handshake_client
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
 
 add_executable(handshake_server
   test/core/handshake/server_ssl.c
 )
 
+
 target_include_directories(handshake_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -6290,12 +5809,14 @@
 
 target_link_libraries(handshake_server
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -6303,17 +5824,20 @@
   test/core/transport/chttp2/hpack_parser_test.c
 )
 
+
 target_include_directories(hpack_parser_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(hpack_parser_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6327,17 +5851,20 @@
   test/core/transport/chttp2/hpack_table_test.c
 )
 
+
 target_include_directories(hpack_table_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(hpack_table_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6351,17 +5878,20 @@
   test/core/http/parser_test.c
 )
 
+
 target_include_directories(http_parser_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(http_parser_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6375,17 +5905,20 @@
   test/core/http/format_request_test.c
 )
 
+
 target_include_directories(httpcli_format_request_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(httpcli_format_request_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6394,52 +5927,62 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(httpcli_test
   test/core/http/httpcli_test.c
 )
 
+
 target_include_directories(httpcli_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(httpcli_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
 
 add_executable(httpscli_test
   test/core/http/httpscli_test.c
 )
 
+
 target_include_directories(httpscli_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(httpscli_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -6447,89 +5990,20 @@
   test/core/surface/init_test.c
 )
 
+
 target_include_directories(init_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(init_test
-  grpc_test_util
-  grpc
-  gpr_test_util
-  gpr
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(internal_api_canary_iomgr_test
-  test/core/internal_api_canaries/iomgr.c
-)
-
-target_include_directories(internal_api_canary_iomgr_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(internal_api_canary_iomgr_test
-  grpc_test_util
-  grpc
-  gpr_test_util
-  gpr
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(internal_api_canary_support_test
-  test/core/internal_api_canaries/iomgr.c
-)
-
-target_include_directories(internal_api_canary_support_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(internal_api_canary_support_test
-  grpc_test_util
-  grpc
-  gpr_test_util
-  gpr
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(internal_api_canary_transport_test
-  test/core/internal_api_canaries/iomgr.c
-)
-
-target_include_directories(internal_api_canary_transport_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(internal_api_canary_transport_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6543,17 +6017,20 @@
   test/core/end2end/invalid_call_argument_test.c
 )
 
+
 target_include_directories(invalid_call_argument_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(invalid_call_argument_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6567,17 +6044,20 @@
   test/core/json/json_rewrite.c
 )
 
+
 target_include_directories(json_rewrite
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(json_rewrite
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc
   gpr
 )
@@ -6589,17 +6069,20 @@
   test/core/json/json_rewrite_test.c
 )
 
+
 target_include_directories(json_rewrite_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(json_rewrite_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6613,17 +6096,20 @@
   test/core/json/json_stream_error_test.c
 )
 
+
 target_include_directories(json_stream_error_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(json_stream_error_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6637,17 +6123,20 @@
   test/core/json/json_test.c
 )
 
+
 target_include_directories(json_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(json_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6661,17 +6150,20 @@
   test/core/surface/lame_client_test.c
 )
 
+
 target_include_directories(lame_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(lame_client_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6685,17 +6177,20 @@
   test/core/client_channel/lb_policies_test.c
 )
 
+
 target_include_directories(lb_policies_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(lb_policies_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6709,17 +6204,20 @@
   test/core/iomgr/load_file_test.c
 )
 
+
 target_include_directories(load_file_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(load_file_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6733,17 +6231,20 @@
   test/core/memory_usage/client.c
 )
 
+
 target_include_directories(memory_profile_client
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(memory_profile_client
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6757,17 +6258,20 @@
   test/core/memory_usage/server.c
 )
 
+
 target_include_directories(memory_profile_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(memory_profile_server
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6776,28 +6280,33 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(memory_profile_test
   test/core/memory_usage/memory_usage_test.c
 )
 
+
 target_include_directories(memory_profile_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(memory_profile_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -6805,17 +6314,20 @@
   test/core/compression/message_compress_test.c
 )
 
+
 target_include_directories(message_compress_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(message_compress_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6829,17 +6341,20 @@
   test/core/census/mlog_test.c
 )
 
+
 target_include_directories(mlog_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(mlog_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6853,17 +6368,20 @@
   test/core/end2end/multiple_server_queues_test.c
 )
 
+
 target_include_directories(multiple_server_queues_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(multiple_server_queues_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6877,17 +6395,20 @@
   test/core/support/murmur_hash_test.c
 )
 
+
 target_include_directories(murmur_hash_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(murmur_hash_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr_test_util
   gpr
 )
@@ -6899,17 +6420,20 @@
   test/core/end2end/no_server_test.c
 )
 
+
 target_include_directories(no_server_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(no_server_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6923,17 +6447,20 @@
   test/core/slice/percent_encoding_test.c
 )
 
+
 target_include_directories(percent_encoding_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(percent_encoding_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6942,22 +6469,83 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
+
+add_executable(pollset_set_test
+  test/core/iomgr/pollset_set_test.c
+)
+
+
+target_include_directories(pollset_set_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(pollset_set_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+add_executable(resolve_address_posix_test
+  test/core/iomgr/resolve_address_posix_test.c
+)
+
+
+target_include_directories(resolve_address_posix_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(resolve_address_posix_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
 
 add_executable(resolve_address_test
   test/core/iomgr/resolve_address_test.c
 )
 
+
 target_include_directories(resolve_address_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(resolve_address_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6971,17 +6559,20 @@
   test/core/iomgr/resource_quota_test.c
 )
 
+
 target_include_directories(resource_quota_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(resource_quota_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -6995,17 +6586,20 @@
   test/core/surface/secure_channel_create_test.c
 )
 
+
 target_include_directories(secure_channel_create_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(secure_channel_create_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7019,17 +6613,20 @@
   test/core/security/secure_endpoint_test.c
 )
 
+
 target_include_directories(secure_endpoint_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(secure_endpoint_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7043,17 +6640,20 @@
   test/core/surface/sequential_connectivity_test.c
 )
 
+
 target_include_directories(sequential_connectivity_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(sequential_connectivity_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7067,17 +6667,20 @@
   test/core/surface/server_chttp2_test.c
 )
 
+
 target_include_directories(server_chttp2_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(server_chttp2_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7091,17 +6694,20 @@
   test/core/surface/server_test.c
 )
 
+
 target_include_directories(server_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(server_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7115,17 +6721,20 @@
   test/core/client_channel/set_initial_connect_string_test.c
 )
 
+
 target_include_directories(set_initial_connect_string_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(set_initial_connect_string_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   test_tcp_server
   grpc_test_util
   grpc
@@ -7140,17 +6749,20 @@
   test/core/slice/slice_buffer_test.c
 )
 
+
 target_include_directories(slice_buffer_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(slice_buffer_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7164,17 +6776,20 @@
   test/core/slice/slice_string_helpers_test.c
 )
 
+
 target_include_directories(slice_string_helpers_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(slice_string_helpers_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7188,17 +6803,20 @@
   test/core/slice/slice_test.c
 )
 
+
 target_include_directories(slice_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(slice_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7212,17 +6830,20 @@
   test/core/client_channel/resolvers/sockaddr_resolver_test.c
 )
 
+
 target_include_directories(sockaddr_resolver_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(sockaddr_resolver_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7236,17 +6857,20 @@
   test/core/iomgr/sockaddr_utils_test.c
 )
 
+
 target_include_directories(sockaddr_utils_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(sockaddr_utils_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7255,22 +6879,54 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(socket_utils_test
   test/core/iomgr/socket_utils_test.c
 )
 
+
 target_include_directories(socket_utils_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(socket_utils_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
+add_executable(status_conversion_test
+  test/core/transport/status_conversion_test.c
+)
+
+
+target_include_directories(status_conversion_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+)
+
+target_link_libraries(status_conversion_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7279,28 +6935,33 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(tcp_client_posix_test
   test/core/iomgr/tcp_client_posix_test.c
 )
 
+
 target_include_directories(tcp_client_posix_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(tcp_client_posix_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -7308,17 +6969,20 @@
   test/core/iomgr/tcp_client_uv_test.c
 )
 
+
 target_include_directories(tcp_client_uv_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(tcp_client_uv_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7327,52 +6991,62 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(tcp_posix_test
   test/core/iomgr/tcp_posix_test.c
 )
 
+
 target_include_directories(tcp_posix_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(tcp_posix_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(tcp_server_posix_test
   test/core/iomgr/tcp_server_posix_test.c
 )
 
+
 target_include_directories(tcp_server_posix_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(tcp_server_posix_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -7380,17 +7054,20 @@
   test/core/iomgr/tcp_server_uv_test.c
 )
 
+
 target_include_directories(tcp_server_uv_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(tcp_server_uv_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7404,17 +7081,20 @@
   test/core/iomgr/time_averaged_stats_test.c
 )
 
+
 target_include_directories(time_averaged_stats_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(time_averaged_stats_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7428,17 +7108,20 @@
   test/core/transport/timeout_encoding_test.c
 )
 
+
 target_include_directories(timeout_encoding_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(timeout_encoding_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7452,17 +7135,20 @@
   test/core/iomgr/timer_heap_test.c
 )
 
+
 target_include_directories(timer_heap_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(timer_heap_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7476,17 +7162,20 @@
   test/core/iomgr/timer_list_test.c
 )
 
+
 target_include_directories(timer_list_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(timer_list_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7500,17 +7189,20 @@
   test/core/transport/connectivity_state_test.c
 )
 
+
 target_include_directories(transport_connectivity_state_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(transport_connectivity_state_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7524,17 +7216,20 @@
   test/core/transport/metadata_test.c
 )
 
+
 target_include_directories(transport_metadata_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(transport_metadata_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7548,17 +7243,20 @@
   test/core/transport/pid_controller_test.c
 )
 
+
 target_include_directories(transport_pid_controller_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(transport_pid_controller_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7567,52 +7265,62 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(transport_security_test
   test/core/tsi/transport_security_test.c
 )
 
+
 target_include_directories(transport_security_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(transport_security_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(udp_server_test
   test/core/iomgr/udp_server_test.c
 )
 
+
 target_include_directories(udp_server_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(udp_server_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -7620,17 +7328,20 @@
   test/core/client_channel/uri_parser_test.c
 )
 
+
 target_include_directories(uri_parser_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(uri_parser_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -7639,28 +7350,33 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(wakeup_fd_cv_test
   test/core/iomgr/wakeup_fd_cv_test.c
 )
 
+
 target_include_directories(wakeup_fd_cv_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(wakeup_fd_cv_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -7669,19 +7385,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(alarm_cpp_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(alarm_cpp_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -7699,19 +7420,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(async_end2end_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(async_end2end_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -7729,19 +7455,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(auth_property_iterator_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(auth_property_iterator_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -7753,25 +7484,31 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-add_executable(bm_fullstack
-  test/cpp/microbenchmarks/bm_fullstack.cc
+add_executable(bm_call_create
+  test/cpp/microbenchmarks/bm_call_create.cc
   third_party/googletest/src/gtest-all.cc
 )
 
-target_include_directories(bm_fullstack
+
+target_include_directories(bm_call_create
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(bm_fullstack
+target_link_libraries(bm_call_create
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   benchmark
   grpc++_test_util
   grpc_test_util
@@ -7782,6 +7519,233 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+add_executable(bm_chttp2_hpack
+  test/cpp/microbenchmarks/bm_chttp2_hpack.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(bm_chttp2_hpack
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bm_chttp2_hpack
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  benchmark
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+add_executable(bm_closure
+  test/cpp/microbenchmarks/bm_closure.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(bm_closure
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bm_closure
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  benchmark
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+add_executable(bm_cq
+  test/cpp/microbenchmarks/bm_cq.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(bm_cq
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bm_cq
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  benchmark
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+add_executable(bm_error
+  test/cpp/microbenchmarks/bm_error.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(bm_error
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bm_error
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  benchmark
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+add_executable(bm_fullstack
+  test/cpp/microbenchmarks/bm_fullstack.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(bm_fullstack
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bm_fullstack
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  benchmark
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+add_executable(bm_metadata
+  test/cpp/microbenchmarks/bm_metadata.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(bm_metadata
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bm_metadata
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  benchmark
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -7790,19 +7754,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(channel_arguments_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(channel_arguments_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   grpc
   gpr
@@ -7817,19 +7786,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(channel_filter_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(channel_filter_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   grpc
   gpr
@@ -7844,19 +7818,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(cli_call_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(cli_call_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_cli_libs
   grpc++_test_util
   grpc_test_util
@@ -7869,25 +7848,31 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(client_crash_test
   test/cpp/end2end/client_crash_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(client_crash_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(client_crash_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -7897,6 +7882,7 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -7905,19 +7891,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(client_crash_test_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(client_crash_test_server
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -7931,28 +7922,63 @@
 if (gRPC_BUILD_TESTS)
 
 add_executable(codegen_test_full
-  src/proto/grpc/testing/control.proto
-  src/proto/grpc/testing/messages.proto
-  src/proto/grpc/testing/payloads.proto
-  src/proto/grpc/testing/services.proto
-  src/proto/grpc/testing/stats.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h
   test/cpp/codegen/codegen_test_full.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/control.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/messages.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/payloads.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/services.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/stats.proto
+)
+
 target_include_directories(codegen_test_full
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(codegen_test_full
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   grpc
   gpr
@@ -7963,29 +7989,64 @@
 if (gRPC_BUILD_TESTS)
 
 add_executable(codegen_test_minimal
-  src/proto/grpc/testing/control.proto
-  src/proto/grpc/testing/messages.proto
-  src/proto/grpc/testing/payloads.proto
-  src/proto/grpc/testing/services.proto
-  src/proto/grpc/testing/stats.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.h
   test/cpp/codegen/codegen_test_minimal.cc
   src/cpp/codegen/codegen_init.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/control.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/messages.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/payloads.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/services.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/stats.proto
+)
+
 target_include_directories(codegen_test_minimal
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(codegen_test_minimal
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -7997,19 +8058,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(credentials_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(credentials_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   grpc
   gpr
@@ -8024,19 +8090,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(cxx_byte_buffer_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(cxx_byte_buffer_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc++
   grpc
@@ -8053,19 +8124,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(cxx_slice_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(cxx_slice_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc++
   grpc
@@ -8082,19 +8158,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(cxx_string_ref_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(cxx_string_ref_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   ${_gRPC_GFLAGS_LIBRARIES}
 )
@@ -8107,19 +8188,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(cxx_time_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(cxx_time_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc++
   grpc
@@ -8136,19 +8222,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(end2end_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(end2end_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -8166,19 +8257,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(filter_end2end_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(filter_end2end_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -8196,19 +8292,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(generic_end2end_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(generic_end2end_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -8222,24 +8323,35 @@
 if (gRPC_BUILD_TESTS)
 
 add_executable(golden_file_test
-  src/proto/grpc/testing/compiler_test.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/compiler_test.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/compiler_test.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/compiler_test.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/compiler_test.grpc.pb.h
   test/cpp/codegen/golden_file_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/compiler_test.proto
+)
+
 target_include_directories(golden_file_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(golden_file_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   grpc
   gpr
@@ -8254,19 +8366,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(grpc_cli
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_cli
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_cli_libs
   grpc++_proto_reflection_desc_db
   grpc++
@@ -8282,18 +8399,23 @@
   src/compiler/cpp_plugin.cc
 )
 
+
 target_include_directories(grpc_cpp_plugin
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_cpp_plugin
   ${_gRPC_PROTOBUF_PROTOC_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_plugin_support
 )
 
@@ -8311,18 +8433,23 @@
   src/compiler/csharp_plugin.cc
 )
 
+
 target_include_directories(grpc_csharp_plugin
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_csharp_plugin
   ${_gRPC_PROTOBUF_PROTOC_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_plugin_support
 )
 
@@ -8340,18 +8467,23 @@
   src/compiler/node_plugin.cc
 )
 
+
 target_include_directories(grpc_node_plugin
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_node_plugin
   ${_gRPC_PROTOBUF_PROTOC_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_plugin_support
 )
 
@@ -8369,18 +8501,23 @@
   src/compiler/objective_c_plugin.cc
 )
 
+
 target_include_directories(grpc_objective_c_plugin
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_objective_c_plugin
   ${_gRPC_PROTOBUF_PROTOC_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_plugin_support
 )
 
@@ -8398,18 +8535,23 @@
   src/compiler/php_plugin.cc
 )
 
+
 target_include_directories(grpc_php_plugin
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_php_plugin
   ${_gRPC_PROTOBUF_PROTOC_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_plugin_support
 )
 
@@ -8427,18 +8569,23 @@
   src/compiler/python_plugin.cc
 )
 
+
 target_include_directories(grpc_python_plugin
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_python_plugin
   ${_gRPC_PROTOBUF_PROTOC_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_plugin_support
 )
 
@@ -8456,18 +8603,23 @@
   src/compiler/ruby_plugin.cc
 )
 
+
 target_include_directories(grpc_ruby_plugin
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_ruby_plugin
   ${_gRPC_PROTOBUF_PROTOC_LIBRARIES}
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_plugin_support
 )
 
@@ -8483,25 +8635,42 @@
 if (gRPC_BUILD_TESTS)
 
 add_executable(grpc_tool_test
-  src/proto/grpc/testing/echo.proto
-  src/proto/grpc/testing/echo_messages.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
   test/cpp/util/grpc_tool_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/echo.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/echo_messages.proto
+)
+
 target_include_directories(grpc_tool_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpc_tool_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_cli_libs
   grpc++_proto_reflection_desc_db
   grpc++_reflection
@@ -8518,24 +8687,35 @@
 if (gRPC_BUILD_TESTS)
 
 add_executable(grpclb_api_test
-  src/proto/grpc/lb/v1/load_balancer.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.h
   test/cpp/grpclb/grpclb_api_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/lb/v1/load_balancer.proto
+)
+
 target_include_directories(grpclb_api_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpclb_api_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -8547,53 +8727,105 @@
 if (gRPC_BUILD_TESTS)
 
 add_executable(grpclb_test
-  src/proto/grpc/lb/v1/load_balancer.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.h
   test/cpp/grpclb/grpclb_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/lb/v1/load_balancer.proto
+)
+
 target_include_directories(grpclb_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(grpclb_test
-  gpr
-  gpr_test_util
-  grpc
-  grpc++
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(health_service_end2end_test
+  test/cpp/end2end/health_service_end2end_test.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(health_service_end2end_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(health_service_end2end_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
 add_executable(http2_client
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(http2_client
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(http2_client
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   http2_client_main
   grpc++_test_util
   grpc_test_util
@@ -8603,6 +8835,7 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -8611,19 +8844,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(hybrid_end2end_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(hybrid_end2end_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -8635,24 +8873,30 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(interop_client
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(interop_client
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(interop_client
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   interop_client_main
   interop_client_helper
   grpc++_test_util
@@ -8665,26 +8909,33 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(interop_server
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(interop_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(interop_server
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   interop_server_main
   interop_server_helper
   interop_server_lib
@@ -8698,27 +8949,34 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(interop_test
   test/cpp/interop/interop_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(interop_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(interop_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -8727,27 +8985,34 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(json_run_localhost
   test/cpp/qps/json_run_localhost.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(json_run_localhost
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(json_run_localhost
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -8758,28 +9023,40 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 add_executable(metrics_client
-  src/proto/grpc/testing/metrics.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.grpc.pb.h
   test/cpp/interop/metrics_client.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/metrics.proto
+)
+
 target_include_directories(metrics_client
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(metrics_client
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   grpc
   gpr
@@ -8795,19 +9072,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(mock_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(mock_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -8825,19 +9107,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(noop-benchmark
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(noop-benchmark
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   benchmark
   ${_gRPC_GFLAGS_LIBRARIES}
 )
@@ -8850,19 +9137,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(proto_server_reflection_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(proto_server_reflection_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_proto_reflection_desc_db
   grpc++_reflection
   grpc++_test_util
@@ -8877,24 +9169,61 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(proto_utils_test
+  test/cpp/codegen/proto_utils_test.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(proto_utils_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(proto_utils_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++
+  grpc
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
 add_executable(qps_interarrival_test
   test/cpp/qps/qps_interarrival_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(qps_interarrival_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(qps_interarrival_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   qps
   grpc++_test_util
   grpc_test_util
@@ -8905,6 +9234,7 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -8913,19 +9243,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(qps_json_driver
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(qps_json_driver
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   qps
   grpc++_test_util
   grpc_test_util
@@ -8939,25 +9274,31 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(qps_openloop_test
   test/cpp/qps/qps_openloop_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(qps_openloop_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(qps_openloop_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   qps
   grpc++_test_util
   grpc_test_util
@@ -8969,6 +9310,7 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -8977,19 +9319,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(qps_worker
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(qps_worker
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   qps
   grpc++_test_util
   grpc_test_util
@@ -9005,26 +9352,49 @@
 if (gRPC_BUILD_TESTS)
 
 add_executable(reconnect_interop_client
-  src/proto/grpc/testing/empty.proto
-  src/proto/grpc/testing/messages.proto
-  src/proto/grpc/testing/test.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
   test/cpp/interop/reconnect_interop_client.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/empty.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/messages.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/test.proto
+)
+
 target_include_directories(reconnect_interop_client
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(reconnect_interop_client
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9039,26 +9409,49 @@
 if (gRPC_BUILD_TESTS)
 
 add_executable(reconnect_interop_server
-  src/proto/grpc/testing/empty.proto
-  src/proto/grpc/testing/messages.proto
-  src/proto/grpc/testing/test.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
   test/cpp/interop/reconnect_interop_server.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/empty.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/messages.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/test.proto
+)
+
 target_include_directories(reconnect_interop_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(reconnect_interop_server
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   reconnect_server
   test_tcp_server
   grpc++_test_util
@@ -9079,19 +9472,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(round_robin_end2end_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(round_robin_end2end_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9109,19 +9507,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(secure_auth_context_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(secure_auth_context_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9133,25 +9536,31 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(secure_sync_unary_ping_pong_test
   test/cpp/qps/secure_sync_unary_ping_pong_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(secure_sync_unary_ping_pong_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(secure_sync_unary_ping_pong_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   qps
   grpc++_test_util
   grpc_test_util
@@ -9162,6 +9571,7 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -9170,19 +9580,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(server_builder_plugin_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(server_builder_plugin_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9200,21 +9615,25 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(server_context_test_spouse_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(server_context_test_spouse_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
-  grpc++_test
   grpc++
   grpc
   gpr_test_util
@@ -9224,25 +9643,31 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(server_crash_test
   test/cpp/end2end/server_crash_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(server_crash_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(server_crash_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9252,6 +9677,7 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -9260,19 +9686,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(server_crash_test_client
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(server_crash_test_client
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9290,19 +9721,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(shutdown_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(shutdown_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9320,19 +9756,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(status_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(status_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc++
   grpc
@@ -9343,25 +9784,31 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(streaming_throughput_test
   test/cpp/end2end/streaming_throughput_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(streaming_throughput_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(streaming_throughput_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9371,14 +9818,27 @@
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
 add_executable(stress_test
-  src/proto/grpc/testing/empty.proto
-  src/proto/grpc/testing/messages.proto
-  src/proto/grpc/testing/metrics.proto
-  src/proto/grpc/testing/test.proto
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/metrics.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h
   test/cpp/interop/interop_client.cc
   test/cpp/interop/stress_interop_client.cc
   test/cpp/interop/stress_test.cc
@@ -9387,19 +9847,36 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/empty.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/messages.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/metrics.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/test.proto
+)
+
 target_include_directories(stress_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(stress_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9418,19 +9895,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(thread_manager_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(thread_manager_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++
   grpc
   gpr
@@ -9446,19 +9928,24 @@
   third_party/googletest/src/gtest-all.cc
 )
 
+
 target_include_directories(thread_stress_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
 target_link_libraries(thread_stress_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc++_test_util
   grpc_test_util
   grpc++
@@ -9470,1244 +9957,64 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
-add_executable(boringssl_aes_test
+add_executable(writes_per_rpc_test
+  test/cpp/performance/writes_per_rpc_test.cc
   third_party/googletest/src/gtest-all.cc
 )
 
-target_include_directories(boringssl_aes_test
+
+target_include_directories(writes_per_rpc_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
   PRIVATE third_party/googletest/include
   PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
-target_link_libraries(boringssl_aes_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_aes_test_lib
-  boringssl_test_util
-  boringssl
+target_link_libraries(writes_per_rpc_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
-add_executable(boringssl_asn1_test
-  third_party/googletest/src/gtest-all.cc
+add_executable(public_headers_must_be_c89
+  test/core/surface/public_headers_must_be_c89.c
 )
 
-target_include_directories(boringssl_asn1_test
+
+target_include_directories(public_headers_must_be_c89
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
 )
 
-target_link_libraries(boringssl_asn1_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_asn1_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_base64_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_base64_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_base64_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_base64_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_bio_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_bio_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_bio_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_bio_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_bn_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_bn_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_bn_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_bn_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_bytestring_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_bytestring_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_bytestring_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_bytestring_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_chacha_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_chacha_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_chacha_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_chacha_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_aead_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_aead_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_aead_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_aead_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_cipher_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_cipher_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_cipher_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_cipher_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_cmac_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_cmac_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_cmac_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_cmac_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_constant_time_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_constant_time_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_constant_time_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_constant_time_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_ed25519_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_ed25519_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ed25519_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_ed25519_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_spake25519_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_spake25519_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_spake25519_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_spake25519_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_x25519_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_x25519_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_x25519_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_x25519_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_dh_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_dh_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_dh_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_dh_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_digest_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_digest_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_digest_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_digest_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_dsa_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_dsa_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_dsa_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_dsa_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_ec_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_ec_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ec_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_ec_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_example_mul
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_example_mul
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_example_mul
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_example_mul_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_ecdh_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_ecdh_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ecdh_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_ecdh_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_ecdsa_sign_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_ecdsa_sign_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ecdsa_sign_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_ecdsa_sign_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_ecdsa_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_ecdsa_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ecdsa_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_ecdsa_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_ecdsa_verify_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_ecdsa_verify_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ecdsa_verify_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_ecdsa_verify_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_err_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_err_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_err_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_err_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_evp_extra_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_evp_extra_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_evp_extra_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_evp_extra_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_evp_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_evp_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_evp_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_evp_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_pbkdf_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_pbkdf_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_pbkdf_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_pbkdf_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_hkdf_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_hkdf_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_hkdf_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_hkdf_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_hmac_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_hmac_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_hmac_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_hmac_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_lhash_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_lhash_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_lhash_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_lhash_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_gcm_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_gcm_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_gcm_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_gcm_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_newhope_statistical_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_newhope_statistical_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_newhope_statistical_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_newhope_statistical_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_newhope_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_newhope_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_newhope_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_newhope_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_newhope_vectors_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_newhope_vectors_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_newhope_vectors_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_newhope_vectors_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_obj_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_obj_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_obj_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_obj_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_pkcs12_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_pkcs12_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_pkcs12_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_pkcs12_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_pkcs8_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_pkcs8_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_pkcs8_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_pkcs8_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_poly1305_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_poly1305_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_poly1305_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_poly1305_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_refcount_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_refcount_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_refcount_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_refcount_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_rsa_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_rsa_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_rsa_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_rsa_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_thread_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_thread_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_thread_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_thread_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_pkcs7_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_pkcs7_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_pkcs7_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_pkcs7_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_x509_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_x509_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_x509_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_x509_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_tab_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_tab_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_tab_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_tab_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_v3name_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_v3name_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_v3name_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_v3name_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
-add_executable(boringssl_ssl_test
-  third_party/googletest/src/gtest-all.cc
-)
-
-target_include_directories(boringssl_ssl_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${BORINGSSL_ROOT_DIR}/include
-  PRIVATE ${PROTOBUF_ROOT_DIR}/src
-  PRIVATE ${ZLIB_ROOT_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-  PRIVATE third_party/googletest/include
-  PRIVATE third_party/googletest
-)
-
-target_link_libraries(boringssl_ssl_test
-  ${_gRPC_SSL_LIBRARIES}
-  boringssl_ssl_test_lib
-  boringssl_test_util
-  boringssl
-  ${_gRPC_GFLAGS_LIBRARIES}
+target_link_libraries(public_headers_must_be_c89
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc
+  gpr
 )
 
 endif (gRPC_BUILD_TESTS)
@@ -10717,11 +10024,13 @@
   test/core/bad_client/tests/badreq.c
 )
 
+
 target_include_directories(badreq_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10729,6 +10038,7 @@
 
 target_link_libraries(badreq_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10743,11 +10053,13 @@
   test/core/bad_client/tests/connection_prefix.c
 )
 
+
 target_include_directories(connection_prefix_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10755,6 +10067,7 @@
 
 target_link_libraries(connection_prefix_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10769,11 +10082,13 @@
   test/core/bad_client/tests/head_of_line_blocking.c
 )
 
+
 target_include_directories(head_of_line_blocking_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10781,6 +10096,7 @@
 
 target_link_libraries(head_of_line_blocking_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10795,11 +10111,13 @@
   test/core/bad_client/tests/headers.c
 )
 
+
 target_include_directories(headers_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10807,6 +10125,7 @@
 
 target_link_libraries(headers_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10821,11 +10140,13 @@
   test/core/bad_client/tests/initial_settings_frame.c
 )
 
+
 target_include_directories(initial_settings_frame_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10833,6 +10154,7 @@
 
 target_link_libraries(initial_settings_frame_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10847,11 +10169,13 @@
   test/core/bad_client/tests/large_metadata.c
 )
 
+
 target_include_directories(large_metadata_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10859,6 +10183,7 @@
 
 target_link_libraries(large_metadata_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10873,11 +10198,13 @@
   test/core/bad_client/tests/server_registered_method.c
 )
 
+
 target_include_directories(server_registered_method_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10885,6 +10212,7 @@
 
 target_link_libraries(server_registered_method_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10899,11 +10227,13 @@
   test/core/bad_client/tests/simple_request.c
 )
 
+
 target_include_directories(simple_request_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10911,6 +10241,7 @@
 
 target_link_libraries(simple_request_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10925,11 +10256,13 @@
   test/core/bad_client/tests/unknown_frame.c
 )
 
+
 target_include_directories(unknown_frame_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10937,6 +10270,7 @@
 
 target_link_libraries(unknown_frame_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10951,11 +10285,13 @@
   test/core/bad_client/tests/window_overflow.c
 )
 
+
 target_include_directories(window_overflow_bad_client_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
@@ -10963,6 +10299,7 @@
 
 target_link_libraries(window_overflow_bad_client_test
   ${_gRPC_SSL_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_client_test
   grpc_test_util_unsecure
   grpc_unsecure
@@ -10972,22 +10309,26 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(bad_ssl_cert_server
   test/core/bad_ssl/servers/cert.c
 )
 
+
 target_include_directories(bad_ssl_cert_server
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(bad_ssl_cert_server
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   bad_ssl_test_server
   grpc_test_util
   grpc
@@ -10995,30 +10336,36 @@
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(bad_ssl_cert_test
   test/core/bad_ssl/bad_ssl_test.c
 )
 
+
 target_include_directories(bad_ssl_cert_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(bad_ssl_cert_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -11026,17 +10373,20 @@
   test/core/end2end/fixtures/h2_census.c
 )
 
+
 target_include_directories(h2_census_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_census_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11051,17 +10401,20 @@
   test/core/end2end/fixtures/h2_compress.c
 )
 
+
 target_include_directories(h2_compress_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_compress_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11076,17 +10429,20 @@
   test/core/end2end/fixtures/h2_fakesec.c
 )
 
+
 target_include_directories(h2_fakesec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_fakesec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11096,22 +10452,26 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(h2_fd_test
   test/core/end2end/fixtures/h2_fd.c
 )
 
+
 target_include_directories(h2_fd_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_fd_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11119,6 +10479,7 @@
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -11126,17 +10487,20 @@
   test/core/end2end/fixtures/h2_full.c
 )
 
+
 target_include_directories(h2_full_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_full_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11146,22 +10510,26 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
 
 add_executable(h2_full+pipe_test
   test/core/end2end/fixtures/h2_full+pipe.c
 )
 
+
 target_include_directories(h2_full+pipe_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_full+pipe_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11169,6 +10537,7 @@
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -11176,17 +10545,20 @@
   test/core/end2end/fixtures/h2_full+trace.c
 )
 
+
 target_include_directories(h2_full+trace_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_full+trace_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11201,17 +10573,20 @@
   test/core/end2end/fixtures/h2_http_proxy.c
 )
 
+
 target_include_directories(h2_http_proxy_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_http_proxy_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11226,17 +10601,20 @@
   test/core/end2end/fixtures/h2_load_reporting.c
 )
 
+
 target_include_directories(h2_load_reporting_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_load_reporting_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11251,17 +10629,20 @@
   test/core/end2end/fixtures/h2_oauth2.c
 )
 
+
 target_include_directories(h2_oauth2_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_oauth2_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11276,17 +10657,20 @@
   test/core/end2end/fixtures/h2_proxy.c
 )
 
+
 target_include_directories(h2_proxy_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_proxy_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11301,17 +10685,20 @@
   test/core/end2end/fixtures/h2_sockpair.c
 )
 
+
 target_include_directories(h2_sockpair_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_sockpair_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11326,17 +10713,20 @@
   test/core/end2end/fixtures/h2_sockpair+trace.c
 )
 
+
 target_include_directories(h2_sockpair+trace_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_sockpair+trace_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11351,17 +10741,20 @@
   test/core/end2end/fixtures/h2_sockpair_1byte.c
 )
 
+
 target_include_directories(h2_sockpair_1byte_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_sockpair_1byte_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11376,17 +10769,20 @@
   test/core/end2end/fixtures/h2_ssl.c
 )
 
+
 target_include_directories(h2_ssl_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_ssl_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11401,17 +10797,20 @@
   test/core/end2end/fixtures/h2_ssl_cert.c
 )
 
+
 target_include_directories(h2_ssl_cert_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_ssl_cert_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11426,17 +10825,20 @@
   test/core/end2end/fixtures/h2_ssl_proxy.c
 )
 
+
 target_include_directories(h2_ssl_proxy_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_ssl_proxy_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11446,22 +10848,26 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(h2_uds_test
   test/core/end2end/fixtures/h2_uds.c
 )
 
+
 target_include_directories(h2_uds_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_uds_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_tests
   grpc_test_util
   grpc
@@ -11469,6 +10875,7 @@
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -11476,17 +10883,20 @@
   test/core/end2end/fixtures/h2_census.c
 )
 
+
 target_include_directories(h2_census_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_census_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11501,17 +10911,20 @@
   test/core/end2end/fixtures/h2_compress.c
 )
 
+
 target_include_directories(h2_compress_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_compress_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11521,22 +10934,26 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(h2_fd_nosec_test
   test/core/end2end/fixtures/h2_fd.c
 )
 
+
 target_include_directories(h2_fd_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_fd_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11544,6 +10961,7 @@
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -11551,17 +10969,20 @@
   test/core/end2end/fixtures/h2_full.c
 )
 
+
 target_include_directories(h2_full_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_full_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11571,22 +10992,26 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
 
 add_executable(h2_full+pipe_nosec_test
   test/core/end2end/fixtures/h2_full+pipe.c
 )
 
+
 target_include_directories(h2_full+pipe_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_full+pipe_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11594,6 +11019,7 @@
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -11601,17 +11027,20 @@
   test/core/end2end/fixtures/h2_full+trace.c
 )
 
+
 target_include_directories(h2_full+trace_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_full+trace_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11626,17 +11055,20 @@
   test/core/end2end/fixtures/h2_http_proxy.c
 )
 
+
 target_include_directories(h2_http_proxy_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_http_proxy_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11651,17 +11083,20 @@
   test/core/end2end/fixtures/h2_load_reporting.c
 )
 
+
 target_include_directories(h2_load_reporting_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_load_reporting_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11676,17 +11111,20 @@
   test/core/end2end/fixtures/h2_proxy.c
 )
 
+
 target_include_directories(h2_proxy_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_proxy_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11701,17 +11139,20 @@
   test/core/end2end/fixtures/h2_sockpair.c
 )
 
+
 target_include_directories(h2_sockpair_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_sockpair_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11726,17 +11167,20 @@
   test/core/end2end/fixtures/h2_sockpair+trace.c
 )
 
+
 target_include_directories(h2_sockpair+trace_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_sockpair+trace_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11751,17 +11195,20 @@
   test/core/end2end/fixtures/h2_sockpair_1byte.c
 )
 
+
 target_include_directories(h2_sockpair_1byte_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_sockpair_1byte_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11771,22 +11218,26 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(h2_uds_nosec_test
   test/core/end2end/fixtures/h2_uds.c
 )
 
+
 target_include_directories(h2_uds_nosec_test
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(h2_uds_nosec_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   end2end_nosec_tests
   grpc_test_util_unsecure
   grpc_unsecure
@@ -11794,6 +11245,7 @@
   gpr
 )
 
+endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
@@ -11802,17 +11254,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(api_fuzzer_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(api_fuzzer_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -11827,17 +11282,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(client_fuzzer_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(client_fuzzer_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -11852,17 +11310,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(hpack_parser_fuzzer_test_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(hpack_parser_fuzzer_test_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -11877,17 +11338,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(http_request_fuzzer_test_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(http_request_fuzzer_test_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -11902,17 +11366,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(http_response_fuzzer_test_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(http_response_fuzzer_test_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -11927,17 +11394,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(json_fuzzer_test_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(json_fuzzer_test_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -11952,17 +11422,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(nanopb_fuzzer_response_test_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(nanopb_fuzzer_response_test_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -11977,17 +11450,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(nanopb_fuzzer_serverlist_test_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(nanopb_fuzzer_serverlist_test_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -12002,17 +11478,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(percent_decode_fuzzer_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(percent_decode_fuzzer_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -12027,17 +11506,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(percent_encode_fuzzer_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(percent_encode_fuzzer_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -12052,17 +11534,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(server_fuzzer_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(server_fuzzer_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -12077,17 +11562,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(ssl_server_fuzzer_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(ssl_server_fuzzer_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -12102,17 +11590,20 @@
   test/core/util/one_corpus_entry_fuzzer.c
 )
 
+
 target_include_directories(uri_fuzzer_test_one_entry
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
   PRIVATE ${BORINGSSL_ROOT_DIR}/include
   PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
   PRIVATE ${ZLIB_ROOT_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
 )
 
 target_link_libraries(uri_fuzzer_test_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_test_util
   grpc
   gpr_test_util
@@ -12127,13 +11618,6 @@
 
 
 
-if (gRPC_INSTALL)
-  install(EXPORT gRPCTargets
-    DESTINATION ${CMAKE_INSTALL_CMAKEDIR}
-    NAMESPACE gRPC::
-  )
-endif()
-
 foreach(_config gRPCConfig gRPCConfigVersion)
   configure_file(tools/cmake/${_config}.cmake.in
     ${_config}.cmake @ONLY)
diff --git a/Makefile b/Makefile
index 578a5dd..57e877b 100644
--- a/Makefile
+++ b/Makefile
@@ -95,56 +95,6 @@
 CPPFLAGS_opt = -O2
 DEFINES_opt = NDEBUG
 
-VALID_CONFIG_asan-trace-cmp = 1
-REQUIRE_CUSTOM_LIBRARIES_asan-trace-cmp = 1
-CC_asan-trace-cmp = clang
-CXX_asan-trace-cmp = clang++
-LD_asan-trace-cmp = clang
-LDXX_asan-trace-cmp = clang++
-CPPFLAGS_asan-trace-cmp = -O0 -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
-LDFLAGS_asan-trace-cmp = -fsanitize=address
-DEFINES_asan-trace-cmp += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
-
-VALID_CONFIG_dbg = 1
-CC_dbg = $(DEFAULT_CC)
-CXX_dbg = $(DEFAULT_CXX)
-LD_dbg = $(DEFAULT_CC)
-LDXX_dbg = $(DEFAULT_CXX)
-CPPFLAGS_dbg = -O0
-DEFINES_dbg = _DEBUG DEBUG
-
-VALID_CONFIG_easan = 1
-REQUIRE_CUSTOM_LIBRARIES_easan = 1
-CC_easan = clang
-CXX_easan = clang++
-LD_easan = clang
-LDXX_easan = clang++
-CPPFLAGS_easan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
-LDFLAGS_easan = -fsanitize=address
-DEFINES_easan = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
-DEFINES_easan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
-
-VALID_CONFIG_asan = 1
-REQUIRE_CUSTOM_LIBRARIES_asan = 1
-CC_asan = clang
-CXX_asan = clang++
-LD_asan = clang
-LDXX_asan = clang++
-CPPFLAGS_asan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
-LDFLAGS_asan = -fsanitize=address
-DEFINES_asan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
-
-VALID_CONFIG_msan = 1
-REQUIRE_CUSTOM_LIBRARIES_msan = 1
-CC_msan = clang
-CXX_msan = clang++
-LD_msan = clang
-LDXX_msan = clang++
-CPPFLAGS_msan = -O0 -fsanitize-coverage=edge -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
-LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
-DEFINES_msan = NDEBUG
-DEFINES_msan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=4
-
 VALID_CONFIG_basicprof = 1
 CC_basicprof = $(DEFAULT_CC)
 CXX_basicprof = $(DEFAULT_CXX)
@@ -161,7 +111,6 @@
 CPPFLAGS_helgrind = -O0
 LDFLAGS_helgrind = -rdynamic
 DEFINES_helgrind = _DEBUG DEBUG
-DEFINES_helgrind += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=20
 
 VALID_CONFIG_asan-noleaks = 1
 REQUIRE_CUSTOM_LIBRARIES_asan-noleaks = 1
@@ -171,26 +120,58 @@
 LDXX_asan-noleaks = clang++
 CPPFLAGS_asan-noleaks = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_asan-noleaks = -fsanitize=address
-DEFINES_asan-noleaks += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
 
-VALID_CONFIG_edbg = 1
-CC_edbg = $(DEFAULT_CC)
-CXX_edbg = $(DEFAULT_CXX)
-LD_edbg = $(DEFAULT_CC)
-LDXX_edbg = $(DEFAULT_CXX)
-CPPFLAGS_edbg = -O0
-DEFINES_edbg = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
+VALID_CONFIG_asan-trace-cmp = 1
+REQUIRE_CUSTOM_LIBRARIES_asan-trace-cmp = 1
+CC_asan-trace-cmp = clang
+CXX_asan-trace-cmp = clang++
+LD_asan-trace-cmp = clang
+LDXX_asan-trace-cmp = clang++
+CPPFLAGS_asan-trace-cmp = -O0 -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
+LDFLAGS_asan-trace-cmp = -fsanitize=address
 
-VALID_CONFIG_ubsan = 1
-REQUIRE_CUSTOM_LIBRARIES_ubsan = 1
-CC_ubsan = clang
-CXX_ubsan = clang++
-LD_ubsan = clang
-LDXX_ubsan = clang++
-CPPFLAGS_ubsan = -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow -fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs
-LDFLAGS_ubsan = -fsanitize=undefined,unsigned-integer-overflow
-DEFINES_ubsan = NDEBUG
-DEFINES_ubsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5
+VALID_CONFIG_dbg = 1
+CC_dbg = $(DEFAULT_CC)
+CXX_dbg = $(DEFAULT_CXX)
+LD_dbg = $(DEFAULT_CC)
+LDXX_dbg = $(DEFAULT_CXX)
+CPPFLAGS_dbg = -O0
+DEFINES_dbg = _DEBUG DEBUG
+
+VALID_CONFIG_stapprof = 1
+CC_stapprof = $(DEFAULT_CC)
+CXX_stapprof = $(DEFAULT_CXX)
+LD_stapprof = $(DEFAULT_CC)
+LDXX_stapprof = $(DEFAULT_CXX)
+CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER
+DEFINES_stapprof = NDEBUG
+
+VALID_CONFIG_gcov = 1
+CC_gcov = gcc
+CXX_gcov = g++
+LD_gcov = gcc
+LDXX_gcov = g++
+CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage -Wno-return-type
+LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -rdynamic
+DEFINES_gcov = _DEBUG DEBUG GPR_GCOV
+
+VALID_CONFIG_memcheck = 1
+CC_memcheck = $(DEFAULT_CC)
+CXX_memcheck = $(DEFAULT_CXX)
+LD_memcheck = $(DEFAULT_CC)
+LDXX_memcheck = $(DEFAULT_CXX)
+CPPFLAGS_memcheck = -O0
+LDFLAGS_memcheck = -rdynamic
+DEFINES_memcheck = _DEBUG DEBUG
+
+VALID_CONFIG_asan = 1
+REQUIRE_CUSTOM_LIBRARIES_asan = 1
+CC_asan = clang
+CXX_asan = clang++
+LD_asan = clang
+LDXX_asan = clang++
+CPPFLAGS_asan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
+LDFLAGS_asan = -fsanitize=address
 
 VALID_CONFIG_tsan = 1
 REQUIRE_CUSTOM_LIBRARIES_tsan = 1
@@ -201,15 +182,26 @@
 CPPFLAGS_tsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_tsan = -fsanitize=thread
 DEFINES_tsan = GRPC_TSAN
-DEFINES_tsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
 
-VALID_CONFIG_stapprof = 1
-CC_stapprof = $(DEFAULT_CC)
-CXX_stapprof = $(DEFAULT_CXX)
-LD_stapprof = $(DEFAULT_CC)
-LDXX_stapprof = $(DEFAULT_CXX)
-CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER
-DEFINES_stapprof = NDEBUG
+VALID_CONFIG_ubsan = 1
+REQUIRE_CUSTOM_LIBRARIES_ubsan = 1
+CC_ubsan = clang
+CXX_ubsan = clang++
+LD_ubsan = clang
+LDXX_ubsan = clang++
+CPPFLAGS_ubsan = -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow -fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs
+LDFLAGS_ubsan = -fsanitize=undefined,unsigned-integer-overflow
+DEFINES_ubsan = NDEBUG
+
+VALID_CONFIG_msan = 1
+REQUIRE_CUSTOM_LIBRARIES_msan = 1
+CC_msan = clang
+CXX_msan = clang++
+LD_msan = clang
+LDXX_msan = clang++
+CPPFLAGS_msan = -O0 -fsanitize-coverage=edge -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
+LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
+DEFINES_msan = NDEBUG
 
 VALID_CONFIG_mutrace = 1
 CC_mutrace = $(DEFAULT_CC)
@@ -220,35 +212,13 @@
 LDFLAGS_mutrace = -rdynamic
 DEFINES_mutrace = NDEBUG
 
-VALID_CONFIG_memcheck = 1
-CC_memcheck = $(DEFAULT_CC)
-CXX_memcheck = $(DEFAULT_CXX)
-LD_memcheck = $(DEFAULT_CC)
-LDXX_memcheck = $(DEFAULT_CXX)
-CPPFLAGS_memcheck = -O0
-LDFLAGS_memcheck = -rdynamic
-DEFINES_memcheck = _DEBUG DEBUG
-DEFINES_memcheck += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=10
-
-VALID_CONFIG_etsan = 1
-REQUIRE_CUSTOM_LIBRARIES_etsan = 1
-CC_etsan = clang
-CXX_etsan = clang++
-LD_etsan = clang
-LDXX_etsan = clang++
-CPPFLAGS_etsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
-LDFLAGS_etsan = -fsanitize=thread
-DEFINES_etsan = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
-DEFINES_etsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
-
-VALID_CONFIG_gcov = 1
-CC_gcov = gcc
-CXX_gcov = g++
-LD_gcov = gcc
-LDXX_gcov = g++
-CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage -Wno-return-type
-LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -rdynamic
-DEFINES_gcov = _DEBUG DEBUG GPR_GCOV
+VALID_CONFIG_counters = 1
+CC_counters = $(DEFAULT_CC)
+CXX_counters = $(DEFAULT_CXX)
+LD_counters = $(DEFAULT_CC)
+LDXX_counters = $(DEFAULT_CXX)
+CPPFLAGS_counters = -O2 -DGPR_LOW_LEVEL_COUNTERS
+DEFINES_counters = NDEBUG
 
 
 
@@ -358,7 +328,7 @@
 else
 CXXFLAGS += -std=c++0x
 endif
-CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter
+CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
 LDFLAGS += -g
 
 CPPFLAGS += $(CPPFLAGS_$(CONFIG))
@@ -441,9 +411,9 @@
 Q = @
 endif
 
-CORE_VERSION = 2.0.0
-CPP_VERSION = 1.1.2
-CSHARP_VERSION = 1.1.2
+CORE_VERSION = 3.0.0-dev
+CPP_VERSION = 1.2.0-dev
+CSHARP_VERSION = 1.2.0-dev
 
 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
 CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -491,7 +461,7 @@
 SHARED_EXT_CPP = dll
 SHARED_EXT_CSHARP = dll
 SHARED_PREFIX =
-SHARED_VERSION_CORE = -2
+SHARED_VERSION_CORE = -3
 SHARED_VERSION_CPP = -1
 SHARED_VERSION_CSHARP = -1
 else ifeq ($(SYSTEM),Darwin)
@@ -937,6 +907,7 @@
 alpn_test: $(BINDIR)/$(CONFIG)/alpn_test
 api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer
 bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test
+bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
 bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
 bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
 census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
@@ -944,7 +915,6 @@
 census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test
 channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
 chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test
-chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
 chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test
 chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test
 client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer
@@ -976,6 +946,7 @@
 gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test
 gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test
 gpr_mpscq_test: $(BINDIR)/$(CONFIG)/gpr_mpscq_test
+gpr_spinlock_test: $(BINDIR)/$(CONFIG)/gpr_spinlock_test
 gpr_stack_lockfree_test: $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test
 gpr_string_test: $(BINDIR)/$(CONFIG)/gpr_string_test
 gpr_sync_test: $(BINDIR)/$(CONFIG)/gpr_sync_test
@@ -1011,9 +982,6 @@
 httpcli_test: $(BINDIR)/$(CONFIG)/httpcli_test
 httpscli_test: $(BINDIR)/$(CONFIG)/httpscli_test
 init_test: $(BINDIR)/$(CONFIG)/init_test
-internal_api_canary_iomgr_test: $(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test
-internal_api_canary_support_test: $(BINDIR)/$(CONFIG)/internal_api_canary_support_test
-internal_api_canary_transport_test: $(BINDIR)/$(CONFIG)/internal_api_canary_transport_test
 invalid_call_argument_test: $(BINDIR)/$(CONFIG)/invalid_call_argument_test
 json_fuzzer_test: $(BINDIR)/$(CONFIG)/json_fuzzer_test
 json_rewrite: $(BINDIR)/$(CONFIG)/json_rewrite
@@ -1037,6 +1005,8 @@
 percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
 percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer
 percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test
+pollset_set_test: $(BINDIR)/$(CONFIG)/pollset_set_test
+resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test
 resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test
 resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test
 secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test
@@ -1053,6 +1023,7 @@
 sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test
 socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test
 ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer
+status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test
 tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test
 tcp_client_uv_test: $(BINDIR)/$(CONFIG)/tcp_client_uv_test
 tcp_posix_test: $(BINDIR)/$(CONFIG)/tcp_posix_test
@@ -1073,7 +1044,13 @@
 alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test
 async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
 auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test
+bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create
+bm_chttp2_hpack: $(BINDIR)/$(CONFIG)/bm_chttp2_hpack
+bm_closure: $(BINDIR)/$(CONFIG)/bm_closure
+bm_cq: $(BINDIR)/$(CONFIG)/bm_cq
+bm_error: $(BINDIR)/$(CONFIG)/bm_error
 bm_fullstack: $(BINDIR)/$(CONFIG)/bm_fullstack
+bm_metadata: $(BINDIR)/$(CONFIG)/bm_metadata
 channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
 channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test
 cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test
@@ -1101,6 +1078,7 @@
 grpc_tool_test: $(BINDIR)/$(CONFIG)/grpc_tool_test
 grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test
 grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test
+health_service_end2end_test: $(BINDIR)/$(CONFIG)/health_service_end2end_test
 http2_client: $(BINDIR)/$(CONFIG)/http2_client
 hybrid_end2end_test: $(BINDIR)/$(CONFIG)/hybrid_end2end_test
 interop_client: $(BINDIR)/$(CONFIG)/interop_client
@@ -1111,6 +1089,7 @@
 mock_test: $(BINDIR)/$(CONFIG)/mock_test
 noop-benchmark: $(BINDIR)/$(CONFIG)/noop-benchmark
 proto_server_reflection_test: $(BINDIR)/$(CONFIG)/proto_server_reflection_test
+proto_utils_test: $(BINDIR)/$(CONFIG)/proto_utils_test
 qps_interarrival_test: $(BINDIR)/$(CONFIG)/qps_interarrival_test
 qps_json_driver: $(BINDIR)/$(CONFIG)/qps_json_driver
 qps_openloop_test: $(BINDIR)/$(CONFIG)/qps_openloop_test
@@ -1130,6 +1109,7 @@
 stress_test: $(BINDIR)/$(CONFIG)/stress_test
 thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test
 thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
+writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test
 public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89
 boringssl_aes_test: $(BINDIR)/$(CONFIG)/boringssl_aes_test
 boringssl_asn1_test: $(BINDIR)/$(CONFIG)/boringssl_asn1_test
@@ -1285,9 +1265,9 @@
 pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
 
 ifeq ($(EMBED_OPENSSL),true)
-privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
+privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
 else
-privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
+privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
 endif
 
 
@@ -1299,6 +1279,7 @@
   $(BINDIR)/$(CONFIG)/alloc_test \
   $(BINDIR)/$(CONFIG)/alpn_test \
   $(BINDIR)/$(CONFIG)/bad_server_response_test \
+  $(BINDIR)/$(CONFIG)/bdp_estimator_test \
   $(BINDIR)/$(CONFIG)/bin_decoder_test \
   $(BINDIR)/$(CONFIG)/bin_encoder_test \
   $(BINDIR)/$(CONFIG)/census_context_test \
@@ -1306,7 +1287,6 @@
   $(BINDIR)/$(CONFIG)/census_trace_context_test \
   $(BINDIR)/$(CONFIG)/channel_create_test \
   $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \
-  $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \
   $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \
   $(BINDIR)/$(CONFIG)/chttp2_varint_test \
   $(BINDIR)/$(CONFIG)/combiner_test \
@@ -1334,6 +1314,7 @@
   $(BINDIR)/$(CONFIG)/gpr_host_port_test \
   $(BINDIR)/$(CONFIG)/gpr_log_test \
   $(BINDIR)/$(CONFIG)/gpr_mpscq_test \
+  $(BINDIR)/$(CONFIG)/gpr_spinlock_test \
   $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test \
   $(BINDIR)/$(CONFIG)/gpr_string_test \
   $(BINDIR)/$(CONFIG)/gpr_sync_test \
@@ -1363,9 +1344,6 @@
   $(BINDIR)/$(CONFIG)/httpcli_test \
   $(BINDIR)/$(CONFIG)/httpscli_test \
   $(BINDIR)/$(CONFIG)/init_test \
-  $(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test \
-  $(BINDIR)/$(CONFIG)/internal_api_canary_support_test \
-  $(BINDIR)/$(CONFIG)/internal_api_canary_transport_test \
   $(BINDIR)/$(CONFIG)/invalid_call_argument_test \
   $(BINDIR)/$(CONFIG)/json_rewrite \
   $(BINDIR)/$(CONFIG)/json_rewrite_test \
@@ -1383,6 +1361,8 @@
   $(BINDIR)/$(CONFIG)/murmur_hash_test \
   $(BINDIR)/$(CONFIG)/no_server_test \
   $(BINDIR)/$(CONFIG)/percent_encoding_test \
+  $(BINDIR)/$(CONFIG)/pollset_set_test \
+  $(BINDIR)/$(CONFIG)/resolve_address_posix_test \
   $(BINDIR)/$(CONFIG)/resolve_address_test \
   $(BINDIR)/$(CONFIG)/resource_quota_test \
   $(BINDIR)/$(CONFIG)/secure_channel_create_test \
@@ -1397,6 +1377,7 @@
   $(BINDIR)/$(CONFIG)/sockaddr_resolver_test \
   $(BINDIR)/$(CONFIG)/sockaddr_utils_test \
   $(BINDIR)/$(CONFIG)/socket_utils_test \
+  $(BINDIR)/$(CONFIG)/status_conversion_test \
   $(BINDIR)/$(CONFIG)/tcp_client_posix_test \
   $(BINDIR)/$(CONFIG)/tcp_client_uv_test \
   $(BINDIR)/$(CONFIG)/tcp_posix_test \
@@ -1477,7 +1458,13 @@
   $(BINDIR)/$(CONFIG)/alarm_cpp_test \
   $(BINDIR)/$(CONFIG)/async_end2end_test \
   $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
+  $(BINDIR)/$(CONFIG)/bm_call_create \
+  $(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
+  $(BINDIR)/$(CONFIG)/bm_closure \
+  $(BINDIR)/$(CONFIG)/bm_cq \
+  $(BINDIR)/$(CONFIG)/bm_error \
   $(BINDIR)/$(CONFIG)/bm_fullstack \
+  $(BINDIR)/$(CONFIG)/bm_metadata \
   $(BINDIR)/$(CONFIG)/channel_arguments_test \
   $(BINDIR)/$(CONFIG)/channel_filter_test \
   $(BINDIR)/$(CONFIG)/cli_call_test \
@@ -1498,6 +1485,7 @@
   $(BINDIR)/$(CONFIG)/grpc_tool_test \
   $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/grpclb_test \
+  $(BINDIR)/$(CONFIG)/health_service_end2end_test \
   $(BINDIR)/$(CONFIG)/http2_client \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
   $(BINDIR)/$(CONFIG)/interop_client \
@@ -1508,6 +1496,7 @@
   $(BINDIR)/$(CONFIG)/mock_test \
   $(BINDIR)/$(CONFIG)/noop-benchmark \
   $(BINDIR)/$(CONFIG)/proto_server_reflection_test \
+  $(BINDIR)/$(CONFIG)/proto_utils_test \
   $(BINDIR)/$(CONFIG)/qps_interarrival_test \
   $(BINDIR)/$(CONFIG)/qps_json_driver \
   $(BINDIR)/$(CONFIG)/qps_openloop_test \
@@ -1527,6 +1516,7 @@
   $(BINDIR)/$(CONFIG)/stress_test \
   $(BINDIR)/$(CONFIG)/thread_manager_test \
   $(BINDIR)/$(CONFIG)/thread_stress_test \
+  $(BINDIR)/$(CONFIG)/writes_per_rpc_test \
   $(BINDIR)/$(CONFIG)/boringssl_aes_test \
   $(BINDIR)/$(CONFIG)/boringssl_asn1_test \
   $(BINDIR)/$(CONFIG)/boringssl_base64_test \
@@ -1579,7 +1569,13 @@
   $(BINDIR)/$(CONFIG)/alarm_cpp_test \
   $(BINDIR)/$(CONFIG)/async_end2end_test \
   $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
+  $(BINDIR)/$(CONFIG)/bm_call_create \
+  $(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
+  $(BINDIR)/$(CONFIG)/bm_closure \
+  $(BINDIR)/$(CONFIG)/bm_cq \
+  $(BINDIR)/$(CONFIG)/bm_error \
   $(BINDIR)/$(CONFIG)/bm_fullstack \
+  $(BINDIR)/$(CONFIG)/bm_metadata \
   $(BINDIR)/$(CONFIG)/channel_arguments_test \
   $(BINDIR)/$(CONFIG)/channel_filter_test \
   $(BINDIR)/$(CONFIG)/cli_call_test \
@@ -1600,6 +1596,7 @@
   $(BINDIR)/$(CONFIG)/grpc_tool_test \
   $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/grpclb_test \
+  $(BINDIR)/$(CONFIG)/health_service_end2end_test \
   $(BINDIR)/$(CONFIG)/http2_client \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
   $(BINDIR)/$(CONFIG)/interop_client \
@@ -1610,6 +1607,7 @@
   $(BINDIR)/$(CONFIG)/mock_test \
   $(BINDIR)/$(CONFIG)/noop-benchmark \
   $(BINDIR)/$(CONFIG)/proto_server_reflection_test \
+  $(BINDIR)/$(CONFIG)/proto_utils_test \
   $(BINDIR)/$(CONFIG)/qps_interarrival_test \
   $(BINDIR)/$(CONFIG)/qps_json_driver \
   $(BINDIR)/$(CONFIG)/qps_openloop_test \
@@ -1629,6 +1627,7 @@
   $(BINDIR)/$(CONFIG)/stress_test \
   $(BINDIR)/$(CONFIG)/thread_manager_test \
   $(BINDIR)/$(CONFIG)/thread_stress_test \
+  $(BINDIR)/$(CONFIG)/writes_per_rpc_test \
 
 endif
 
@@ -1648,6 +1647,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/alpn_test || ( echo test alpn_test failed ; exit 1 )
 	$(E) "[RUN]     Testing bad_server_response_test"
 	$(Q) $(BINDIR)/$(CONFIG)/bad_server_response_test || ( echo test bad_server_response_test failed ; exit 1 )
+	$(E) "[RUN]     Testing bdp_estimator_test"
+	$(Q) $(BINDIR)/$(CONFIG)/bdp_estimator_test || ( echo test bdp_estimator_test failed ; exit 1 )
 	$(E) "[RUN]     Testing bin_decoder_test"
 	$(Q) $(BINDIR)/$(CONFIG)/bin_decoder_test || ( echo test bin_decoder_test failed ; exit 1 )
 	$(E) "[RUN]     Testing bin_encoder_test"
@@ -1662,8 +1663,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 )
 	$(E) "[RUN]     Testing chttp2_hpack_encoder_test"
 	$(Q) $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test || ( echo test chttp2_hpack_encoder_test failed ; exit 1 )
-	$(E) "[RUN]     Testing chttp2_status_conversion_test"
-	$(Q) $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test || ( echo test chttp2_status_conversion_test failed ; exit 1 )
 	$(E) "[RUN]     Testing chttp2_stream_map_test"
 	$(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 )
 	$(E) "[RUN]     Testing chttp2_varint_test"
@@ -1714,6 +1713,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_log_test || ( echo test gpr_log_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_mpscq_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_mpscq_test || ( echo test gpr_mpscq_test failed ; exit 1 )
+	$(E) "[RUN]     Testing gpr_spinlock_test"
+	$(Q) $(BINDIR)/$(CONFIG)/gpr_spinlock_test || ( echo test gpr_spinlock_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_stack_lockfree_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test || ( echo test gpr_stack_lockfree_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_string_test"
@@ -1794,6 +1795,10 @@
 	$(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 )
 	$(E) "[RUN]     Testing percent_encoding_test"
 	$(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 )
+	$(E) "[RUN]     Testing pollset_set_test"
+	$(Q) $(BINDIR)/$(CONFIG)/pollset_set_test || ( echo test pollset_set_test failed ; exit 1 )
+	$(E) "[RUN]     Testing resolve_address_posix_test"
+	$(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 )
 	$(E) "[RUN]     Testing resolve_address_test"
 	$(Q) $(BINDIR)/$(CONFIG)/resolve_address_test || ( echo test resolve_address_test failed ; exit 1 )
 	$(E) "[RUN]     Testing resource_quota_test"
@@ -1822,6 +1827,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/sockaddr_utils_test || ( echo test sockaddr_utils_test failed ; exit 1 )
 	$(E) "[RUN]     Testing socket_utils_test"
 	$(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 )
+	$(E) "[RUN]     Testing status_conversion_test"
+	$(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 )
 	$(E) "[RUN]     Testing tcp_client_posix_test"
 	$(Q) $(BINDIR)/$(CONFIG)/tcp_client_posix_test || ( echo test tcp_client_posix_test failed ; exit 1 )
 	$(E) "[RUN]     Testing tcp_client_uv_test"
@@ -1881,8 +1888,6 @@
 
 
 flaky_test_c: buildtests_c
-	$(E) "[RUN]     Testing lb_policies_test"
-	$(Q) $(BINDIR)/$(CONFIG)/lb_policies_test || ( echo test lb_policies_test failed ; exit 1 )
 	$(E) "[RUN]     Testing mlog_test"
 	$(Q) $(BINDIR)/$(CONFIG)/mlog_test || ( echo test mlog_test failed ; exit 1 )
 
@@ -1894,8 +1899,20 @@
 	$(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 )
 	$(E) "[RUN]     Testing auth_property_iterator_test"
 	$(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 )
+	$(E) "[RUN]     Testing bm_call_create"
+	$(Q) $(BINDIR)/$(CONFIG)/bm_call_create || ( echo test bm_call_create failed ; exit 1 )
+	$(E) "[RUN]     Testing bm_chttp2_hpack"
+	$(Q) $(BINDIR)/$(CONFIG)/bm_chttp2_hpack || ( echo test bm_chttp2_hpack failed ; exit 1 )
+	$(E) "[RUN]     Testing bm_closure"
+	$(Q) $(BINDIR)/$(CONFIG)/bm_closure || ( echo test bm_closure failed ; exit 1 )
+	$(E) "[RUN]     Testing bm_cq"
+	$(Q) $(BINDIR)/$(CONFIG)/bm_cq || ( echo test bm_cq failed ; exit 1 )
+	$(E) "[RUN]     Testing bm_error"
+	$(Q) $(BINDIR)/$(CONFIG)/bm_error || ( echo test bm_error failed ; exit 1 )
 	$(E) "[RUN]     Testing bm_fullstack"
 	$(Q) $(BINDIR)/$(CONFIG)/bm_fullstack || ( echo test bm_fullstack failed ; exit 1 )
+	$(E) "[RUN]     Testing bm_metadata"
+	$(Q) $(BINDIR)/$(CONFIG)/bm_metadata || ( echo test bm_metadata failed ; exit 1 )
 	$(E) "[RUN]     Testing channel_arguments_test"
 	$(Q) $(BINDIR)/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 )
 	$(E) "[RUN]     Testing channel_filter_test"
@@ -1932,8 +1949,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/grpclb_api_test || ( echo test grpclb_api_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpclb_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpclb_test || ( echo test grpclb_test failed ; exit 1 )
-	$(E) "[RUN]     Testing hybrid_end2end_test"
-	$(Q) $(BINDIR)/$(CONFIG)/hybrid_end2end_test || ( echo test hybrid_end2end_test failed ; exit 1 )
+	$(E) "[RUN]     Testing health_service_end2end_test"
+	$(Q) $(BINDIR)/$(CONFIG)/health_service_end2end_test || ( echo test health_service_end2end_test failed ; exit 1 )
 	$(E) "[RUN]     Testing interop_test"
 	$(Q) $(BINDIR)/$(CONFIG)/interop_test || ( echo test interop_test failed ; exit 1 )
 	$(E) "[RUN]     Testing mock_test"
@@ -1942,6 +1959,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/noop-benchmark || ( echo test noop-benchmark failed ; exit 1 )
 	$(E) "[RUN]     Testing proto_server_reflection_test"
 	$(Q) $(BINDIR)/$(CONFIG)/proto_server_reflection_test || ( echo test proto_server_reflection_test failed ; exit 1 )
+	$(E) "[RUN]     Testing proto_utils_test"
+	$(Q) $(BINDIR)/$(CONFIG)/proto_utils_test || ( echo test proto_utils_test failed ; exit 1 )
 	$(E) "[RUN]     Testing qps_openloop_test"
 	$(Q) $(BINDIR)/$(CONFIG)/qps_openloop_test || ( echo test qps_openloop_test failed ; exit 1 )
 	$(E) "[RUN]     Testing round_robin_end2end_test"
@@ -1966,9 +1985,13 @@
 	$(Q) $(BINDIR)/$(CONFIG)/thread_manager_test || ( echo test thread_manager_test failed ; exit 1 )
 	$(E) "[RUN]     Testing thread_stress_test"
 	$(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 )
+	$(E) "[RUN]     Testing writes_per_rpc_test"
+	$(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 )
 
 
 flaky_test_cxx: buildtests_cxx
+	$(E) "[RUN]     Testing hybrid_end2end_test"
+	$(Q) $(BINDIR)/$(CONFIG)/hybrid_end2end_test || ( echo test hybrid_end2end_test failed ; exit 1 )
 
 
 test_python: static_c
@@ -2077,6 +2100,21 @@
 	$(Q) echo "$(GRPCXX_UNSECURE_PC_FILE)" | tr , '\n' >$@
 
 ifeq ($(NO_PROTOC),true)
+$(GENDIR)/src/proto/grpc/health/v1/health.pb.cc: protoc_dep_error
+$(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc: protoc_dep_error
+else
+$(GENDIR)/src/proto/grpc/health/v1/health.pb.cc: src/proto/grpc/health/v1/health.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+	$(E) "[PROTOC]  Generating protobuf CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
+
+$(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc: src/proto/grpc/health/v1/health.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
+endif
+
+ifeq ($(NO_PROTOC),true)
 $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: protoc_dep_error
 $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: protoc_dep_error
 else
@@ -2380,7 +2418,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgpr.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -2389,7 +2427,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -2398,7 +2436,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_cronet.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -2407,7 +2445,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_unsecure.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so
 endif
 ifneq ($(SYSTEM),MINGW32)
@@ -2424,7 +2462,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
@@ -2433,7 +2471,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_cronet.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
@@ -2442,7 +2480,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_reflection.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
@@ -2451,7 +2489,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_unsecure.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so
 endif
 ifneq ($(SYSTEM),MINGW32)
@@ -2468,7 +2506,7 @@
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a $(prefix)/lib/libgrpc_csharp_ext.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so.2
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so
 endif
 ifneq ($(SYSTEM),MINGW32)
@@ -2632,8 +2670,8 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBS)
 else
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.2 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.2
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.3 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBS)
+	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.3
 	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -2754,6 +2792,8 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
+    src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
     src/core/lib/surface/api_trace.c \
@@ -2773,14 +2813,16 @@
     src/core/lib/surface/server.c \
     src/core/lib/surface/validate_metadata.c \
     src/core/lib/surface/version.c \
+    src/core/lib/transport/bdp_estimator.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
+    src/core/lib/transport/error_utils.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/pid_controller.c \
     src/core/lib/transport/service_config.c \
     src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/status_conversion.c \
     src/core/lib/transport/timeout_encoding.c \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
@@ -2801,7 +2843,6 @@
     src/core/ext/transport/chttp2/transport/huffsyms.c \
     src/core/ext/transport/chttp2/transport/incoming_metadata.c \
     src/core/ext/transport/chttp2/transport/parsing.c \
-    src/core/ext/transport/chttp2/transport/status_conversion.c \
     src/core/ext/transport/chttp2/transport/stream_lists.c \
     src/core/ext/transport/chttp2/transport/stream_map.c \
     src/core/ext/transport/chttp2/transport/varint.c \
@@ -2823,6 +2864,7 @@
     src/core/lib/security/credentials/plugin/plugin_credentials.c \
     src/core/lib/security/credentials/ssl/ssl_credentials.c \
     src/core/lib/security/transport/client_auth_filter.c \
+    src/core/lib/security/transport/lb_targets_info.c \
     src/core/lib/security/transport/secure_endpoint.c \
     src/core/lib/security/transport/security_connector.c \
     src/core/lib/security/transport/security_handshaker.c \
@@ -2843,11 +2885,14 @@
     src/core/ext/client_channel/connector.c \
     src/core/ext/client_channel/default_initial_connect_string.c \
     src/core/ext/client_channel/http_connect_handshaker.c \
+    src/core/ext/client_channel/http_proxy.c \
     src/core/ext/client_channel/initial_connect_string.c \
     src/core/ext/client_channel/lb_policy.c \
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
@@ -2860,6 +2905,7 @@
     src/core/ext/transport/chttp2/client/insecure/channel_create.c \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
     src/core/ext/lb_policy/grpclb/grpclb.c \
+    src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c \
     src/core/ext/lb_policy/grpclb/load_balancer_api.c \
     src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
     third_party/nanopb/pb_common.c \
@@ -2894,6 +2940,7 @@
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
@@ -2956,8 +3003,8 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
 else
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.2
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
+	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -3057,6 +3104,8 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
+    src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
     src/core/lib/surface/api_trace.c \
@@ -3076,14 +3125,16 @@
     src/core/lib/surface/server.c \
     src/core/lib/surface/validate_metadata.c \
     src/core/lib/surface/version.c \
+    src/core/lib/transport/bdp_estimator.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
+    src/core/lib/transport/error_utils.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/pid_controller.c \
     src/core/lib/transport/service_config.c \
     src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/status_conversion.c \
     src/core/lib/transport/timeout_encoding.c \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
@@ -3107,7 +3158,6 @@
     src/core/ext/transport/chttp2/transport/huffsyms.c \
     src/core/ext/transport/chttp2/transport/incoming_metadata.c \
     src/core/ext/transport/chttp2/transport/parsing.c \
-    src/core/ext/transport/chttp2/transport/status_conversion.c \
     src/core/ext/transport/chttp2/transport/stream_lists.c \
     src/core/ext/transport/chttp2/transport/stream_map.c \
     src/core/ext/transport/chttp2/transport/varint.c \
@@ -3120,11 +3170,14 @@
     src/core/ext/client_channel/connector.c \
     src/core/ext/client_channel/default_initial_connect_string.c \
     src/core/ext/client_channel/http_connect_handshaker.c \
+    src/core/ext/client_channel/http_proxy.c \
     src/core/ext/client_channel/initial_connect_string.c \
     src/core/ext/client_channel/lb_policy.c \
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
@@ -3147,6 +3200,7 @@
     src/core/lib/security/credentials/plugin/plugin_credentials.c \
     src/core/lib/security/credentials/ssl/ssl_credentials.c \
     src/core/lib/security/transport/client_auth_filter.c \
+    src/core/lib/security/transport/lb_targets_info.c \
     src/core/lib/security/transport/secure_endpoint.c \
     src/core/lib/security/transport/security_connector.c \
     src/core/lib/security/transport/security_handshaker.c \
@@ -3159,6 +3213,8 @@
     src/core/lib/tsi/ssl_transport_security.c \
     src/core/lib/tsi/transport_security.c \
     src/core/ext/transport/chttp2/client/chttp2_connector.c \
+    src/core/ext/load_reporting/load_reporting.c \
+    src/core/ext/load_reporting/load_reporting_filter.c \
     src/core/plugin_registry/grpc_cronet_plugin_registry.c \
 
 PUBLIC_HEADERS_C += \
@@ -3168,6 +3224,7 @@
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
@@ -3230,8 +3287,8 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
 else
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_cronet.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.2
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_cronet.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -3256,6 +3313,7 @@
     test/core/end2end/fixtures/http_proxy.c \
     test/core/end2end/fixtures/proxy.c \
     test/core/iomgr/endpoint_tests.c \
+    test/core/util/debugger_macros.c \
     test/core/util/grpc_profiler.c \
     test/core/util/memory_counters.c \
     test/core/util/mock_endpoint.c \
@@ -3266,6 +3324,7 @@
     test/core/util/port_uv.c \
     test/core/util/port_windows.c \
     test/core/util/slice_splitter.c \
+    test/core/util/trickle_endpoint.c \
     src/core/lib/channel/channel_args.c \
     src/core/lib/channel/channel_stack.c \
     src/core/lib/channel/channel_stack_builder.c \
@@ -3350,6 +3409,8 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
+    src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
     src/core/lib/surface/api_trace.c \
@@ -3369,14 +3430,16 @@
     src/core/lib/surface/server.c \
     src/core/lib/surface/validate_metadata.c \
     src/core/lib/surface/version.c \
+    src/core/lib/transport/bdp_estimator.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
+    src/core/lib/transport/error_utils.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/pid_controller.c \
     src/core/lib/transport/service_config.c \
     src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/status_conversion.c \
     src/core/lib/transport/timeout_encoding.c \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
@@ -3388,6 +3451,7 @@
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
@@ -3451,6 +3515,7 @@
     test/core/end2end/fixtures/http_proxy.c \
     test/core/end2end/fixtures/proxy.c \
     test/core/iomgr/endpoint_tests.c \
+    test/core/util/debugger_macros.c \
     test/core/util/grpc_profiler.c \
     test/core/util/memory_counters.c \
     test/core/util/mock_endpoint.c \
@@ -3461,6 +3526,7 @@
     test/core/util/port_uv.c \
     test/core/util/port_windows.c \
     test/core/util/slice_splitter.c \
+    test/core/util/trickle_endpoint.c \
 
 PUBLIC_HEADERS_C += \
 
@@ -3571,6 +3637,8 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
+    src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
     src/core/lib/surface/api_trace.c \
@@ -3590,14 +3658,16 @@
     src/core/lib/surface/server.c \
     src/core/lib/surface/validate_metadata.c \
     src/core/lib/surface/version.c \
+    src/core/lib/transport/bdp_estimator.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
+    src/core/lib/transport/error_utils.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/pid_controller.c \
     src/core/lib/transport/service_config.c \
     src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/status_conversion.c \
     src/core/lib/transport/timeout_encoding.c \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
@@ -3619,7 +3689,6 @@
     src/core/ext/transport/chttp2/transport/huffsyms.c \
     src/core/ext/transport/chttp2/transport/incoming_metadata.c \
     src/core/ext/transport/chttp2/transport/parsing.c \
-    src/core/ext/transport/chttp2/transport/status_conversion.c \
     src/core/ext/transport/chttp2/transport/stream_lists.c \
     src/core/ext/transport/chttp2/transport/stream_map.c \
     src/core/ext/transport/chttp2/transport/varint.c \
@@ -3636,11 +3705,14 @@
     src/core/ext/client_channel/connector.c \
     src/core/ext/client_channel/default_initial_connect_string.c \
     src/core/ext/client_channel/http_connect_handshaker.c \
+    src/core/ext/client_channel/http_proxy.c \
     src/core/ext/client_channel/initial_connect_string.c \
     src/core/ext/client_channel/lb_policy.c \
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
@@ -3652,6 +3724,7 @@
     src/core/ext/load_reporting/load_reporting.c \
     src/core/ext/load_reporting/load_reporting_filter.c \
     src/core/ext/lb_policy/grpclb/grpclb.c \
+    src/core/ext/lb_policy/grpclb/grpclb_channel.c \
     src/core/ext/lb_policy/grpclb/load_balancer_api.c \
     src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
     third_party/nanopb/pb_common.c \
@@ -3682,6 +3755,7 @@
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
@@ -3732,8 +3806,8 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
 else
-	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.2
+	$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.3
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -3847,6 +3921,10 @@
     src/cpp/server/async_generic_service.cc \
     src/cpp/server/create_default_thread_pool.cc \
     src/cpp/server/dynamic_thread_pool.cc \
+    src/cpp/server/health/default_health_check_service.cc \
+    src/cpp/server/health/health.pb.c \
+    src/cpp/server/health/health_check_service.cc \
+    src/cpp/server/health/health_check_service_server_builder_option.cc \
     src/cpp/server/server_builder.cc \
     src/cpp/server/server_cc.cc \
     src/cpp/server/server_context.cc \
@@ -3867,9 +3945,11 @@
     include/grpc++/completion_queue.h \
     include/grpc++/create_channel.h \
     include/grpc++/create_channel_posix.h \
+    include/grpc++/ext/health_check_service_server_builder_option.h \
     include/grpc++/generic/async_generic_service.h \
     include/grpc++/generic/generic_stub.h \
     include/grpc++/grpc++.h \
+    include/grpc++/health_check_service_interface.h \
     include/grpc++/impl/call.h \
     include/grpc++/impl/client_unary_call.h \
     include/grpc++/impl/codegen/core_codegen.h \
@@ -3916,6 +3996,7 @@
     include/grpc++/impl/codegen/core_codegen_interface.h \
     include/grpc++/impl/codegen/create_auth_context.h \
     include/grpc++/impl/codegen/grpc_library.h \
+    include/grpc++/impl/codegen/metadata_map.h \
     include/grpc++/impl/codegen/method_handler_impl.h \
     include/grpc++/impl/codegen/rpc_method.h \
     include/grpc++/impl/codegen/rpc_service_method.h \
@@ -3924,6 +4005,7 @@
     include/grpc++/impl/codegen/server_context.h \
     include/grpc++/impl/codegen/server_interface.h \
     include/grpc++/impl/codegen/service_type.h \
+    include/grpc++/impl/codegen/slice.h \
     include/grpc++/impl/codegen/status.h \
     include/grpc++/impl/codegen/status_code_enum.h \
     include/grpc++/impl/codegen/status_helper.h \
@@ -3950,6 +4032,8 @@
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
+    include/grpc++/impl/codegen/proto_utils.h \
+    include/grpc++/impl/codegen/config_protobuf.h \
 
 LIBGRPC++_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_SRC))))
 
@@ -3997,7 +4081,7 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so
 endif
@@ -4036,6 +4120,10 @@
     src/cpp/server/async_generic_service.cc \
     src/cpp/server/create_default_thread_pool.cc \
     src/cpp/server/dynamic_thread_pool.cc \
+    src/cpp/server/health/default_health_check_service.cc \
+    src/cpp/server/health/health.pb.c \
+    src/cpp/server/health/health_check_service.cc \
+    src/cpp/server/health/health_check_service_server_builder_option.cc \
     src/cpp/server/server_builder.cc \
     src/cpp/server/server_cc.cc \
     src/cpp/server/server_context.cc \
@@ -4067,7 +4155,6 @@
     src/core/ext/transport/chttp2/transport/huffsyms.c \
     src/core/ext/transport/chttp2/transport/incoming_metadata.c \
     src/core/ext/transport/chttp2/transport/parsing.c \
-    src/core/ext/transport/chttp2/transport/status_conversion.c \
     src/core/ext/transport/chttp2/transport/stream_lists.c \
     src/core/ext/transport/chttp2/transport/stream_map.c \
     src/core/ext/transport/chttp2/transport/varint.c \
@@ -4156,6 +4243,8 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
+    src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
     src/core/lib/surface/api_trace.c \
@@ -4175,14 +4264,16 @@
     src/core/lib/surface/server.c \
     src/core/lib/surface/validate_metadata.c \
     src/core/lib/surface/version.c \
+    src/core/lib/transport/bdp_estimator.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
+    src/core/lib/transport/error_utils.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/pid_controller.c \
     src/core/lib/transport/service_config.c \
     src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/status_conversion.c \
     src/core/lib/transport/timeout_encoding.c \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
@@ -4194,11 +4285,14 @@
     src/core/ext/client_channel/connector.c \
     src/core/ext/client_channel/default_initial_connect_string.c \
     src/core/ext/client_channel/http_connect_handshaker.c \
+    src/core/ext/client_channel/http_proxy.c \
     src/core/ext/client_channel/initial_connect_string.c \
     src/core/ext/client_channel/lb_policy.c \
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
@@ -4233,9 +4327,11 @@
     include/grpc++/completion_queue.h \
     include/grpc++/create_channel.h \
     include/grpc++/create_channel_posix.h \
+    include/grpc++/ext/health_check_service_server_builder_option.h \
     include/grpc++/generic/async_generic_service.h \
     include/grpc++/generic/generic_stub.h \
     include/grpc++/grpc++.h \
+    include/grpc++/health_check_service_interface.h \
     include/grpc++/impl/call.h \
     include/grpc++/impl/client_unary_call.h \
     include/grpc++/impl/codegen/core_codegen.h \
@@ -4282,6 +4378,7 @@
     include/grpc++/impl/codegen/core_codegen_interface.h \
     include/grpc++/impl/codegen/create_auth_context.h \
     include/grpc++/impl/codegen/grpc_library.h \
+    include/grpc++/impl/codegen/metadata_map.h \
     include/grpc++/impl/codegen/method_handler_impl.h \
     include/grpc++/impl/codegen/rpc_method.h \
     include/grpc++/impl/codegen/rpc_service_method.h \
@@ -4290,6 +4387,7 @@
     include/grpc++/impl/codegen/server_context.h \
     include/grpc++/impl/codegen/server_interface.h \
     include/grpc++/impl/codegen/service_type.h \
+    include/grpc++/impl/codegen/slice.h \
     include/grpc++/impl/codegen/status.h \
     include/grpc++/impl/codegen/status_code_enum.h \
     include/grpc++/impl/codegen/status_helper.h \
@@ -4322,6 +4420,7 @@
     include/grpc/grpc.h \
     include/grpc/grpc_posix.h \
     include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
     include/grpc/slice.h \
     include/grpc/slice_buffer.h \
     include/grpc/status.h \
@@ -4373,7 +4472,7 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so
 endif
@@ -4496,7 +4595,7 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_reflection.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_reflection.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so
 endif
@@ -4515,55 +4614,6 @@
 $(OBJDIR)/$(CONFIG)/src/cpp/ext/proto_server_reflection_plugin.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc
 
 
-LIBGRPC++_TEST_SRC = \
-    src/cpp/test/server_context_test_spouse.cc \
-
-PUBLIC_HEADERS_CXX += \
-
-LIBGRPC++_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_SRC))))
-
-
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure libraries if you don't have OpenSSL.
-
-$(LIBDIR)/$(CONFIG)/libgrpc++_test.a: openssl_dep_error
-
-
-else
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
-
-$(LIBDIR)/$(CONFIG)/libgrpc++_test.a: protobuf_dep_error
-
-
-else
-
-$(LIBDIR)/$(CONFIG)/libgrpc++_test.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_TEST_OBJS) 
-	$(E) "[AR]      Creating $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_test.a
-	$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBGRPC++_TEST_OBJS) 
-ifeq ($(SYSTEM),Darwin)
-	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_test.a
-endif
-
-
-
-
-endif
-
-endif
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(LIBGRPC++_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 LIBGRPC++_TEST_CONFIG_SRC = \
     test/cpp/util/test_config_cc.cc \
 
@@ -4614,6 +4664,7 @@
 
 
 LIBGRPC++_TEST_UTIL_SRC = \
+    $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc \
@@ -4639,6 +4690,7 @@
     include/grpc++/impl/codegen/core_codegen_interface.h \
     include/grpc++/impl/codegen/create_auth_context.h \
     include/grpc++/impl/codegen/grpc_library.h \
+    include/grpc++/impl/codegen/metadata_map.h \
     include/grpc++/impl/codegen/method_handler_impl.h \
     include/grpc++/impl/codegen/rpc_method.h \
     include/grpc++/impl/codegen/rpc_service_method.h \
@@ -4647,6 +4699,7 @@
     include/grpc++/impl/codegen/server_context.h \
     include/grpc++/impl/codegen/server_interface.h \
     include/grpc++/impl/codegen/service_type.h \
+    include/grpc++/impl/codegen/slice.h \
     include/grpc++/impl/codegen/status.h \
     include/grpc++/impl/codegen/status_code_enum.h \
     include/grpc++/impl/codegen/status_helper.h \
@@ -4720,13 +4773,13 @@
 -include $(LIBGRPC++_TEST_UTIL_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/end2end/test_service_impl.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/util/byte_buffer_proto_helper.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/util/create_test_channel.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/util/string_ref_helper.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/util/subprocess.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/util/test_credentials_provider.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/end2end/test_service_impl.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/byte_buffer_proto_helper.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/create_test_channel.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/string_ref_helper.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/subprocess.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/test_credentials_provider.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/health/v1/health.pb.cc $(GENDIR)/src/proto/grpc/health/v1/health.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc
 
 
 LIBGRPC++_UNSECURE_SRC = \
@@ -4750,6 +4803,10 @@
     src/cpp/server/async_generic_service.cc \
     src/cpp/server/create_default_thread_pool.cc \
     src/cpp/server/dynamic_thread_pool.cc \
+    src/cpp/server/health/default_health_check_service.cc \
+    src/cpp/server/health/health.pb.c \
+    src/cpp/server/health/health_check_service.cc \
+    src/cpp/server/health/health_check_service_server_builder_option.cc \
     src/cpp/server/server_builder.cc \
     src/cpp/server/server_cc.cc \
     src/cpp/server/server_context.cc \
@@ -4770,9 +4827,11 @@
     include/grpc++/completion_queue.h \
     include/grpc++/create_channel.h \
     include/grpc++/create_channel_posix.h \
+    include/grpc++/ext/health_check_service_server_builder_option.h \
     include/grpc++/generic/async_generic_service.h \
     include/grpc++/generic/generic_stub.h \
     include/grpc++/grpc++.h \
+    include/grpc++/health_check_service_interface.h \
     include/grpc++/impl/call.h \
     include/grpc++/impl/client_unary_call.h \
     include/grpc++/impl/codegen/core_codegen.h \
@@ -4819,6 +4878,7 @@
     include/grpc++/impl/codegen/core_codegen_interface.h \
     include/grpc++/impl/codegen/create_auth_context.h \
     include/grpc++/impl/codegen/grpc_library.h \
+    include/grpc++/impl/codegen/metadata_map.h \
     include/grpc++/impl/codegen/method_handler_impl.h \
     include/grpc++/impl/codegen/rpc_method.h \
     include/grpc++/impl/codegen/rpc_service_method.h \
@@ -4827,6 +4887,7 @@
     include/grpc++/impl/codegen/server_context.h \
     include/grpc++/impl/codegen/server_interface.h \
     include/grpc++/impl/codegen/service_type.h \
+    include/grpc++/impl/codegen/slice.h \
     include/grpc++/impl/codegen/status.h \
     include/grpc++/impl/codegen/status_code_enum.h \
     include/grpc++/impl/codegen/status_helper.h \
@@ -4890,7 +4951,7 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so
 endif
@@ -5431,7 +5492,7 @@
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
 else
-	$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
+	$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so
 endif
@@ -7647,6 +7708,7 @@
     test/core/end2end/tests/hpack_size.c \
     test/core/end2end/tests/idempotent_request.c \
     test/core/end2end/tests/invoke_large_request.c \
+    test/core/end2end/tests/keepalive_timeout.c \
     test/core/end2end/tests/large_metadata.c \
     test/core/end2end/tests/load_reporting_hook.c \
     test/core/end2end/tests/max_concurrent_streams.c \
@@ -7735,6 +7797,7 @@
     test/core/end2end/tests/hpack_size.c \
     test/core/end2end/tests/idempotent_request.c \
     test/core/end2end/tests/invoke_large_request.c \
+    test/core/end2end/tests/keepalive_timeout.c \
     test/core/end2end/tests/large_metadata.c \
     test/core/end2end/tests/load_reporting_hook.c \
     test/core/end2end/tests/max_concurrent_streams.c \
@@ -7980,6 +8043,38 @@
 endif
 
 
+BDP_ESTIMATOR_TEST_SRC = \
+    test/core/transport/bdp_estimator_test.c \
+
+BDP_ESTIMATOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BDP_ESTIMATOR_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bdp_estimator_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/bdp_estimator_test: $(BDP_ESTIMATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(BDP_ESTIMATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/bdp_estimator_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/transport/bdp_estimator_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bdp_estimator_test: $(BDP_ESTIMATOR_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BDP_ESTIMATOR_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 BIN_DECODER_TEST_SRC = \
     test/core/transport/chttp2/bin_decoder_test.c \
 
@@ -8204,38 +8299,6 @@
 endif
 
 
-CHTTP2_STATUS_CONVERSION_TEST_SRC = \
-    test/core/transport/chttp2/status_conversion_test.c \
-
-CHTTP2_STATUS_CONVERSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_STATUS_CONVERSION_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/chttp2_status_conversion_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/chttp2_status_conversion_test: $(CHTTP2_STATUS_CONVERSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(CHTTP2_STATUS_CONVERSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/status_conversion_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_chttp2_status_conversion_test: $(CHTTP2_STATUS_CONVERSION_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(CHTTP2_STATUS_CONVERSION_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 CHTTP2_STREAM_MAP_TEST_SRC = \
     test/core/transport/chttp2/stream_map_test.c \
 
@@ -9228,6 +9291,38 @@
 endif
 
 
+GPR_SPINLOCK_TEST_SRC = \
+    test/core/support/spinlock_test.c \
+
+GPR_SPINLOCK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_SPINLOCK_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/gpr_spinlock_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/gpr_spinlock_test: $(GPR_SPINLOCK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(GPR_SPINLOCK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_spinlock_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/support/spinlock_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_gpr_spinlock_test: $(GPR_SPINLOCK_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GPR_SPINLOCK_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 GPR_STACK_LOCKFREE_TEST_SRC = \
     test/core/support/stack_lockfree_test.c \
 
@@ -10348,102 +10443,6 @@
 endif
 
 
-INTERNAL_API_CANARY_IOMGR_TEST_SRC = \
-    test/core/internal_api_canaries/iomgr.c \
-
-INTERNAL_API_CANARY_IOMGR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INTERNAL_API_CANARY_IOMGR_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test: $(INTERNAL_API_CANARY_IOMGR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(INTERNAL_API_CANARY_IOMGR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/internal_api_canary_iomgr_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/internal_api_canaries/iomgr.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_internal_api_canary_iomgr_test: $(INTERNAL_API_CANARY_IOMGR_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(INTERNAL_API_CANARY_IOMGR_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
-INTERNAL_API_CANARY_SUPPORT_TEST_SRC = \
-    test/core/internal_api_canaries/iomgr.c \
-
-INTERNAL_API_CANARY_SUPPORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INTERNAL_API_CANARY_SUPPORT_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/internal_api_canary_support_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/internal_api_canary_support_test: $(INTERNAL_API_CANARY_SUPPORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(INTERNAL_API_CANARY_SUPPORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/internal_api_canary_support_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/internal_api_canaries/iomgr.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_internal_api_canary_support_test: $(INTERNAL_API_CANARY_SUPPORT_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(INTERNAL_API_CANARY_SUPPORT_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
-INTERNAL_API_CANARY_TRANSPORT_TEST_SRC = \
-    test/core/internal_api_canaries/iomgr.c \
-
-INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INTERNAL_API_CANARY_TRANSPORT_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/internal_api_canary_transport_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/internal_api_canary_transport_test: $(INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/internal_api_canary_transport_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/internal_api_canaries/iomgr.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_internal_api_canary_transport_test: $(INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(INTERNAL_API_CANARY_TRANSPORT_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 INVALID_CALL_ARGUMENT_TEST_SRC = \
     test/core/end2end/invalid_call_argument_test.c \
 
@@ -11180,6 +11179,70 @@
 endif
 
 
+POLLSET_SET_TEST_SRC = \
+    test/core/iomgr/pollset_set_test.c \
+
+POLLSET_SET_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(POLLSET_SET_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/pollset_set_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/pollset_set_test: $(POLLSET_SET_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(POLLSET_SET_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/pollset_set_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/iomgr/pollset_set_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_pollset_set_test: $(POLLSET_SET_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(POLLSET_SET_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
+RESOLVE_ADDRESS_POSIX_TEST_SRC = \
+    test/core/iomgr/resolve_address_posix_test.c \
+
+RESOLVE_ADDRESS_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_POSIX_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/resolve_address_posix_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/resolve_address_posix_test: $(RESOLVE_ADDRESS_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_posix_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_posix_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_resolve_address_posix_test: $(RESOLVE_ADDRESS_POSIX_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(RESOLVE_ADDRESS_POSIX_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 RESOLVE_ADDRESS_TEST_SRC = \
     test/core/iomgr/resolve_address_test.c \
 
@@ -11692,6 +11755,38 @@
 endif
 
 
+STATUS_CONVERSION_TEST_SRC = \
+    test/core/transport/status_conversion_test.c \
+
+STATUS_CONVERSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STATUS_CONVERSION_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/status_conversion_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/status_conversion_test: $(STATUS_CONVERSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(STATUS_CONVERSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/status_conversion_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/transport/status_conversion_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_status_conversion_test: $(STATUS_CONVERSION_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(STATUS_CONVERSION_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 TCP_CLIENT_POSIX_TEST_SRC = \
     test/core/iomgr/tcp_client_posix_test.c \
 
@@ -12365,6 +12460,221 @@
 endif
 
 
+BM_CALL_CREATE_SRC = \
+    test/cpp/microbenchmarks/bm_call_create.cc \
+
+BM_CALL_CREATE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CALL_CREATE_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bm_call_create: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/bm_call_create: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bm_call_create: $(PROTOBUF_DEP) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_call_create
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_call_create.o:  $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bm_call_create: $(BM_CALL_CREATE_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BM_CALL_CREATE_OBJS:.o=.dep)
+endif
+endif
+
+
+BM_CHTTP2_HPACK_SRC = \
+    test/cpp/microbenchmarks/bm_chttp2_hpack.cc \
+
+BM_CHTTP2_HPACK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CHTTP2_HPACK_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bm_chttp2_hpack: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/bm_chttp2_hpack: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bm_chttp2_hpack: $(PROTOBUF_DEP) $(BM_CHTTP2_HPACK_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CHTTP2_HPACK_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_chttp2_hpack
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_chttp2_hpack.o:  $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bm_chttp2_hpack: $(BM_CHTTP2_HPACK_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BM_CHTTP2_HPACK_OBJS:.o=.dep)
+endif
+endif
+
+
+BM_CLOSURE_SRC = \
+    test/cpp/microbenchmarks/bm_closure.cc \
+
+BM_CLOSURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CLOSURE_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bm_closure: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/bm_closure: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bm_closure: $(PROTOBUF_DEP) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_closure
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_closure.o:  $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bm_closure: $(BM_CLOSURE_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BM_CLOSURE_OBJS:.o=.dep)
+endif
+endif
+
+
+BM_CQ_SRC = \
+    test/cpp/microbenchmarks/bm_cq.cc \
+
+BM_CQ_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CQ_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bm_cq: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/bm_cq: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bm_cq: $(PROTOBUF_DEP) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_cq
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_cq.o:  $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bm_cq: $(BM_CQ_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BM_CQ_OBJS:.o=.dep)
+endif
+endif
+
+
+BM_ERROR_SRC = \
+    test/cpp/microbenchmarks/bm_error.cc \
+
+BM_ERROR_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_ERROR_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bm_error: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/bm_error: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bm_error: $(PROTOBUF_DEP) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_error
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_error.o:  $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bm_error: $(BM_ERROR_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BM_ERROR_OBJS:.o=.dep)
+endif
+endif
+
+
 BM_FULLSTACK_SRC = \
     test/cpp/microbenchmarks/bm_fullstack.cc \
 
@@ -12408,6 +12718,49 @@
 endif
 
 
+BM_METADATA_SRC = \
+    test/cpp/microbenchmarks/bm_metadata.cc \
+
+BM_METADATA_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_METADATA_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bm_metadata: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/bm_metadata: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bm_metadata: $(PROTOBUF_DEP) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_metadata
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_metadata.o:  $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bm_metadata: $(BM_METADATA_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BM_METADATA_OBJS:.o=.dep)
+endif
+endif
+
+
 CHANNEL_ARGUMENTS_TEST_SRC = \
     test/cpp/common/channel_arguments_test.cc \
 
@@ -13517,18 +13870,18 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/grpclb_test: $(PROTOBUF_DEP) $(GRPCLB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a
+$(BINDIR)/$(CONFIG)/grpclb_test: $(PROTOBUF_DEP) $(GRPCLB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(GRPCLB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpclb_test
+	$(Q) $(LDXX) $(LDFLAGS) $(GRPCLB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpclb_test
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o:  $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o:  $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a
+$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 deps_grpclb_test: $(GRPCLB_TEST_OBJS:.o=.dep)
 
@@ -13540,6 +13893,49 @@
 $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc
 
 
+HEALTH_SERVICE_END2END_TEST_SRC = \
+    test/cpp/end2end/health_service_end2end_test.cc \
+
+HEALTH_SERVICE_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEALTH_SERVICE_END2END_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/health_service_end2end_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/health_service_end2end_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/health_service_end2end_test: $(PROTOBUF_DEP) $(HEALTH_SERVICE_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(HEALTH_SERVICE_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/health_service_end2end_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/end2end/health_service_end2end_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_health_service_end2end_test: $(HEALTH_SERVICE_END2END_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HEALTH_SERVICE_END2END_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -13938,6 +14334,49 @@
 endif
 
 
+PROTO_UTILS_TEST_SRC = \
+    test/cpp/codegen/proto_utils_test.cc \
+
+PROTO_UTILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PROTO_UTILS_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/proto_utils_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/proto_utils_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/proto_utils_test: $(PROTOBUF_DEP) $(PROTO_UTILS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(PROTO_UTILS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/proto_utils_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/codegen/proto_utils_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a
+
+deps_proto_utils_test: $(PROTO_UTILS_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(PROTO_UTILS_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 QPS_INTERARRIVAL_TEST_SRC = \
     test/cpp/qps/qps_interarrival_test.cc \
 
@@ -14411,16 +14850,16 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/server_context_test_spouse_test: $(PROTOBUF_DEP) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/server_context_test_spouse_test: $(PROTOBUF_DEP) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_context_test_spouse_test
+	$(Q) $(LDXX) $(LDFLAGS) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_context_test_spouse_test
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/test/server_context_test_spouse_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/test/server_context_test_spouse_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 deps_server_context_test_spouse_test: $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS:.o=.dep)
 
@@ -14804,6 +15243,49 @@
 endif
 
 
+WRITES_PER_RPC_TEST_SRC = \
+    test/cpp/performance/writes_per_rpc_test.cc \
+
+WRITES_PER_RPC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WRITES_PER_RPC_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/writes_per_rpc_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/writes_per_rpc_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/writes_per_rpc_test: $(PROTOBUF_DEP) $(WRITES_PER_RPC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(WRITES_PER_RPC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/writes_per_rpc_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/performance/writes_per_rpc_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_writes_per_rpc_test: $(WRITES_PER_RPC_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(WRITES_PER_RPC_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 PUBLIC_HEADERS_MUST_BE_C89_SRC = \
     test/core/surface/public_headers_must_be_c89.c \
 
@@ -17645,6 +18127,7 @@
 # This is to ensure the embedded OpenSSL is built beforehand, properly
 # installing headers to their final destination on the drive. We need this
 # otherwise parallel compilation will fail if a source is compiled first.
+src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c: $(OPENSSL_DEP)
 src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP)
 src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP)
 src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP)
@@ -17666,6 +18149,7 @@
 src/core/lib/security/credentials/plugin/plugin_credentials.c: $(OPENSSL_DEP)
 src/core/lib/security/credentials/ssl/ssl_credentials.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/client_auth_filter.c: $(OPENSSL_DEP)
+src/core/lib/security/transport/lb_targets_info.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP)
 src/core/lib/security/transport/security_handshaker.c: $(OPENSSL_DEP)
@@ -17688,7 +18172,6 @@
 src/cpp/ext/proto_server_reflection.cc: $(OPENSSL_DEP)
 src/cpp/ext/proto_server_reflection_plugin.cc: $(OPENSSL_DEP)
 src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP)
-src/cpp/test/server_context_test_spouse.cc: $(OPENSSL_DEP)
 src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP)
 test/core/bad_client/bad_client.c: $(OPENSSL_DEP)
 test/core/bad_ssl/server_common.c: $(OPENSSL_DEP)
diff --git a/WORKSPACE b/WORKSPACE
index 9883109..9b79d04 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -28,20 +28,41 @@
     actual = "@submodule_protobuf//:protoc",
 )
 
+bind(
+    name = "gtest",
+    actual = "@submodule_gtest//:gtest",
+)
+
+bind(
+    name = "gflags",
+    actual = "@com_github_gflags_gflags//:gflags",
+)
+
 new_local_repository(
     name = "submodule_boringssl",
-    path = "third_party/boringssl-with-bazel",
     build_file = "third_party/boringssl-with-bazel/BUILD",
+    path = "third_party/boringssl-with-bazel",
 )
 
 new_local_repository(
     name = "submodule_zlib",
-    path = "third_party/zlib",
     build_file = "third_party/zlib.BUILD",
+    path = "third_party/zlib",
 )
 
 new_local_repository(
     name = "submodule_protobuf",
-    path = "third_party/protobuf",
     build_file = "third_party/protobuf/BUILD",
+    path = "third_party/protobuf",
+)
+
+new_local_repository(
+    name = "submodule_gtest",
+    build_file = "third_party/gtest.BUILD",
+    path = "third_party/googletest",
+)
+
+local_repository(
+    name = "com_github_gflags_gflags",
+    path = "third_party/gflags",
 )
diff --git a/binding.gyp b/binding.gyp
index aa6f236..6fbe59b 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -682,6 +682,8 @@
         'src/core/lib/slice/percent_encoding.c',
         'src/core/lib/slice/slice.c',
         'src/core/lib/slice/slice_buffer.c',
+        'src/core/lib/slice/slice_hash_table.c',
+        'src/core/lib/slice/slice_intern.c',
         'src/core/lib/slice/slice_string_helpers.c',
         'src/core/lib/surface/alarm.c',
         'src/core/lib/surface/api_trace.c',
@@ -701,14 +703,16 @@
         'src/core/lib/surface/server.c',
         'src/core/lib/surface/validate_metadata.c',
         'src/core/lib/surface/version.c',
+        'src/core/lib/transport/bdp_estimator.c',
         'src/core/lib/transport/byte_stream.c',
         'src/core/lib/transport/connectivity_state.c',
-        'src/core/lib/transport/mdstr_hash_table.c',
+        'src/core/lib/transport/error_utils.c',
         'src/core/lib/transport/metadata.c',
         'src/core/lib/transport/metadata_batch.c',
         'src/core/lib/transport/pid_controller.c',
         'src/core/lib/transport/service_config.c',
         'src/core/lib/transport/static_metadata.c',
+        'src/core/lib/transport/status_conversion.c',
         'src/core/lib/transport/timeout_encoding.c',
         'src/core/lib/transport/transport.c',
         'src/core/lib/transport/transport_op_string.c',
@@ -729,7 +733,6 @@
         'src/core/ext/transport/chttp2/transport/huffsyms.c',
         'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
         'src/core/ext/transport/chttp2/transport/parsing.c',
-        'src/core/ext/transport/chttp2/transport/status_conversion.c',
         'src/core/ext/transport/chttp2/transport/stream_lists.c',
         'src/core/ext/transport/chttp2/transport/stream_map.c',
         'src/core/ext/transport/chttp2/transport/varint.c',
@@ -751,6 +754,7 @@
         'src/core/lib/security/credentials/plugin/plugin_credentials.c',
         'src/core/lib/security/credentials/ssl/ssl_credentials.c',
         'src/core/lib/security/transport/client_auth_filter.c',
+        'src/core/lib/security/transport/lb_targets_info.c',
         'src/core/lib/security/transport/secure_endpoint.c',
         'src/core/lib/security/transport/security_connector.c',
         'src/core/lib/security/transport/security_handshaker.c',
@@ -771,11 +775,14 @@
         'src/core/ext/client_channel/connector.c',
         'src/core/ext/client_channel/default_initial_connect_string.c',
         'src/core/ext/client_channel/http_connect_handshaker.c',
+        'src/core/ext/client_channel/http_proxy.c',
         'src/core/ext/client_channel/initial_connect_string.c',
         'src/core/ext/client_channel/lb_policy.c',
         'src/core/ext/client_channel/lb_policy_factory.c',
         'src/core/ext/client_channel/lb_policy_registry.c',
         'src/core/ext/client_channel/parse_address.c',
+        'src/core/ext/client_channel/proxy_mapper.c',
+        'src/core/ext/client_channel/proxy_mapper_registry.c',
         'src/core/ext/client_channel/resolver.c',
         'src/core/ext/client_channel/resolver_factory.c',
         'src/core/ext/client_channel/resolver_registry.c',
@@ -788,6 +795,7 @@
         'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
         'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
         'src/core/ext/lb_policy/grpclb/grpclb.c',
+        'src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c',
         'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
         'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
         'third_party/nanopb/pb_common.c',
@@ -879,6 +887,7 @@
         "src/node/ext/server_credentials.cc",
         "src/node/ext/server_generic.cc",
         "src/node/ext/server_uv.cc",
+        "src/node/ext/slice.cc",
         "src/node/ext/timeval.cc",
       ],
       "dependencies": [
diff --git a/build.yaml b/build.yaml
index de1c6de..48d7f12 100644
--- a/build.yaml
+++ b/build.yaml
@@ -12,9 +12,9 @@
   '#08': Use "-preN" suffixes to identify pre-release versions
   '#09': Per-language overrides are possible with (eg) ruby_version tag here
   '#10': See the expand_version.py for all the quirks here
-  core_version: 2.0.0
-  g_stands_for: good
-  version: 1.1.2
+  core_version: 3.0.0-dev
+  g_stands_for: green
+  version: 1.2.0-dev
 filegroups:
 - name: census
   public_headers:
@@ -31,6 +31,11 @@
   - src/core/ext/census/resource.h
   - src/core/ext/census/rpc_metric_id.h
   - src/core/ext/census/trace_context.h
+  - src/core/ext/census/trace_label.h
+  - src/core/ext/census/trace_propagation.h
+  - src/core/ext/census/trace_status.h
+  - src/core/ext/census/trace_string.h
+  - src/core/ext/census/tracing.h
   src:
   - src/core/ext/census/base_resources.c
   - src/core/ext/census/context.c
@@ -85,6 +90,7 @@
   - src/core/lib/support/env.h
   - src/core/lib/support/mpscq.h
   - src/core/lib/support/murmur_hash.h
+  - src/core/lib/support/spinlock.h
   - src/core/lib/support/stack_lockfree.h
   - src/core/lib/support/string.h
   - src/core/lib/support/string_windows.h
@@ -160,6 +166,7 @@
   - include/grpc/grpc.h
   - include/grpc/grpc_posix.h
   - include/grpc/grpc_security_constants.h
+  - include/grpc/load_reporting.h
   - include/grpc/slice.h
   - include/grpc/slice_buffer.h
   - include/grpc/status.h
@@ -188,6 +195,7 @@
   - src/core/lib/iomgr/endpoint.h
   - src/core/lib/iomgr/endpoint_pair.h
   - src/core/lib/iomgr/error.h
+  - src/core/lib/iomgr/error_internal.h
   - src/core/lib/iomgr/ev_epoll_linux.h
   - src/core/lib/iomgr/ev_poll_posix.h
   - src/core/lib/iomgr/ev_posix.h
@@ -240,6 +248,7 @@
   - src/core/lib/json/json_reader.h
   - src/core/lib/json/json_writer.h
   - src/core/lib/slice/percent_encoding.h
+  - src/core/lib/slice/slice_hash_table.h
   - src/core/lib/slice/slice_internal.h
   - src/core/lib/slice/slice_string_helpers.h
   - src/core/lib/surface/api_trace.h
@@ -253,14 +262,18 @@
   - src/core/lib/surface/init.h
   - src/core/lib/surface/lame_client.h
   - src/core/lib/surface/server.h
+  - src/core/lib/surface/validate_metadata.h
+  - src/core/lib/transport/bdp_estimator.h
   - src/core/lib/transport/byte_stream.h
   - src/core/lib/transport/connectivity_state.h
-  - src/core/lib/transport/mdstr_hash_table.h
+  - src/core/lib/transport/error_utils.h
+  - src/core/lib/transport/http2_errors.h
   - src/core/lib/transport/metadata.h
   - src/core/lib/transport/metadata_batch.h
   - src/core/lib/transport/pid_controller.h
   - src/core/lib/transport/service_config.h
   - src/core/lib/transport/static_metadata.h
+  - src/core/lib/transport/status_conversion.h
   - src/core/lib/transport/timeout_encoding.h
   - src/core/lib/transport/transport.h
   - src/core/lib/transport/transport_impl.h
@@ -349,6 +362,8 @@
   - src/core/lib/slice/percent_encoding.c
   - src/core/lib/slice/slice.c
   - src/core/lib/slice/slice_buffer.c
+  - src/core/lib/slice/slice_hash_table.c
+  - src/core/lib/slice/slice_intern.c
   - src/core/lib/slice/slice_string_helpers.c
   - src/core/lib/surface/alarm.c
   - src/core/lib/surface/api_trace.c
@@ -368,14 +383,16 @@
   - src/core/lib/surface/server.c
   - src/core/lib/surface/validate_metadata.c
   - src/core/lib/surface/version.c
+  - src/core/lib/transport/bdp_estimator.c
   - src/core/lib/transport/byte_stream.c
   - src/core/lib/transport/connectivity_state.c
-  - src/core/lib/transport/mdstr_hash_table.c
+  - src/core/lib/transport/error_utils.c
   - src/core/lib/transport/metadata.c
   - src/core/lib/transport/metadata_batch.c
   - src/core/lib/transport/pid_controller.c
   - src/core/lib/transport/service_config.c
   - src/core/lib/transport/static_metadata.c
+  - src/core/lib/transport/status_conversion.c
   - src/core/lib/transport/timeout_encoding.c
   - src/core/lib/transport/transport.c
   - src/core/lib/transport/transport_op_string.c
@@ -389,11 +406,14 @@
   - src/core/ext/client_channel/client_channel_factory.h
   - src/core/ext/client_channel/connector.h
   - src/core/ext/client_channel/http_connect_handshaker.h
+  - src/core/ext/client_channel/http_proxy.h
   - src/core/ext/client_channel/initial_connect_string.h
   - src/core/ext/client_channel/lb_policy.h
   - src/core/ext/client_channel/lb_policy_factory.h
   - src/core/ext/client_channel/lb_policy_registry.h
   - src/core/ext/client_channel/parse_address.h
+  - src/core/ext/client_channel/proxy_mapper.h
+  - src/core/ext/client_channel/proxy_mapper_registry.h
   - src/core/ext/client_channel/resolver.h
   - src/core/ext/client_channel/resolver_factory.h
   - src/core/ext/client_channel/resolver_registry.h
@@ -408,11 +428,14 @@
   - src/core/ext/client_channel/connector.c
   - src/core/ext/client_channel/default_initial_connect_string.c
   - src/core/ext/client_channel/http_connect_handshaker.c
+  - src/core/ext/client_channel/http_proxy.c
   - src/core/ext/client_channel/initial_connect_string.c
   - src/core/ext/client_channel/lb_policy.c
   - src/core/ext/client_channel/lb_policy_factory.c
   - src/core/ext/client_channel/lb_policy_registry.c
   - src/core/ext/client_channel/parse_address.c
+  - src/core/ext/client_channel/proxy_mapper.c
+  - src/core/ext/client_channel/proxy_mapper_registry.c
   - src/core/ext/client_channel/resolver.c
   - src/core/ext/client_channel/resolver_factory.c
   - src/core/ext/client_channel/resolver_registry.c
@@ -436,10 +459,28 @@
 - name: grpc_lb_policy_grpclb
   headers:
   - src/core/ext/lb_policy/grpclb/grpclb.h
+  - src/core/ext/lb_policy/grpclb/grpclb_channel.h
   - src/core/ext/lb_policy/grpclb/load_balancer_api.h
   - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
   src:
   - src/core/ext/lb_policy/grpclb/grpclb.c
+  - src/core/ext/lb_policy/grpclb/grpclb_channel.c
+  - src/core/ext/lb_policy/grpclb/load_balancer_api.c
+  - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
+  plugin: grpc_lb_policy_grpclb
+  uses:
+  - grpc_base
+  - grpc_client_channel
+  - nanopb
+- name: grpc_lb_policy_grpclb_secure
+  headers:
+  - src/core/ext/lb_policy/grpclb/grpclb.h
+  - src/core/ext/lb_policy/grpclb/grpclb_channel.h
+  - src/core/ext/lb_policy/grpclb/load_balancer_api.h
+  - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
+  src:
+  - src/core/ext/lb_policy/grpclb/grpclb.c
+  - src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c
   - src/core/ext/lb_policy/grpclb/load_balancer_api.c
   - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
   plugin: grpc_lb_policy_grpclb
@@ -502,6 +543,7 @@
   - src/core/lib/security/credentials/plugin/plugin_credentials.h
   - src/core/lib/security/credentials/ssl/ssl_credentials.h
   - src/core/lib/security/transport/auth_filters.h
+  - src/core/lib/security/transport/lb_targets_info.h
   - src/core/lib/security/transport/secure_endpoint.h
   - src/core/lib/security/transport/security_connector.h
   - src/core/lib/security/transport/security_handshaker.h
@@ -525,6 +567,7 @@
   - src/core/lib/security/credentials/plugin/plugin_credentials.c
   - src/core/lib/security/credentials/ssl/ssl_credentials.c
   - src/core/lib/security/transport/client_auth_filter.c
+  - src/core/lib/security/transport/lb_targets_info.c
   - src/core/lib/security/transport/secure_endpoint.c
   - src/core/lib/security/transport/security_connector.c
   - src/core/lib/security/transport/security_handshaker.c
@@ -546,6 +589,7 @@
   - test/core/end2end/fixtures/http_proxy.h
   - test/core/end2end/fixtures/proxy.h
   - test/core/iomgr/endpoint_tests.h
+  - test/core/util/debugger_macros.h
   - test/core/util/grpc_profiler.h
   - test/core/util/memory_counters.h
   - test/core/util/mock_endpoint.h
@@ -554,12 +598,14 @@
   - test/core/util/port.h
   - test/core/util/port_server_client.h
   - test/core/util/slice_splitter.h
+  - test/core/util/trickle_endpoint.h
   src:
   - test/core/end2end/cq_verifier.c
   - test/core/end2end/fake_resolver.c
   - test/core/end2end/fixtures/http_proxy.c
   - test/core/end2end/fixtures/proxy.c
   - test/core/iomgr/endpoint_tests.c
+  - test/core/util/debugger_macros.c
   - test/core/util/grpc_profiler.c
   - test/core/util/memory_counters.c
   - test/core/util/mock_endpoint.c
@@ -570,6 +616,7 @@
   - test/core/util/port_uv.c
   - test/core/util/port_windows.c
   - test/core/util/slice_splitter.c
+  - test/core/util/trickle_endpoint.c
   deps:
   - grpc
   - gpr_test_util
@@ -588,11 +635,9 @@
   - src/core/ext/transport/chttp2/transport/hpack_encoder.h
   - src/core/ext/transport/chttp2/transport/hpack_parser.h
   - src/core/ext/transport/chttp2/transport/hpack_table.h
-  - src/core/ext/transport/chttp2/transport/http2_errors.h
   - src/core/ext/transport/chttp2/transport/huffsyms.h
   - src/core/ext/transport/chttp2/transport/incoming_metadata.h
   - src/core/ext/transport/chttp2/transport/internal.h
-  - src/core/ext/transport/chttp2/transport/status_conversion.h
   - src/core/ext/transport/chttp2/transport/stream_map.h
   - src/core/ext/transport/chttp2/transport/varint.h
   src:
@@ -612,7 +657,6 @@
   - src/core/ext/transport/chttp2/transport/huffsyms.c
   - src/core/ext/transport/chttp2/transport/incoming_metadata.c
   - src/core/ext/transport/chttp2/transport/parsing.c
-  - src/core/ext/transport/chttp2/transport/status_conversion.c
   - src/core/ext/transport/chttp2/transport/stream_lists.c
   - src/core/ext/transport/chttp2/transport/stream_map.c
   - src/core/ext/transport/chttp2/transport/varint.c
@@ -684,7 +728,8 @@
   - include/grpc/grpc_security.h
   - include/grpc/grpc_security_constants.h
   headers:
-  - third_party/Cronet/bidirectional_stream_c.h
+  - src/core/ext/transport/cronet/transport/cronet_transport.h
+  - third_party/objective_c/Cronet/bidirectional_stream_c.h
   src:
   - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
   - src/core/ext/transport/cronet/transport/cronet_api_dummy.c
@@ -725,9 +770,11 @@
   - include/grpc++/completion_queue.h
   - include/grpc++/create_channel.h
   - include/grpc++/create_channel_posix.h
+  - include/grpc++/ext/health_check_service_server_builder_option.h
   - include/grpc++/generic/async_generic_service.h
   - include/grpc++/generic/generic_stub.h
   - include/grpc++/grpc++.h
+  - include/grpc++/health_check_service_interface.h
   - include/grpc++/impl/call.h
   - include/grpc++/impl/client_unary_call.h
   - include/grpc++/impl/codegen/core_codegen.h
@@ -765,6 +812,8 @@
   - src/cpp/client/create_channel_internal.h
   - src/cpp/common/channel_filter.h
   - src/cpp/server/dynamic_thread_pool.h
+  - src/cpp/server/health/default_health_check_service.h
+  - src/cpp/server/health/health.pb.h
   - src/cpp/server/thread_pool_interface.h
   - src/cpp/thread_manager/thread_manager.h
   src:
@@ -785,6 +834,10 @@
   - src/cpp/server/async_generic_service.cc
   - src/cpp/server/create_default_thread_pool.cc
   - src/cpp/server/dynamic_thread_pool.cc
+  - src/cpp/server/health/default_health_check_service.cc
+  - src/cpp/server/health/health.pb.c
+  - src/cpp/server/health/health_check_service.cc
+  - src/cpp/server/health/health_check_service_server_builder_option.cc
   - src/cpp/server/server_builder.cc
   - src/cpp/server/server_cc.cc
   - src/cpp/server/server_context.cc
@@ -814,6 +867,7 @@
   - include/grpc++/impl/codegen/core_codegen_interface.h
   - include/grpc++/impl/codegen/create_auth_context.h
   - include/grpc++/impl/codegen/grpc_library.h
+  - include/grpc++/impl/codegen/metadata_map.h
   - include/grpc++/impl/codegen/method_handler_impl.h
   - include/grpc++/impl/codegen/rpc_method.h
   - include/grpc++/impl/codegen/rpc_service_method.h
@@ -822,6 +876,7 @@
   - include/grpc++/impl/codegen/server_context.h
   - include/grpc++/impl/codegen/server_interface.h
   - include/grpc++/impl/codegen/service_type.h
+  - include/grpc++/impl/codegen/slice.h
   - include/grpc++/impl/codegen/status.h
   - include/grpc++/impl/codegen/status_code_enum.h
   - include/grpc++/impl/codegen/status_helper.h
@@ -852,6 +907,12 @@
   language: c++
   src:
   - src/proto/grpc/reflection/v1alpha/reflection.proto
+- name: grpc++_test
+  language: c++
+  public_headers:
+  - include/grpc++/test/server_context_test_spouse.h
+  deps:
+  - grpc++
 - name: thrift_util
   language: c++
   public_headers:
@@ -892,7 +953,7 @@
   - grpc_transport_chttp2_client_secure
   - grpc_transport_chttp2_server_insecure
   - grpc_transport_chttp2_client_insecure
-  - grpc_lb_policy_grpclb
+  - grpc_lb_policy_grpclb_secure
   - grpc_lb_policy_pick_first
   - grpc_lb_policy_round_robin
   - grpc_resolver_dns_native
@@ -918,6 +979,7 @@
   - grpc_base
   - grpc_transport_cronet_client_secure
   - grpc_transport_chttp2_client_secure
+  - grpc_load_reporting
   generate_plugin_registry: true
   platforms:
   - linux
@@ -1046,6 +1108,7 @@
   filegroups:
   - grpc++_base
   - grpc++_codegen_base
+  - grpc++_codegen_proto
   - grpc++_codegen_base_src
   secure: check
   vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}'
@@ -1098,15 +1161,6 @@
   - grpc++
   filegroups:
   - grpc++_reflection_proto
-- name: grpc++_test
-  build: private
-  language: c++
-  headers:
-  - include/grpc++/test/server_context_test_spouse.h
-  src:
-  - src/cpp/test/server_context_test_spouse.cc
-  deps:
-  - grpc++
 - name: grpc++_test_config
   build: private
   language: c++
@@ -1125,6 +1179,7 @@
   - test/cpp/util/subprocess.h
   - test/cpp/util/test_credentials_provider.h
   src:
+  - src/proto/grpc/health/v1/health.proto
   - src/proto/grpc/testing/echo_messages.proto
   - src/proto/grpc/testing/echo.proto
   - src/proto/grpc/testing/duplicate/echo_duplicate.proto
@@ -1427,6 +1482,16 @@
   - gpr
   exclude_iomgrs:
   - uv
+- name: bdp_estimator_test
+  build: test
+  language: c
+  src:
+  - test/core/transport/bdp_estimator_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: bin_decoder_test
   build: test
   language: c
@@ -1493,16 +1558,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: chttp2_status_conversion_test
-  build: test
-  language: c
-  src:
-  - test/core/transport/chttp2/status_conversion_test.c
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
 - name: chttp2_stream_map_test
   build: test
   language: c
@@ -1841,6 +1896,15 @@
   deps:
   - gpr_test_util
   - gpr
+- name: gpr_spinlock_test
+  cpu_cost: 10
+  build: test
+  language: c
+  src:
+  - test/core/support/spinlock_test.c
+  deps:
+  - gpr_test_util
+  - gpr
 - name: gpr_stack_lockfree_test
   cpu_cost: 7
   build: test
@@ -2208,39 +2272,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: internal_api_canary_iomgr_test
-  build: test
-  run: false
-  language: c
-  src:
-  - test/core/internal_api_canaries/iomgr.c
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
-- name: internal_api_canary_support_test
-  build: test
-  run: false
-  language: c
-  src:
-  - test/core/internal_api_canaries/iomgr.c
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
-- name: internal_api_canary_transport_test
-  build: test
-  run: false
-  language: c
-  src:
-  - test/core/internal_api_canaries/iomgr.c
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
 - name: invalid_call_argument_test
   cpu_cost: 0.1
   build: test
@@ -2316,8 +2347,8 @@
   - gpr
 - name: lb_policies_test
   cpu_cost: 0.1
-  flaky: true
   build: test
+  run: false
   language: c
   src:
   - test/core/client_channel/lb_policies_test.c
@@ -2499,6 +2530,34 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: pollset_set_test
+  build: test
+  language: c
+  src:
+  - test/core/iomgr/pollset_set_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  exclude_iomgrs:
+  - uv
+  platforms:
+  - linux
+- name: resolve_address_posix_test
+  build: test
+  language: c
+  src:
+  - test/core/iomgr/resolve_address_posix_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: resolve_address_test
   build: test
   language: c
@@ -2681,6 +2740,16 @@
   corpus_dirs:
   - test/core/security/corpus/ssl_server_corpus
   maxlen: 2048
+- name: status_conversion_test
+  build: test
+  language: c
+  src:
+  - test/core/transport/status_conversion_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: tcp_client_posix_test
   cpu_cost: 0.5
   build: test
@@ -2938,6 +3007,101 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: bm_call_create
+  build: test
+  language: c++
+  src:
+  - test/cpp/microbenchmarks/bm_call_create.cc
+  deps:
+  - benchmark
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  args:
+  - --benchmark_min_time=0
+  platforms:
+  - mac
+  - linux
+  - posix
+- name: bm_chttp2_hpack
+  build: test
+  language: c++
+  src:
+  - test/cpp/microbenchmarks/bm_chttp2_hpack.cc
+  deps:
+  - benchmark
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  args:
+  - --benchmark_min_time=0
+  platforms:
+  - mac
+  - linux
+  - posix
+- name: bm_closure
+  build: test
+  language: c++
+  src:
+  - test/cpp/microbenchmarks/bm_closure.cc
+  deps:
+  - benchmark
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  args:
+  - --benchmark_min_time=0
+  platforms:
+  - mac
+  - linux
+  - posix
+- name: bm_cq
+  build: test
+  language: c++
+  src:
+  - test/cpp/microbenchmarks/bm_cq.cc
+  deps:
+  - benchmark
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  args:
+  - --benchmark_min_time=0
+  platforms:
+  - mac
+  - linux
+  - posix
+- name: bm_error
+  build: test
+  language: c++
+  src:
+  - test/cpp/microbenchmarks/bm_error.cc
+  deps:
+  - benchmark
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  args:
+  - --benchmark_min_time=0
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: bm_fullstack
   build: test
   language: c++
@@ -2951,6 +3115,33 @@
   - grpc
   - gpr_test_util
   - gpr
+  args:
+  - --benchmark_min_time=0
+  excluded_poll_engines:
+  - poll
+  - poll-cv
+  platforms:
+  - mac
+  - linux
+  - posix
+  timeout_seconds: 1200
+- name: bm_metadata
+  build: test
+  language: c++
+  src:
+  - test/cpp/microbenchmarks/bm_metadata.cc
+  deps:
+  - benchmark
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  args:
+  - --benchmark_min_time=0
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: channel_arguments_test
   gtest: true
   build: test
@@ -3152,6 +3343,8 @@
   - grpc++
   - grpc
   - gpr
+  args:
+  - --generated_file_path=gens/src/proto/grpc/testing/compiler_test.grpc.pb.h
 - name: grpc_cli
   build: test
   run: false
@@ -3273,12 +3466,25 @@
   - src/proto/grpc/lb/v1/load_balancer.proto
   - test/cpp/grpclb/grpclb_test.cc
   deps:
-  - gpr
-  - gpr_test_util
-  - grpc
-  - grpc++
   - grpc++_test_util
   - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: health_service_end2end_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - test/cpp/end2end/health_service_end2end_test.cc
+  deps:
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: http2_client
   build: test
   run: false
@@ -3296,7 +3502,7 @@
   - linux
   - posix
 - name: hybrid_end2end_test
-  gtest: true
+  flaky: true
   build: test
   language: c++
   src:
@@ -3377,6 +3583,10 @@
   - gpr_test_util
   - gpr
   - grpc++_test_config
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: metrics_client
   build: test
   run: false
@@ -3426,6 +3636,18 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: proto_utils_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - test/cpp/codegen/proto_utils_test.cc
+  deps:
+  - grpc++
+  - grpc
+  filegroups:
+  - grpc++_codegen_base
+  - grpc++_codegen_proto
 - name: qps_interarrival_test
   build: test
   run: false
@@ -3596,11 +3818,12 @@
   - test/cpp/test/server_context_test_spouse_test.cc
   deps:
   - grpc_test_util
-  - grpc++_test
   - grpc++
   - grpc
   - gpr_test_util
   - gpr
+  uses:
+  - grpc++_test
 - name: server_crash_test
   gtest: true
   cpu_cost: 0.1
@@ -3725,6 +3948,24 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: writes_per_rpc_test
+  gtest: true
+  cpu_cost: 0.5
+  build: test
+  language: c++
+  src:
+  - test/cpp/performance/writes_per_rpc_test.cc
+  deps:
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: public_headers_must_be_c89
   build: test
   language: c89
@@ -3765,7 +4006,6 @@
     test_environ:
       ASAN_OPTIONS: detect_leaks=1:color=always
       LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
-    timeout_multiplier: 3
   asan-noleaks:
     CC: clang
     CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer
@@ -3777,7 +4017,6 @@
     compile_the_world: true
     test_environ:
       ASAN_OPTIONS: detect_leaks=0:color=always
-    timeout_multiplier: 3
   asan-trace-cmp:
     CC: clang
     CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp -fsanitize=address
@@ -3790,43 +4029,15 @@
     test_environ:
       ASAN_OPTIONS: detect_leaks=1:color=always
       LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
-    timeout_multiplier: 3
   basicprof:
     CPPFLAGS: -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC
     DEFINES: NDEBUG
+  counters:
+    CPPFLAGS: -O2 -DGPR_LOW_LEVEL_COUNTERS
+    DEFINES: NDEBUG
   dbg:
     CPPFLAGS: -O0
     DEFINES: _DEBUG DEBUG
-  easan:
-    CC: clang
-    CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer
-      -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
-    CXX: clang++
-    DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
-    LD: clang
-    LDFLAGS: -fsanitize=address
-    LDXX: clang++
-    compile_the_world: true
-    test_environ:
-      ASAN_OPTIONS: detect_leaks=1:color=always
-      LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
-    timeout_multiplier: 3
-  edbg:
-    CPPFLAGS: -O0
-    DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
-  etsan:
-    CC: clang
-    CPPFLAGS: -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument
-      -DGPR_NO_DIRECT_SYSCALLS
-    CXX: clang++
-    DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
-    LD: clang
-    LDFLAGS: -fsanitize=thread
-    LDXX: clang++
-    compile_the_world: true
-    test_environ:
-      TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
-    timeout_multiplier: 5
   gcov:
     CC: gcc
     CPPFLAGS: -O0 -fprofile-arcs -ftest-coverage -Wno-return-type
@@ -3839,13 +4050,11 @@
     CPPFLAGS: -O0
     DEFINES: _DEBUG DEBUG
     LDFLAGS: -rdynamic
-    timeout_multiplier: 20
     valgrind: --tool=helgrind
   memcheck:
     CPPFLAGS: -O0
     DEFINES: _DEBUG DEBUG
     LDFLAGS: -rdynamic
-    timeout_multiplier: 10
     valgrind: --tool=memcheck --leak-check=full
   msan:
     CC: clang
@@ -3859,7 +4068,6 @@
       -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
     LDXX: clang++
     compile_the_world: true
-    timeout_multiplier: 4
   mutrace:
     CPPFLAGS: -O3 -fno-omit-frame-pointer
     DEFINES: NDEBUG
@@ -3882,7 +4090,6 @@
     compile_the_world: true
     test_environ:
       TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
-    timeout_multiplier: 5
   ubsan:
     CC: clang
     CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow
@@ -3895,7 +4102,6 @@
     compile_the_world: true
     test_environ:
       UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
-    timeout_multiplier: 1.5
 defaults:
   benchmark:
     CPPFLAGS: -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
@@ -3905,7 +4111,7 @@
     CPPFLAGS: -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM
       -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
   global:
-    CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter
+    CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
     LDFLAGS: -g
   zlib:
     CFLAGS: -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-implicit-function-declaration
@@ -3925,6 +4131,7 @@
   - src/node/ext/completion_queue.h
   - src/node/ext/server.h
   - src/node/ext/server_credentials.h
+  - src/node/ext/slice.h
   - src/node/ext/timeval.h
   js:
   - src/node/index.js
@@ -3948,6 +4155,7 @@
   - src/node/ext/server_credentials.cc
   - src/node/ext/server_generic.cc
   - src/node/ext/server_uv.cc
+  - src/node/ext/slice.cc
   - src/node/ext/timeval.cc
 openssl_fallback:
   base_uri: https://openssl.org/source/old/1.0.2/
diff --git a/build_config.rb b/build_config.rb
index 35e887e..b5a8c20 100644
--- a/build_config.rb
+++ b/build_config.rb
@@ -28,5 +28,5 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 module GrpcBuildConfig
-  CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-2.dll'
+  CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-3.dll'
 end
diff --git a/cmake/msvc_static_runtime.cmake b/cmake/msvc_static_runtime.cmake
new file mode 100644
index 0000000..5a31ab3
--- /dev/null
+++ b/cmake/msvc_static_runtime.cmake
@@ -0,0 +1,14 @@
+option(gRPC_MSVC_STATIC_RUNTIME "Link with static msvc runtime libraries" OFF)
+
+if(gRPC_MSVC_STATIC_RUNTIME)
+  # switch from dynamic to static linking of msvcrt
+  foreach(flag_var
+    CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+    CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+
+    if(${flag_var} MATCHES "/MD")
+    string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+    endif(${flag_var} MATCHES "/MD")
+  endforeach(flag_var)
+endif()
+
diff --git a/composer.json b/composer.json
index 711ee82..53ae638 100644
--- a/composer.json
+++ b/composer.json
@@ -7,8 +7,7 @@
   "license": "BSD-3-Clause",
   "require": {
     "php": ">=5.5.0",
-    "ext-grpc": "*",
-    "google/protobuf": "v3.1.0-alpha-1"
+    "google/protobuf": "v3.1.0"
   },
   "require-dev": {
     "google/auth": "v0.9"
diff --git a/config.m4 b/config.m4
index 621bbb3..90536e5 100644
--- a/config.m4
+++ b/config.m4
@@ -165,6 +165,8 @@
     src/core/lib/slice/percent_encoding.c \
     src/core/lib/slice/slice.c \
     src/core/lib/slice/slice_buffer.c \
+    src/core/lib/slice/slice_hash_table.c \
+    src/core/lib/slice/slice_intern.c \
     src/core/lib/slice/slice_string_helpers.c \
     src/core/lib/surface/alarm.c \
     src/core/lib/surface/api_trace.c \
@@ -184,14 +186,16 @@
     src/core/lib/surface/server.c \
     src/core/lib/surface/validate_metadata.c \
     src/core/lib/surface/version.c \
+    src/core/lib/transport/bdp_estimator.c \
     src/core/lib/transport/byte_stream.c \
     src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/mdstr_hash_table.c \
+    src/core/lib/transport/error_utils.c \
     src/core/lib/transport/metadata.c \
     src/core/lib/transport/metadata_batch.c \
     src/core/lib/transport/pid_controller.c \
     src/core/lib/transport/service_config.c \
     src/core/lib/transport/static_metadata.c \
+    src/core/lib/transport/status_conversion.c \
     src/core/lib/transport/timeout_encoding.c \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
@@ -212,7 +216,6 @@
     src/core/ext/transport/chttp2/transport/huffsyms.c \
     src/core/ext/transport/chttp2/transport/incoming_metadata.c \
     src/core/ext/transport/chttp2/transport/parsing.c \
-    src/core/ext/transport/chttp2/transport/status_conversion.c \
     src/core/ext/transport/chttp2/transport/stream_lists.c \
     src/core/ext/transport/chttp2/transport/stream_map.c \
     src/core/ext/transport/chttp2/transport/varint.c \
@@ -234,6 +237,7 @@
     src/core/lib/security/credentials/plugin/plugin_credentials.c \
     src/core/lib/security/credentials/ssl/ssl_credentials.c \
     src/core/lib/security/transport/client_auth_filter.c \
+    src/core/lib/security/transport/lb_targets_info.c \
     src/core/lib/security/transport/secure_endpoint.c \
     src/core/lib/security/transport/security_connector.c \
     src/core/lib/security/transport/security_handshaker.c \
@@ -254,11 +258,14 @@
     src/core/ext/client_channel/connector.c \
     src/core/ext/client_channel/default_initial_connect_string.c \
     src/core/ext/client_channel/http_connect_handshaker.c \
+    src/core/ext/client_channel/http_proxy.c \
     src/core/ext/client_channel/initial_connect_string.c \
     src/core/ext/client_channel/lb_policy.c \
     src/core/ext/client_channel/lb_policy_factory.c \
     src/core/ext/client_channel/lb_policy_registry.c \
     src/core/ext/client_channel/parse_address.c \
+    src/core/ext/client_channel/proxy_mapper.c \
+    src/core/ext/client_channel/proxy_mapper_registry.c \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
@@ -271,6 +278,7 @@
     src/core/ext/transport/chttp2/client/insecure/channel_create.c \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
     src/core/ext/lb_policy/grpclb/grpclb.c \
+    src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c \
     src/core/ext/lb_policy/grpclb/load_balancer_api.c \
     src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
     third_party/nanopb/pb_common.c \
diff --git a/doc/PROTOCOL-WEB.md b/doc/PROTOCOL-WEB.md
index 562d599..35448d6 100644
--- a/doc/PROTOCOL-WEB.md
+++ b/doc/PROTOCOL-WEB.md
@@ -60,21 +60,22 @@
 Message framing (vs. [http2-transport-mapping](http://www.grpc.io/docs/guides/wire.html#http2-transport-mapping))
 
 1. Response status encoded as part of the response body
-  * Key-value pairs encoded in the HTTP/2 [literal header format](https://tools.ietf.org/html/rfc7541#section-6.2) as a single header block.
+  * Key-value pairs encoded as a HTTP/1 headers block (without the terminating newline).
 2. 8th (MSB) bit of the 1st gRPC frame byte
   * 0: data
   * 1: trailers
 3. Trailers must be the last message of the response, as enforced
 by the implementation
 4. Trailers-only responses: no change to the gRPC protocol spec.
-Trailers will be sent together with response headers, with no message
+Trailers may be sent together with response headers, with no message
 in the body.
 
 ---
 
-User Agent
+User Agent and Server headers
 
-* grpc-web-javascript/0.1
+* U-A: grpc-web-javascript/0.1
+* Server: grpc-web-gateway/0.1
 
 ---
 
diff --git a/doc/command_line_tool.md b/doc/command_line_tool.md
index 79a131c..77c3d07 100644
--- a/doc/command_line_tool.md
+++ b/doc/command_line_tool.md
@@ -2,8 +2,8 @@
 
 ## Overview
 
-This document describes the command line tool that comes with gRPC repository. It is desireable to have command line
-tools written in other languages to roughly follow the same syntax and flags.
+This document describes the command line tool that comes with gRPC repository. It is desirable to have command line
+tools written in other languages roughly follow the same syntax and flags.
 
 At this point, the tool needs to be built from source, and it should be moved out to grpc-tools repository as a stand
 alone application once it is mature enough.
@@ -30,7 +30,26 @@
 
 ## Code location
 
-To use the tool, you need to get the grpc repository and in the grpc directory execute
+To use the tool, you need to get the grpc repository and make sure your system
+has the prerequisites for building grpc from source, given in the [installation
+instructions](https://github.com/grpc/grpc/blob/master/INSTALL.md).
+
+In order to build the grpc command line tool from a fresh clone of the grpc
+repository, you need to run the following command to update submodules:
+
+```
+git submodule update --init
+```
+
+You also need to have the gflags library installed on your system. On Linux
+systems, gflags can be installed with the following command:
+
+```
+sudo apt-get install libgflags-dev
+```
+
+Once the prerequisites are satisfied, you can build the command line tool with
+the command:
 
 ```
 $ make grpc_cli
diff --git a/doc/environment_variables.md b/doc/environment_variables.md
index 832762a..a380673 100644
--- a/doc/environment_variables.md
+++ b/doc/environment_variables.md
@@ -35,6 +35,8 @@
   A comma separated list of tracers that provide additional insight into how
   gRPC C core is processing requests via debug logs. Available tracers include:
   - api - traces api calls to the C core
+  - bdp_estimator - traces behavior of bdp estimation logic
+  - call_error - traces the possible errors contributing to final call status
   - channel - traces operations on the C core channel stack
   - combiner - traces combiner lock state
   - compression - traces compression operations
@@ -55,10 +57,10 @@
   - secure_endpoint - traces bytes flowing through encrypted channels
   - transport_security - traces metadata about secure channel establishment
   - tcp - traces bytes in and out of a channel
-  
+
   'all' can additionally be used to turn all traces on.
   Individual traces can be disabled by prefixing them with '-'.
- 
+
   Example:
   export GRPC_TRACE=all,-pending_tags
 
diff --git a/doc/g_stands_for.md b/doc/g_stands_for.md
index 52f8eae..53a1fdf 100644
--- a/doc/g_stands_for.md
+++ b/doc/g_stands_for.md
@@ -6,3 +6,4 @@
 
 - 1.0 'g' stands for 'gRPC'
 - 1.1 'g' stands for 'good'
+- 1.2 'g' stands for 'green'
diff --git a/doc/internationalization.md b/doc/internationalization.md
new file mode 100644
index 0000000..1b614cb
--- /dev/null
+++ b/doc/internationalization.md
@@ -0,0 +1,45 @@
+gRPC Internationalization
+=========================
+
+As a universal RPC framework, gRPC needs to be fully usable within/across different international environments. 
+This document describes gRPC API and behavior specifics when used in a non-english environment.
+
+## API Concepts
+
+While some API elements need to be able to represent non-english content, some are intentionally left as ASCII-only
+for simplicity & performance reasons.
+
+### Method name (in RPC Invocation)
+Method names are ASCII-only and may only contain characters allowed by HTTP/2 text header values. That should not
+be very limiting as most gRPC services will use protobuf which only allows method names from an even more restricted ASCII subset.
+Also, handling method names is a very hot code path so any additional encoding/decoding step is to be avoided.
+
+Recommended representation in language-specific APIs: string type.
+
+### Host name (in RPC Invocation)
+Host names are punycode encoded, but the user is responsible for providing the punycode-encoded string if she wishes to use an internationalized host name.
+
+Recommended representation in language-specific APIs: string/unicode string.
+
+NOTE: overriding host name when invoking RPCs is only supported by C-core based gRPC implementations.
+
+### Status detail/message (accompanies RPC status code)
+
+Status messages are expected to contain national-alphabet characters.
+Allowed values are unicode strings (content will be percent-encoded on the wire).
+
+Recommended representation in language-specific APIs: unicode string.
+
+### Metadata key
+Allowed values are defined by HTTP/2 standard (metadata keys are represented as HTTP/2 header/trailer names).
+
+Recommended representation in language-specific APIs: string.
+
+### Metadata value (text-valued metadata)
+Allowed values are defined by HTTP/2 standard (metadata values are represented as HTTP/2 header/trailer text values).
+
+Recommended representation in language-specific APIs: string.
+
+### Channel target (in channel creation)
+
+TBD
diff --git a/doc/service_config.md b/doc/service_config.md
index 7318b69..ecc2381 100644
--- a/doc/service_config.md
+++ b/doc/service_config.md
@@ -12,112 +12,106 @@
 
 ```
 {
-  # Load balancing policy name.
-  # Supported values are 'round_robin' and 'grpclb'.
-  # Optional; if unset, the default behavior is pick the first available
-  # backend.
-  # Note that if the resolver returns only balancer addresses and no
-  # backend addresses, gRPC will always use the 'grpclb' policy,
-  # regardless of what this field is set to.
+  // Load balancing policy name.
+  // Supported values are 'round_robin' and 'grpclb'.
+  // Optional; if unset, the default behavior is pick the first available
+  // backend.
+  // Note that if the resolver returns only balancer addresses and no
+  // backend addresses, gRPC will always use the 'grpclb' policy,
+  // regardless of what this field is set to.
   'loadBalancingPolicy': string,
 
-  # Per-method configuration.  Optional.
+  // Per-method configuration.  Optional.
   'methodConfig': [
     {
-      # The names of the methods to which this method config applies. There
-      # must be at least one name. Each name entry must be unique across the
-      # entire service config. If the 'method' field is empty, then this
-      # method config specifies the defaults for all methods for the specified
-      # service.
-      #
-      # For example, let's say that the service config contains the following
-      # method config entries:
-      #
-      # 'methodConfig': [
-      #   { 'name': [ { 'service': 'MyService' } ] ... },
-      #   { 'name': [ { 'service': 'MyService', 'method': 'Foo' } ] ... }
-      # ]
-      #
-      # For a request for MyService/Foo, we will use the second entry, because
-      # it exactly matches the service and method name.
-      # For a request for MyService/Bar, we will use the first entry, because
-      # it provides the default for all methods of MyService.
+      // The names of the methods to which this method config applies. There
+      // must be at least one name. Each name entry must be unique across the
+      // entire service config. If the 'method' field is empty, then this
+      // method config specifies the defaults for all methods for the specified
+      // service.
+      //
+      // For example, let's say that the service config contains the following
+      // method config entries:
+      //
+      // 'methodConfig': [
+      //   { 'name': [ { 'service': 'MyService' } ] ... },
+      //   { 'name': [ { 'service': 'MyService', 'method': 'Foo' } ] ... }
+      // ]
+      //
+      // For a request for MyService/Foo, we will use the second entry, because
+      // it exactly matches the service and method name.
+      // For a request for MyService/Bar, we will use the first entry, because
+      // it provides the default for all methods of MyService.
       'name': [
         {
-          # RPC service name.  Required.
-          # If using gRPC with protobuf as the IDL, then this will be of
-          # the form "pkg.service_name", where "pkg" is the package name
-          # defined in the proto file.
+          // RPC service name.  Required.
+          // If using gRPC with protobuf as the IDL, then this will be of
+          // the form "pkg.service_name", where "pkg" is the package name
+          // defined in the proto file.
           'service': string,
 
-          # RPC method name.  Optional (see above).
+          // RPC method name.  Optional (see above).
           'method': string,
         }
       ],
 
-      # Whether RPCs sent to this method should wait until the connection is
-      # ready by default. If false, the RPC will abort immediately if there
-      # is a transient failure connecting to the server. Otherwise, gRPC will
-      # attempt to connect until the deadline is exceeded.
-      #
-      # The value specified via the gRPC client API will override the value
-      # set here. However, note that setting the value in the client API will
-      # also affect transient errors encountered during name resolution,
-      # which cannot be caught by the value here, since the service config
-      # is obtained by the gRPC client via name resolution.
+      // Whether RPCs sent to this method should wait until the connection is
+      // ready by default. If false, the RPC will abort immediately if there
+      // is a transient failure connecting to the server. Otherwise, gRPC will
+      // attempt to connect until the deadline is exceeded.
+      //
+      // The value specified via the gRPC client API will override the value
+      // set here. However, note that setting the value in the client API will
+      // also affect transient errors encountered during name resolution,
+      // which cannot be caught by the value here, since the service config
+      // is obtained by the gRPC client via name resolution.
       'waitForReady': bool,
 
-      # The default timeout in seconds for RPCs sent to this method. This can
-      # be overridden in code. If no reply is received in the specified amount
-      # of time, the request is aborted and a deadline-exceeded error status
-      # is returned to the caller.
-      #
-      # The actual deadline used will be the minimum of the value specified
-      # here and the value set by the application via the gRPC client API.
-      # If either one is not set, then the other will be used.
-      # If neither is set, then the request has no deadline.
-      #
-      # The format of the value is that of the 'Duration' type defined here:
-      # https://developers.google.com/protocol-buffers/docs/proto3#json
+      // The default timeout in seconds for RPCs sent to this method. This can
+      // be overridden in code. If no reply is received in the specified amount
+      // of time, the request is aborted and a deadline-exceeded error status
+      // is returned to the caller.
+      //
+      // The actual deadline used will be the minimum of the value specified
+      // here and the value set by the application via the gRPC client API.
+      // If either one is not set, then the other will be used.
+      // If neither is set, then the request has no deadline.
+      //
+      // The format of the value is that of the 'Duration' type defined here:
+      // https://developers.google.com/protocol-buffers/docs/proto3#json
       'timeout': string,
 
-      # The maximum allowed payload size for an individual request or object
-      # in a stream (client->server) in bytes. The size which is measured is
-      # the serialized, uncompressed payload in bytes. This applies both
-      # to streaming and non-streaming requests.
-      #
-      # The actual value used is the minimum of the value specified here and
-      # the value set by the application via the gRPC client API.
-      # If either one is not set, then the other will be used.
-      # If neither is set, then the built-in default is used.
-      #
-      # If a client attempts to send an object larger than this value, it
-      # will not be sent and the client will see an error.
-      # Note that 0 is a valid value, meaning that the request message must
-      # be empty.
-      #
-      # The format of the value is that of the 'uint64' type defined here:
-      # https://developers.google.com/protocol-buffers/docs/proto3#json
-      'maxRequestMessageBytes': string,
+      // The maximum allowed payload size for an individual request or object
+      // in a stream (client->server) in bytes. The size which is measured is
+      // the serialized, uncompressed payload in bytes. This applies both
+      // to streaming and non-streaming requests.
+      //
+      // The actual value used is the minimum of the value specified here and
+      // the value set by the application via the gRPC client API.
+      // If either one is not set, then the other will be used.
+      // If neither is set, then the built-in default is used.
+      //
+      // If a client attempts to send an object larger than this value, it
+      // will not be sent and the client will see an error.
+      // Note that 0 is a valid value, meaning that the request message must
+      // be empty.
+      'maxRequestMessageBytes': number,
 
-      # The maximum allowed payload size for an individual response or object
-      # in a stream (server->client) in bytes. The size which is measured is
-      # the serialized, uncompressed payload in bytes. This applies both
-      # to streaming and non-streaming requests.
-      #
-      # The actual value used is the minimum of the value specified here and
-      # the value set by the application via the gRPC client API.
-      # If either one is not set, then the other will be used.
-      # If neither is set, then the built-in default is used.
-      #
-      # If a server attempts to send an object larger than this value, it
-      # will not be sent, and the client will see an error.
-      # Note that 0 is a valid value, meaning that the response message must
-      # be empty.
-      #
-      # The format of the value is that of the 'uint64' type defined here:
-      # https://developers.google.com/protocol-buffers/docs/proto3#json
-      'maxResponseMessageBytes': string
+      // The maximum allowed payload size for an individual response or object
+      // in a stream (server->client) in bytes. The size which is measured is
+      // the serialized, uncompressed payload in bytes. This applies both
+      // to streaming and non-streaming requests.
+      //
+      // The actual value used is the minimum of the value specified here and
+      // the value set by the application via the gRPC client API.
+      // If either one is not set, then the other will be used.
+      // If neither is set, then the built-in default is used.
+      //
+      // If a server attempts to send an object larger than this value, it
+      // will not be sent, and the client will see an error.
+      // Note that 0 is a valid value, meaning that the response message must
+      // be empty.
+      'maxResponseMessageBytes': number
     }
   ]
 }
diff --git a/etc/roots.pem b/etc/roots.pem
index 79357e0..6660567 100644
--- a/etc/roots.pem
+++ b/etc/roots.pem
@@ -320,35 +320,6 @@
 0vdXcDazv/wor3ElhVsT/h5/WrQ8
 -----END CERTIFICATE-----
 
-# Issuer: O=RSA Security Inc OU=RSA Security 2048 V3
-# Subject: O=RSA Security Inc OU=RSA Security 2048 V3
-# Label: "RSA Security 2048 v3"
-# Serial: 13297492616345471454730593562152402946
-# MD5 Fingerprint: 77:0d:19:b1:21:fd:00:42:9c:3e:0c:a5:dd:0b:02:8e
-# SHA1 Fingerprint: 25:01:90:19:cf:fb:d9:99:1c:b7:68:25:74:8d:94:5f:30:93:95:42
-# SHA256 Fingerprint: af:8b:67:62:a1:e5:28:22:81:61:a9:5d:5c:55:9e:e2:66:27:8f:75:d7:9e:83:01:89:a5:03:50:6a:bd:6b:4c
------BEGIN CERTIFICATE-----
-MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6
-MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp
-dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX
-BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy
-MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp
-eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg
-/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl
-wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh
-AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2
-PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu
-AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
-BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR
-MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc
-HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/
-Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+
-f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO
-rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch
-6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3
-7CAFYd4=
------END CERTIFICATE-----
-
 # Issuer: CN=GeoTrust Global CA O=GeoTrust Inc.
 # Subject: CN=GeoTrust Global CA O=GeoTrust Inc.
 # Label: "GeoTrust Global CA"
@@ -1987,34 +1958,6 @@
 yZyQ2uypQjyttgI=
 -----END CERTIFICATE-----
 
-# Issuer: CN=Buypass Class 2 CA 1 O=Buypass AS-983163327
-# Subject: CN=Buypass Class 2 CA 1 O=Buypass AS-983163327
-# Label: "Buypass Class 2 CA 1"
-# Serial: 1
-# MD5 Fingerprint: b8:08:9a:f0:03:cc:1b:0d:c8:6c:0b:76:a1:75:64:23
-# SHA1 Fingerprint: a0:a1:ab:90:c9:fc:84:7b:3b:12:61:e8:97:7d:5f:d3:22:61:d3:cc
-# SHA256 Fingerprint: 0f:4e:9c:dd:26:4b:02:55:50:d1:70:80:63:40:21:4f:e9:44:34:c9:b0:2f:69:7e:c7:10:fc:5f:ea:fb:5e:38
------BEGIN CERTIFICATE-----
-MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd
-MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg
-Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL
-MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD
-VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0
-ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX
-l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB
-HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B
-5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3
-WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
-AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD
-AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP
-gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+
-DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu
-BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs
-h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk
-LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho
------END CERTIFICATE-----
-
 # Issuer: O=certSIGN OU=certSIGN ROOT CA
 # Subject: O=certSIGN OU=certSIGN ROOT CA
 # Label: "certSIGN ROOT CA"
@@ -2976,51 +2919,6 @@
 BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5
 -----END CERTIFICATE-----
 
-# Issuer: CN=Root CA Generalitat Valenciana O=Generalitat Valenciana OU=PKIGVA
-# Subject: CN=Root CA Generalitat Valenciana O=Generalitat Valenciana OU=PKIGVA
-# Label: "Root CA Generalitat Valenciana"
-# Serial: 994436456
-# MD5 Fingerprint: 2c:8c:17:5e:b1:54:ab:93:17:b5:36:5a:db:d1:c6:f2
-# SHA1 Fingerprint: a0:73:e5:c5:bd:43:61:0d:86:4c:21:13:0a:85:58:57:cc:9c:ea:46
-# SHA256 Fingerprint: 8c:4e:df:d0:43:48:f3:22:96:9e:7e:29:a4:cd:4d:ca:00:46:55:06:1c:16:e1:b0:76:42:2e:f3:42:ad:63:0e
------BEGIN CERTIFICATE-----
-MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJF
-UzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJ
-R1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcN
-MDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3WjBoMQswCQYDVQQGEwJFUzEfMB0G
-A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScw
-JQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+
-WmmmO3I2F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKj
-SgbwJ/BXufjpTjJ3Cj9BZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGl
-u6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQD0EbtFpKd71ng+CT516nDOeB0/RSrFOy
-A8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXteJajCq+TA81yc477OMUxk
-Hl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMBAAGjggM7
-MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBr
-aS5ndmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIIC
-IwYKKwYBBAG/VQIBADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8A
-cgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIA
-YQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIAYQBsAGkAdABhAHQAIABWAGEA
-bABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQByAGEAYwBpAPMA
-bgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA
-aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMA
-aQBvAG4AYQBtAGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQA
-ZQAgAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEA
-YwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBuAHQAcgBhACAAZQBuACAAbABhACAA
-ZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAAOgAvAC8AdwB3AHcA
-LgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0dHA6
-Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+y
-eAT8MIGVBgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQsw
-CQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0G
-A1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVu
-Y2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRhTvW1yEICKrNcda3Fbcrn
-lD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdzCkj+IHLt
-b8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg
-9J63NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XF
-ducTZnV+ZfsBn5OHiJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmC
-IoaZM3Fa6hlXPZHNqcCjbgcTpsnt+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM=
------END CERTIFICATE-----
-
 # Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA
 # Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA
 # Label: "TWCA Root Certification Authority"
@@ -5315,3 +5213,192 @@
 mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
 emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
 -----END CERTIFICATE-----
+
+# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM
+# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM
+# Label: "AC RAIZ FNMT-RCM"
+# Serial: 485876308206448804701554682760554759
+# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d
+# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20
+# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx
+CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ
+WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ
+BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG
+Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/
+yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf
+BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz
+WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF
+tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z
+374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC
+IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL
+mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7
+wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS
+MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2
+ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet
+UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H
+YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3
+LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1
+RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM
+LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf
+77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N
+JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm
+fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp
+6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp
+1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B
+9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok
+RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv
+uu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 1 O=Amazon
+# Subject: CN=Amazon Root CA 1 O=Amazon
+# Label: "Amazon Root CA 1"
+# Serial: 143266978916655856878034712317230054538369994
+# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6
+# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16
+# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
+rqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 2 O=Amazon
+# Subject: CN=Amazon Root CA 2 O=Amazon
+# Label: "Amazon Root CA 2"
+# Serial: 143266982885963551818349160658925006970653239
+# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66
+# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a
+# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
+4PsJYGw=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 3 O=Amazon
+# Subject: CN=Amazon Root CA 3 O=Amazon
+# Label: "Amazon Root CA 3"
+# Serial: 143266986699090766294700635381230934788665930
+# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87
+# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e
+# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
+YyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 4 O=Amazon
+# Subject: CN=Amazon Root CA 4 O=Amazon
+# Label: "Amazon Root CA 4"
+# Serial: 143266989758080763974105200630763877849284878
+# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd
+# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be
+# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
+1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=LuxTrust Global Root 2 O=LuxTrust S.A.
+# Subject: CN=LuxTrust Global Root 2 O=LuxTrust S.A.
+# Label: "LuxTrust Global Root 2"
+# Serial: 59914338225734147123941058376788110305822489521
+# MD5 Fingerprint: b2:e1:09:00:61:af:f7:f1:91:6f:c4:ad:8d:5e:3b:7c
+# SHA1 Fingerprint: 1e:0e:56:19:0a:d1:8b:25:98:b2:04:44:ff:66:8a:04:17:99:5f:3f
+# SHA256 Fingerprint: 54:45:5f:71:29:c2:0b:14:47:c4:18:f9:97:16:8f:24:c5:8f:c5:02:3b:f5:da:5b:e2:eb:6e:1d:d8:90:2e:d5
+-----BEGIN CERTIFICATE-----
+MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQEL
+BQAwRjELMAkGA1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNV
+BAMMFkx1eFRydXN0IEdsb2JhbCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUw
+MzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEWMBQGA1UECgwNTHV4VHJ1c3QgUy5B
+LjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wmKb3F
+ibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTem
+hfY7RBi2xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1
+EMShduxq3sVs35a0VkBCwGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsn
+Xpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4
+zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkmFRseTJIpgp7VkoGSQXAZ
+96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niFwpN6cj5m
+j5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4g
+DEa/a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+
+8kPREd8vZS9kzl8UubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2j
+X5t/Lax5Gw5CMZdjpPuKadUiDTSQMC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmH
+hFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGByuB
+KwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5Lmx1eHRydXN0
+Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQEL
+BQADggIBAGoZFO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9
+BzZAcg4atmpZ1gDlaCDdLnINH2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTO
+jFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW7MM3LGVYvlcAGvI1+ut7MV3CwRI9
+loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIuZY+kt9J/Z93I055c
+qqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWAVWe+
+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/
+JEAdemrRTxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKre
+zrnK+T+Tb/mjuuqlPpmt/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQf
+LSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+
+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31IiyBMz2TWuJdGsE7RKlY6
+oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
+-----END CERTIFICATE-----
diff --git a/examples/csharp/helloworld/generate_protos.bat b/examples/csharp/helloworld/generate_protos.bat
index 28b7395..0afa129 100644
--- a/examples/csharp/helloworld/generate_protos.bat
+++ b/examples/csharp/helloworld/generate_protos.bat
@@ -34,7 +34,7 @@
 @rem enter this directory
 cd /d %~dp0
 
-set TOOLS_PATH=packages\Grpc.Tools.1.0.0\tools\windows_x86
+set TOOLS_PATH=packages\Grpc.Tools.1.0.1\tools\windows_x86
 
 %TOOLS_PATH%\protoc.exe -I../../protos --csharp_out Greeter  ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe
 
diff --git a/examples/php/composer.json b/examples/php/composer.json
index 3d1a95d..f0b9977 100644
--- a/examples/php/composer.json
+++ b/examples/php/composer.json
@@ -2,7 +2,11 @@
   "name": "grpc/grpc-demo",
   "description": "gRPC example for PHP",
   "require": {
-    "ext-grpc": "*",
-    "grpc/grpc": "v1.0.0"
+    "grpc/grpc": "v1.1.0"
+  },
+  "autoload": {
+    "psr-4": {
+      "": "route_guide/"
+    }
   }
 }
diff --git a/examples/php/greeter_client.php b/examples/php/greeter_client.php
index a5c0865..986a4bb 100644
--- a/examples/php/greeter_client.php
+++ b/examples/php/greeter_client.php
@@ -33,14 +33,18 @@
  */
 
 require dirname(__FILE__).'/vendor/autoload.php';
-require dirname(__FILE__).'/helloworld.php';
+
+// The following includes are needed when using protobuf 3.1.0
+// and will suppress warnings when using protobuf 3.2.0+
+@include_once dirname(__FILE__).'/helloworld.pb.php';
+@include_once dirname(__FILE__).'/helloworld_grpc_pb.php';
 
 function greet($name)
 {
-    $client = new helloworld\GreeterClient('localhost:50051', [
+    $client = new Helloworld\GreeterClient('localhost:50051', [
         'credentials' => Grpc\ChannelCredentials::createInsecure(),
     ]);
-    $request = new helloworld\HelloRequest();
+    $request = new Helloworld\HelloRequest();
     $request->setName($name);
     list($reply, $status) = $client->SayHello($request)->wait();
     $message = $reply->getMessage();
diff --git a/examples/php/helloworld.pb.php b/examples/php/helloworld.pb.php
new file mode 100644
index 0000000..757a4a5
--- /dev/null
+++ b/examples/php/helloworld.pb.php
@@ -0,0 +1,58 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: helloworld.proto
+
+namespace Helloworld;
+
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+class HelloRequest extends \Google\Protobuf\Internal\Message
+{
+    private $name = '';
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function setName($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->name = $var;
+    }
+
+}
+
+class HelloReply extends \Google\Protobuf\Internal\Message
+{
+    private $message = '';
+
+    public function getMessage()
+    {
+        return $this->message;
+    }
+
+    public function setMessage($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->message = $var;
+    }
+
+}
+
+$pool = DescriptorPool::getGeneratedPool();
+
+$pool->internalAddGeneratedFile(hex2bin(
+    "0ae6010a1068656c6c6f776f726c642e70726f746f120a68656c6c6f776f" .
+    "726c64221c0a0c48656c6c6f52657175657374120c0a046e616d65180120" .
+    "012809221d0a0a48656c6c6f5265706c79120f0a076d6573736167651801" .
+    "2001280932490a0747726565746572123e0a0853617948656c6c6f12182e" .
+    "68656c6c6f776f726c642e48656c6c6f526571756573741a162e68656c6c" .
+    "6f776f726c642e48656c6c6f5265706c79220042360a1b696f2e67727063" .
+    "2e6578616d706c65732e68656c6c6f776f726c64420f48656c6c6f576f72" .
+    "6c6450726f746f5001a20203484c57620670726f746f33"
+));
+
diff --git a/examples/php/helloworld.php b/examples/php/helloworld.php
deleted file mode 100644
index 697f52a..0000000
--- a/examples/php/helloworld.php
+++ /dev/null
@@ -1,168 +0,0 @@
-<?php
-// DO NOT EDIT! Generated by Protobuf-PHP protoc plugin 1.0
-// Source: helloworld.proto
-//   Date: 2015-09-24 20:40:14
-
-namespace helloworld {
-
-  class HelloRequest extends \DrSlump\Protobuf\Message
-  {
-      /**  @var string */
-    public $name = null;
-
-    /** @var \Closure[] */
-    protected static $__extensions = array();
-
-      public static function descriptor()
-      {
-          $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloRequest');
-
-      // OPTIONAL STRING name = 1
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 1;
-          $f->name = 'name';
-          $f->type = \DrSlump\Protobuf::TYPE_STRING;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $descriptor->addField($f);
-
-          foreach (self::$__extensions as $cb) {
-              $descriptor->addField($cb(), true);
-          }
-
-          return $descriptor;
-      }
-
-    /**
-     * Check if <name> has a value.
-     *
-     * @return bool
-     */
-    public function hasName()
-    {
-        return $this->_has(1);
-    }
-
-    /**
-     * Clear <name> value.
-     *
-     * @return \helloworld\HelloRequest
-     */
-    public function clearName()
-    {
-        return $this->_clear(1);
-    }
-
-    /**
-     * Get <name> value.
-     *
-     * @return string
-     */
-    public function getName()
-    {
-        return $this->_get(1);
-    }
-
-    /**
-     * Set <name> value.
-     *
-     * @param string $value
-     *
-     * @return \helloworld\HelloRequest
-     */
-    public function setName($value)
-    {
-        return $this->_set(1, $value);
-    }
-  }
-}
-
-namespace helloworld {
-
-  class HelloReply extends \DrSlump\Protobuf\Message
-  {
-      /**  @var string */
-    public $message = null;
-
-    /** @var \Closure[] */
-    protected static $__extensions = array();
-
-      public static function descriptor()
-      {
-          $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloReply');
-
-      // OPTIONAL STRING message = 1
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 1;
-          $f->name = 'message';
-          $f->type = \DrSlump\Protobuf::TYPE_STRING;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $descriptor->addField($f);
-
-          foreach (self::$__extensions as $cb) {
-              $descriptor->addField($cb(), true);
-          }
-
-          return $descriptor;
-      }
-
-    /**
-     * Check if <message> has a value.
-     *
-     * @return bool
-     */
-    public function hasMessage()
-    {
-        return $this->_has(1);
-    }
-
-    /**
-     * Clear <message> value.
-     *
-     * @return \helloworld\HelloReply
-     */
-    public function clearMessage()
-    {
-        return $this->_clear(1);
-    }
-
-    /**
-     * Get <message> value.
-     *
-     * @return string
-     */
-    public function getMessage()
-    {
-        return $this->_get(1);
-    }
-
-    /**
-     * Set <message> value.
-     *
-     * @param string $value
-     *
-     * @return \helloworld\HelloReply
-     */
-    public function setMessage($value)
-    {
-        return $this->_set(1, $value);
-    }
-  }
-}
-
-namespace helloworld {
-
-  class GreeterClient extends \Grpc\BaseStub
-  {
-      public function __construct($hostname, $opts)
-      {
-          parent::__construct($hostname, $opts);
-      }
-    /**
-     * @param helloworld\HelloRequest $input
-     */
-    public function SayHello(\helloworld\HelloRequest $argument, $metadata = array(), $options = array())
-    {
-        return $this->_simpleRequest('/helloworld.Greeter/SayHello', $argument, '\helloworld\HelloReply::deserialize', $metadata, $options);
-    }
-  }
-}
diff --git a/examples/php/helloworld.proto b/examples/php/helloworld.proto
deleted file mode 100644
index ad8f7a1..0000000
--- a/examples/php/helloworld.proto
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto2";
-
-option java_package = "ex.grpc";
-
-package helloworld;
-
-// The greeting service definition.
-service Greeter {
-  // Sends a greeting
-  rpc SayHello (HelloRequest) returns (HelloReply) {}
-}
-
-// The request message containing the user's name.
-message HelloRequest {
-  optional string name = 1;
-}
-
-// The response message containing the greetings
-message HelloReply {
-  optional string message = 1;
-}
diff --git a/examples/php/helloworld_grpc_pb.php b/examples/php/helloworld_grpc_pb.php
new file mode 100644
index 0000000..cae48bc
--- /dev/null
+++ b/examples/php/helloworld_grpc_pb.php
@@ -0,0 +1,64 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+namespace Helloworld {
+
+  // The greeting service definition.
+  class GreeterClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+      parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * Sends a greeting
+     * @param \Helloworld\HelloRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function SayHello(\Helloworld\HelloRequest $argument,
+      $metadata = [], $options = []) {
+      return $this->_simpleRequest('/helloworld.Greeter/SayHello',
+      $argument,
+      ['\Helloworld\HelloReply', 'decode'],
+      $metadata, $options);
+    }
+
+  }
+
+}
diff --git a/examples/php/route_guide/route_guide.pb.php b/examples/php/route_guide/route_guide.pb.php
new file mode 100644
index 0000000..78f3ea6
--- /dev/null
+++ b/examples/php/route_guide/route_guide.pb.php
@@ -0,0 +1,209 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: route_guide.proto
+
+namespace Routeguide;
+
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+class Point extends \Google\Protobuf\Internal\Message
+{
+    private $latitude = 0;
+    private $longitude = 0;
+
+    public function getLatitude()
+    {
+        return $this->latitude;
+    }
+
+    public function setLatitude($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->latitude = $var;
+    }
+
+    public function getLongitude()
+    {
+        return $this->longitude;
+    }
+
+    public function setLongitude($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->longitude = $var;
+    }
+
+}
+
+class Rectangle extends \Google\Protobuf\Internal\Message
+{
+    private $lo = null;
+    private $hi = null;
+
+    public function getLo()
+    {
+        return $this->lo;
+    }
+
+    public function setLo(&$var)
+    {
+        GPBUtil::checkMessage($var, \Routeguide\Point::class);
+        $this->lo = $var;
+    }
+
+    public function getHi()
+    {
+        return $this->hi;
+    }
+
+    public function setHi(&$var)
+    {
+        GPBUtil::checkMessage($var, \Routeguide\Point::class);
+        $this->hi = $var;
+    }
+
+}
+
+class Feature extends \Google\Protobuf\Internal\Message
+{
+    private $name = '';
+    private $location = null;
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function setName($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->name = $var;
+    }
+
+    public function getLocation()
+    {
+        return $this->location;
+    }
+
+    public function setLocation(&$var)
+    {
+        GPBUtil::checkMessage($var, \Routeguide\Point::class);
+        $this->location = $var;
+    }
+
+}
+
+class RouteNote extends \Google\Protobuf\Internal\Message
+{
+    private $location = null;
+    private $message = '';
+
+    public function getLocation()
+    {
+        return $this->location;
+    }
+
+    public function setLocation(&$var)
+    {
+        GPBUtil::checkMessage($var, \Routeguide\Point::class);
+        $this->location = $var;
+    }
+
+    public function getMessage()
+    {
+        return $this->message;
+    }
+
+    public function setMessage($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->message = $var;
+    }
+
+}
+
+class RouteSummary extends \Google\Protobuf\Internal\Message
+{
+    private $point_count = 0;
+    private $feature_count = 0;
+    private $distance = 0;
+    private $elapsed_time = 0;
+
+    public function getPointCount()
+    {
+        return $this->point_count;
+    }
+
+    public function setPointCount($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->point_count = $var;
+    }
+
+    public function getFeatureCount()
+    {
+        return $this->feature_count;
+    }
+
+    public function setFeatureCount($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->feature_count = $var;
+    }
+
+    public function getDistance()
+    {
+        return $this->distance;
+    }
+
+    public function setDistance($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->distance = $var;
+    }
+
+    public function getElapsedTime()
+    {
+        return $this->elapsed_time;
+    }
+
+    public function setElapsedTime($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->elapsed_time = $var;
+    }
+
+}
+
+$pool = DescriptorPool::getGeneratedPool();
+
+$pool->internalAddGeneratedFile(hex2bin(
+    "0ac5050a11726f7574655f67756964652e70726f746f120a726f75746567" .
+    "75696465222c0a05506f696e7412100a086c617469747564651801200128" .
+    "0512110a096c6f6e67697475646518022001280522490a0952656374616e" .
+    "676c65121d0a026c6f18012001280b32112e726f75746567756964652e50" .
+    "6f696e74121d0a02686918022001280b32112e726f75746567756964652e" .
+    "506f696e74223c0a0746656174757265120c0a046e616d65180120012809" .
+    "12230a086c6f636174696f6e18022001280b32112e726f75746567756964" .
+    "652e506f696e7422410a09526f7574654e6f746512230a086c6f63617469" .
+    "6f6e18012001280b32112e726f75746567756964652e506f696e74120f0a" .
+    "076d65737361676518022001280922620a0c526f75746553756d6d617279" .
+    "12130a0b706f696e745f636f756e7418012001280512150a0d6665617475" .
+    "72655f636f756e7418022001280512100a0864697374616e636518032001" .
+    "280512140a0c656c61707365645f74696d651804200128053285020a0a52" .
+    "6f757465477569646512360a0a4765744665617475726512112e726f7574" .
+    "6567756964652e506f696e741a132e726f75746567756964652e46656174" .
+    "7572652200123e0a0c4c697374466561747572657312152e726f75746567" .
+    "756964652e52656374616e676c651a132e726f75746567756964652e4665" .
+    "617475726522003001123e0a0b5265636f7264526f75746512112e726f75" .
+    "746567756964652e506f696e741a182e726f75746567756964652e526f75" .
+    "746553756d6d61727922002801123f0a09526f7574654368617412152e72" .
+    "6f75746567756964652e526f7574654e6f74651a152e726f757465677569" .
+    "64652e526f7574654e6f746522002801300142360a1b696f2e677270632e" .
+    "6578616d706c65732e726f7574656775696465420f526f75746547756964" .
+    "6550726f746f5001a20203525447620670726f746f33"
+));
+
diff --git a/examples/php/route_guide/route_guide.php b/examples/php/route_guide/route_guide.php
deleted file mode 100644
index 65045d0..0000000
--- a/examples/php/route_guide/route_guide.php
+++ /dev/null
@@ -1,789 +0,0 @@
-<?php
-// DO NOT EDIT! Generated by Protobuf-PHP protoc plugin 1.0
-// Source: route_guide.proto
-//   Date: 2015-09-24 21:21:51
-
-namespace routeguide {
-
-  class Point extends \DrSlump\Protobuf\Message
-  {
-      /**  @var int */
-    public $latitude = 0;
-
-    /**  @var int */
-    public $longitude = 0;
-
-    /** @var \Closure[] */
-    protected static $__extensions = array();
-
-      public static function descriptor()
-      {
-          $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.Point');
-
-      // OPTIONAL INT32 latitude = 1
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 1;
-          $f->name = 'latitude';
-          $f->type = \DrSlump\Protobuf::TYPE_INT32;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->default = 0;
-          $descriptor->addField($f);
-
-      // OPTIONAL INT32 longitude = 2
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 2;
-          $f->name = 'longitude';
-          $f->type = \DrSlump\Protobuf::TYPE_INT32;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->default = 0;
-          $descriptor->addField($f);
-
-          foreach (self::$__extensions as $cb) {
-              $descriptor->addField($cb(), true);
-          }
-
-          return $descriptor;
-      }
-
-    /**
-     * Check if <latitude> has a value.
-     *
-     * @return bool
-     */
-    public function hasLatitude()
-    {
-        return $this->_has(1);
-    }
-
-    /**
-     * Clear <latitude> value.
-     *
-     * @return \routeguide\Point
-     */
-    public function clearLatitude()
-    {
-        return $this->_clear(1);
-    }
-
-    /**
-     * Get <latitude> value.
-     *
-     * @return int
-     */
-    public function getLatitude()
-    {
-        return $this->_get(1);
-    }
-
-    /**
-     * Set <latitude> value.
-     *
-     * @param int $value
-     *
-     * @return \routeguide\Point
-     */
-    public function setLatitude($value)
-    {
-        return $this->_set(1, $value);
-    }
-
-    /**
-     * Check if <longitude> has a value.
-     *
-     * @return bool
-     */
-    public function hasLongitude()
-    {
-        return $this->_has(2);
-    }
-
-    /**
-     * Clear <longitude> value.
-     *
-     * @return \routeguide\Point
-     */
-    public function clearLongitude()
-    {
-        return $this->_clear(2);
-    }
-
-    /**
-     * Get <longitude> value.
-     *
-     * @return int
-     */
-    public function getLongitude()
-    {
-        return $this->_get(2);
-    }
-
-    /**
-     * Set <longitude> value.
-     *
-     * @param int $value
-     *
-     * @return \routeguide\Point
-     */
-    public function setLongitude($value)
-    {
-        return $this->_set(2, $value);
-    }
-  }
-}
-
-namespace routeguide {
-
-  class Rectangle extends \DrSlump\Protobuf\Message
-  {
-      /**  @var \routeguide\Point */
-    public $lo = null;
-
-    /**  @var \routeguide\Point */
-    public $hi = null;
-
-    /** @var \Closure[] */
-    protected static $__extensions = array();
-
-      public static function descriptor()
-      {
-          $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.Rectangle');
-
-      // OPTIONAL MESSAGE lo = 1
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 1;
-          $f->name = 'lo';
-          $f->type = \DrSlump\Protobuf::TYPE_MESSAGE;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->reference = '\routeguide\Point';
-          $descriptor->addField($f);
-
-      // OPTIONAL MESSAGE hi = 2
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 2;
-          $f->name = 'hi';
-          $f->type = \DrSlump\Protobuf::TYPE_MESSAGE;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->reference = '\routeguide\Point';
-          $descriptor->addField($f);
-
-          foreach (self::$__extensions as $cb) {
-              $descriptor->addField($cb(), true);
-          }
-
-          return $descriptor;
-      }
-
-    /**
-     * Check if <lo> has a value.
-     *
-     * @return bool
-     */
-    public function hasLo()
-    {
-        return $this->_has(1);
-    }
-
-    /**
-     * Clear <lo> value.
-     *
-     * @return \routeguide\Rectangle
-     */
-    public function clearLo()
-    {
-        return $this->_clear(1);
-    }
-
-    /**
-     * Get <lo> value.
-     *
-     * @return \routeguide\Point
-     */
-    public function getLo()
-    {
-        return $this->_get(1);
-    }
-
-    /**
-     * Set <lo> value.
-     *
-     * @param \routeguide\Point $value
-     *
-     * @return \routeguide\Rectangle
-     */
-    public function setLo(\routeguide\Point $value)
-    {
-        return $this->_set(1, $value);
-    }
-
-    /**
-     * Check if <hi> has a value.
-     *
-     * @return bool
-     */
-    public function hasHi()
-    {
-        return $this->_has(2);
-    }
-
-    /**
-     * Clear <hi> value.
-     *
-     * @return \routeguide\Rectangle
-     */
-    public function clearHi()
-    {
-        return $this->_clear(2);
-    }
-
-    /**
-     * Get <hi> value.
-     *
-     * @return \routeguide\Point
-     */
-    public function getHi()
-    {
-        return $this->_get(2);
-    }
-
-    /**
-     * Set <hi> value.
-     *
-     * @param \routeguide\Point $value
-     *
-     * @return \routeguide\Rectangle
-     */
-    public function setHi(\routeguide\Point $value)
-    {
-        return $this->_set(2, $value);
-    }
-  }
-}
-
-namespace routeguide {
-
-  class Feature extends \DrSlump\Protobuf\Message
-  {
-      /**  @var string */
-    public $name = null;
-
-    /**  @var \routeguide\Point */
-    public $location = null;
-
-    /** @var \Closure[] */
-    protected static $__extensions = array();
-
-      public static function descriptor()
-      {
-          $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.Feature');
-
-      // OPTIONAL STRING name = 1
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 1;
-          $f->name = 'name';
-          $f->type = \DrSlump\Protobuf::TYPE_STRING;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $descriptor->addField($f);
-
-      // OPTIONAL MESSAGE location = 2
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 2;
-          $f->name = 'location';
-          $f->type = \DrSlump\Protobuf::TYPE_MESSAGE;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->reference = '\routeguide\Point';
-          $descriptor->addField($f);
-
-          foreach (self::$__extensions as $cb) {
-              $descriptor->addField($cb(), true);
-          }
-
-          return $descriptor;
-      }
-
-    /**
-     * Check if <name> has a value.
-     *
-     * @return bool
-     */
-    public function hasName()
-    {
-        return $this->_has(1);
-    }
-
-    /**
-     * Clear <name> value.
-     *
-     * @return \routeguide\Feature
-     */
-    public function clearName()
-    {
-        return $this->_clear(1);
-    }
-
-    /**
-     * Get <name> value.
-     *
-     * @return string
-     */
-    public function getName()
-    {
-        return $this->_get(1);
-    }
-
-    /**
-     * Set <name> value.
-     *
-     * @param string $value
-     *
-     * @return \routeguide\Feature
-     */
-    public function setName($value)
-    {
-        return $this->_set(1, $value);
-    }
-
-    /**
-     * Check if <location> has a value.
-     *
-     * @return bool
-     */
-    public function hasLocation()
-    {
-        return $this->_has(2);
-    }
-
-    /**
-     * Clear <location> value.
-     *
-     * @return \routeguide\Feature
-     */
-    public function clearLocation()
-    {
-        return $this->_clear(2);
-    }
-
-    /**
-     * Get <location> value.
-     *
-     * @return \routeguide\Point
-     */
-    public function getLocation()
-    {
-        return $this->_get(2);
-    }
-
-    /**
-     * Set <location> value.
-     *
-     * @param \routeguide\Point $value
-     *
-     * @return \routeguide\Feature
-     */
-    public function setLocation(\routeguide\Point $value)
-    {
-        return $this->_set(2, $value);
-    }
-  }
-}
-
-namespace routeguide {
-
-  class RouteNote extends \DrSlump\Protobuf\Message
-  {
-      /**  @var \routeguide\Point */
-    public $location = null;
-
-    /**  @var string */
-    public $message = null;
-
-    /** @var \Closure[] */
-    protected static $__extensions = array();
-
-      public static function descriptor()
-      {
-          $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.RouteNote');
-
-      // OPTIONAL MESSAGE location = 1
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 1;
-          $f->name = 'location';
-          $f->type = \DrSlump\Protobuf::TYPE_MESSAGE;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->reference = '\routeguide\Point';
-          $descriptor->addField($f);
-
-      // OPTIONAL STRING message = 2
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 2;
-          $f->name = 'message';
-          $f->type = \DrSlump\Protobuf::TYPE_STRING;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $descriptor->addField($f);
-
-          foreach (self::$__extensions as $cb) {
-              $descriptor->addField($cb(), true);
-          }
-
-          return $descriptor;
-      }
-
-    /**
-     * Check if <location> has a value.
-     *
-     * @return bool
-     */
-    public function hasLocation()
-    {
-        return $this->_has(1);
-    }
-
-    /**
-     * Clear <location> value.
-     *
-     * @return \routeguide\RouteNote
-     */
-    public function clearLocation()
-    {
-        return $this->_clear(1);
-    }
-
-    /**
-     * Get <location> value.
-     *
-     * @return \routeguide\Point
-     */
-    public function getLocation()
-    {
-        return $this->_get(1);
-    }
-
-    /**
-     * Set <location> value.
-     *
-     * @param \routeguide\Point $value
-     *
-     * @return \routeguide\RouteNote
-     */
-    public function setLocation(\routeguide\Point $value)
-    {
-        return $this->_set(1, $value);
-    }
-
-    /**
-     * Check if <message> has a value.
-     *
-     * @return bool
-     */
-    public function hasMessage()
-    {
-        return $this->_has(2);
-    }
-
-    /**
-     * Clear <message> value.
-     *
-     * @return \routeguide\RouteNote
-     */
-    public function clearMessage()
-    {
-        return $this->_clear(2);
-    }
-
-    /**
-     * Get <message> value.
-     *
-     * @return string
-     */
-    public function getMessage()
-    {
-        return $this->_get(2);
-    }
-
-    /**
-     * Set <message> value.
-     *
-     * @param string $value
-     *
-     * @return \routeguide\RouteNote
-     */
-    public function setMessage($value)
-    {
-        return $this->_set(2, $value);
-    }
-  }
-}
-
-namespace routeguide {
-
-  class RouteSummary extends \DrSlump\Protobuf\Message
-  {
-      /**  @var int */
-    public $point_count = 0;
-
-    /**  @var int */
-    public $feature_count = 0;
-
-    /**  @var int */
-    public $distance = 0;
-
-    /**  @var int */
-    public $elapsed_time = 0;
-
-    /** @var \Closure[] */
-    protected static $__extensions = array();
-
-      public static function descriptor()
-      {
-          $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.RouteSummary');
-
-      // OPTIONAL INT32 point_count = 1
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 1;
-          $f->name = 'point_count';
-          $f->type = \DrSlump\Protobuf::TYPE_INT32;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->default = 0;
-          $descriptor->addField($f);
-
-      // OPTIONAL INT32 feature_count = 2
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 2;
-          $f->name = 'feature_count';
-          $f->type = \DrSlump\Protobuf::TYPE_INT32;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->default = 0;
-          $descriptor->addField($f);
-
-      // OPTIONAL INT32 distance = 3
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 3;
-          $f->name = 'distance';
-          $f->type = \DrSlump\Protobuf::TYPE_INT32;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->default = 0;
-          $descriptor->addField($f);
-
-      // OPTIONAL INT32 elapsed_time = 4
-      $f = new \DrSlump\Protobuf\Field();
-          $f->number = 4;
-          $f->name = 'elapsed_time';
-          $f->type = \DrSlump\Protobuf::TYPE_INT32;
-          $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
-          $f->default = 0;
-          $descriptor->addField($f);
-
-          foreach (self::$__extensions as $cb) {
-              $descriptor->addField($cb(), true);
-          }
-
-          return $descriptor;
-      }
-
-    /**
-     * Check if <point_count> has a value.
-     *
-     * @return bool
-     */
-    public function hasPointCount()
-    {
-        return $this->_has(1);
-    }
-
-    /**
-     * Clear <point_count> value.
-     *
-     * @return \routeguide\RouteSummary
-     */
-    public function clearPointCount()
-    {
-        return $this->_clear(1);
-    }
-
-    /**
-     * Get <point_count> value.
-     *
-     * @return int
-     */
-    public function getPointCount()
-    {
-        return $this->_get(1);
-    }
-
-    /**
-     * Set <point_count> value.
-     *
-     * @param int $value
-     *
-     * @return \routeguide\RouteSummary
-     */
-    public function setPointCount($value)
-    {
-        return $this->_set(1, $value);
-    }
-
-    /**
-     * Check if <feature_count> has a value.
-     *
-     * @return bool
-     */
-    public function hasFeatureCount()
-    {
-        return $this->_has(2);
-    }
-
-    /**
-     * Clear <feature_count> value.
-     *
-     * @return \routeguide\RouteSummary
-     */
-    public function clearFeatureCount()
-    {
-        return $this->_clear(2);
-    }
-
-    /**
-     * Get <feature_count> value.
-     *
-     * @return int
-     */
-    public function getFeatureCount()
-    {
-        return $this->_get(2);
-    }
-
-    /**
-     * Set <feature_count> value.
-     *
-     * @param int $value
-     *
-     * @return \routeguide\RouteSummary
-     */
-    public function setFeatureCount($value)
-    {
-        return $this->_set(2, $value);
-    }
-
-    /**
-     * Check if <distance> has a value.
-     *
-     * @return bool
-     */
-    public function hasDistance()
-    {
-        return $this->_has(3);
-    }
-
-    /**
-     * Clear <distance> value.
-     *
-     * @return \routeguide\RouteSummary
-     */
-    public function clearDistance()
-    {
-        return $this->_clear(3);
-    }
-
-    /**
-     * Get <distance> value.
-     *
-     * @return int
-     */
-    public function getDistance()
-    {
-        return $this->_get(3);
-    }
-
-    /**
-     * Set <distance> value.
-     *
-     * @param int $value
-     *
-     * @return \routeguide\RouteSummary
-     */
-    public function setDistance($value)
-    {
-        return $this->_set(3, $value);
-    }
-
-    /**
-     * Check if <elapsed_time> has a value.
-     *
-     * @return bool
-     */
-    public function hasElapsedTime()
-    {
-        return $this->_has(4);
-    }
-
-    /**
-     * Clear <elapsed_time> value.
-     *
-     * @return \routeguide\RouteSummary
-     */
-    public function clearElapsedTime()
-    {
-        return $this->_clear(4);
-    }
-
-    /**
-     * Get <elapsed_time> value.
-     *
-     * @return int
-     */
-    public function getElapsedTime()
-    {
-        return $this->_get(4);
-    }
-
-    /**
-     * Set <elapsed_time> value.
-     *
-     * @param int $value
-     *
-     * @return \routeguide\RouteSummary
-     */
-    public function setElapsedTime($value)
-    {
-        return $this->_set(4, $value);
-    }
-  }
-}
-
-namespace routeguide {
-
-  class RouteGuideClient extends \Grpc\BaseStub
-  {
-      public function __construct($hostname, $opts)
-      {
-          parent::__construct($hostname, $opts);
-      }
-    /**
-     * @param routeguide\Point $input
-     */
-    public function GetFeature(\routeguide\Point $argument, $metadata = array(), $options = array())
-    {
-        return $this->_simpleRequest('/routeguide.RouteGuide/GetFeature', $argument, '\routeguide\Feature::deserialize', $metadata, $options);
-    }
-    /**
-     * @param routeguide\Rectangle $input
-     */
-    public function ListFeatures($argument, $metadata = array(), $options = array())
-    {
-        return $this->_serverStreamRequest('/routeguide.RouteGuide/ListFeatures', $argument, '\routeguide\Feature::deserialize', $metadata, $options);
-    }
-    /**
-     * @param routeguide\Point $input
-     */
-    public function RecordRoute($metadata = array())
-    {
-        return $this->_clientStreamRequest('/routeguide.RouteGuide/RecordRoute', '\routeguide\RouteSummary::deserialize', $metadata);
-    }
-    /**
-     * @param routeguide\RouteNote $input
-     */
-    public function RouteChat($metadata = array())
-    {
-        return $this->_bidiRequest('/routeguide.RouteGuide/RouteChat', '\routeguide\RouteNote::deserialize', $metadata);
-    }
-  }
-}
diff --git a/examples/php/route_guide/route_guide.proto b/examples/php/route_guide/route_guide.proto
deleted file mode 100644
index d50f8a5..0000000
--- a/examples/php/route_guide/route_guide.proto
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto2";
-
-option java_package = "io.grpc.examples";
-
-package routeguide;
-
-// Interface exported by the server.
-service RouteGuide {
-  // A simple RPC.
-  //
-  // Obtains the feature at a given position.
-  rpc GetFeature(Point) returns (Feature) {}
-
-  // A server-to-client streaming RPC.
-  //
-  // Obtains the Features available within the given Rectangle.  Results are
-  // streamed rather than returned at once (e.g. in a response message with a
-  // repeated field), as the rectangle may cover a large area and contain a
-  // huge number of features.
-  rpc ListFeatures(Rectangle) returns (stream Feature) {}
-
-  // A client-to-server streaming RPC.
-  //
-  // Accepts a stream of Points on a route being traversed, returning a
-  // RouteSummary when traversal is completed.
-  rpc RecordRoute(stream Point) returns (RouteSummary) {}
-
-  // A Bidirectional streaming RPC.
-  //
-  // Accepts a stream of RouteNotes sent while a route is being traversed,
-  // while receiving other RouteNotes (e.g. from other users).
-  rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
-}
-
-// Points are represented as latitude-longitude pairs in the E7 representation
-// (degrees multiplied by 10**7 and rounded to the nearest integer).
-// Latitudes should be in the range +/- 90 degrees and longitude should be in
-// the range +/- 180 degrees (inclusive).
-message Point {
-  optional int32 latitude = 1 [default = 0];
-  optional int32 longitude = 2 [default = 0];
-}
-
-// A latitude-longitude rectangle, represented as two diagonally opposite
-// points "lo" and "hi".
-message Rectangle {
-  // One corner of the rectangle.
-  optional Point lo = 1;
-
-  // The other corner of the rectangle.
-  optional Point hi = 2;
-}
-
-// A feature names something at a given point.
-//
-// If a feature could not be named, the name is empty.
-message Feature {
-  // The name of the feature.
-  optional string name = 1;
-
-  // The point where the feature is detected.
-  optional Point location = 2;
-}
-
-// A RouteNote is a message sent while at a given point.
-message RouteNote {
-  // The location from which the message is sent.
-  optional Point location = 1;
-
-  // The message to be sent.
-  optional string message = 2;
-}
-
-// A RouteSummary is received in response to a RecordRoute rpc.
-//
-// It contains the number of individual points received, the number of
-// detected features, and the total distance covered as the cumulative sum of
-// the distance between each point.
-message RouteSummary {
-  // The number of points received.
-  optional int32 point_count = 1 [default = 0];
-
-  // The number of known features passed while traversing the route.
-  optional int32 feature_count = 2 [default = 0];
-
-  // The distance covered in metres.
-  optional int32 distance = 3 [default = 0];
-
-  // The duration of the traversal in seconds.
-  optional int32 elapsed_time = 4 [default = 0];
-}
diff --git a/examples/php/route_guide/route_guide_client.php b/examples/php/route_guide/route_guide_client.php
index b3cd606..3f38c26 100644
--- a/examples/php/route_guide/route_guide_client.php
+++ b/examples/php/route_guide/route_guide_client.php
@@ -33,11 +33,15 @@
  */
 
 require dirname(__FILE__).'/../vendor/autoload.php';
-require dirname(__FILE__).'/route_guide.php';
+
+// The following includes are needed when using protobuf 3.1.0
+// and will suppress warnings when using protobuf 3.2.0+
+@include_once dirname(__FILE__).'/route_guide.pb.php';
+@include_once dirname(__FILE__).'/route_guide_grpc_pb.php';
 
 define('COORD_FACTOR', 1e7);
 
-$client = new routeguide\RouteGuideClient('localhost:50051', [
+$client = new Routeguide\RouteGuideClient('localhost:50051', [
     'credentials' => Grpc\ChannelCredentials::createInsecure(),
 ]);
 
@@ -63,7 +67,7 @@
     echo "Running GetFeature...\n";
     global $client;
 
-    $point = new routeguide\Point();
+    $point = new Routeguide\Point();
     $points = array(
         array(409146138, -746188906),
         array(0, 0),
@@ -88,15 +92,15 @@
     echo "Running ListFeatures...\n";
     global $client;
 
-    $lo_point = new routeguide\Point();
-    $hi_point = new routeguide\Point();
+    $lo_point = new Routeguide\Point();
+    $hi_point = new Routeguide\Point();
 
     $lo_point->setLatitude(400000000);
     $lo_point->setLongitude(-750000000);
     $hi_point->setLatitude(420000000);
     $hi_point->setLongitude(-730000000);
 
-    $rectangle = new routeguide\Rectangle();
+    $rectangle = new Routeguide\Rectangle();
     $rectangle->setLo($lo_point);
     $rectangle->setHi($hi_point);
 
@@ -126,7 +130,7 @@
     $num_points_in_db = count($db);
     $num_points = 10;
     for ($i = 0; $i < $num_points; ++$i) {
-        $point = new routeguide\Point();
+        $point = new Routeguide\Point();
         $index = rand(0, $num_points_in_db - 1);
         $lat = $db[$index]['location']['latitude'];
         $long = $db[$index]['location']['longitude'];
@@ -169,11 +173,11 @@
     );
 
     foreach ($notes as $n) {
-        $point = new routeguide\Point();
+        $point = new Routeguide\Point();
         $point->setLatitude($lat = $n[0]);
         $point->setLongitude($long = $n[1]);
 
-        $route_note = new routeguide\RouteNote();
+        $route_note = new Routeguide\RouteNote();
         $route_note->setLocation($point);
         $route_note->setMessage($message = $n[2]);
 
diff --git a/examples/php/route_guide/route_guide_grpc_pb.php b/examples/php/route_guide/route_guide_grpc_pb.php
new file mode 100644
index 0000000..fdc55e6
--- /dev/null
+++ b/examples/php/route_guide/route_guide_grpc_pb.php
@@ -0,0 +1,116 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+namespace Routeguide {
+
+  // Interface exported by the server.
+  class RouteGuideClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+      parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * A simple RPC.
+     *
+     * Obtains the feature at a given position.
+     *
+     * A feature with an empty name is returned if there's no feature at the given
+     * position.
+     * @param \Routeguide\Point $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function GetFeature(\Routeguide\Point $argument,
+      $metadata = [], $options = []) {
+      return $this->_simpleRequest('/routeguide.RouteGuide/GetFeature',
+      $argument,
+      ['\Routeguide\Feature', 'decode'],
+      $metadata, $options);
+    }
+
+    /**
+     * A server-to-client streaming RPC.
+     *
+     * Obtains the Features available within the given Rectangle.  Results are
+     * streamed rather than returned at once (e.g. in a response message with a
+     * repeated field), as the rectangle may cover a large area and contain a
+     * huge number of features.
+     * @param \Routeguide\Rectangle $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function ListFeatures(\Routeguide\Rectangle $argument,
+      $metadata = [], $options = []) {
+      return $this->_serverStreamRequest('/routeguide.RouteGuide/ListFeatures',
+      $argument,
+      ['\Routeguide\Feature', 'decode'],
+      $metadata, $options);
+    }
+
+    /**
+     * A client-to-server streaming RPC.
+     *
+     * Accepts a stream of Points on a route being traversed, returning a
+     * RouteSummary when traversal is completed.
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function RecordRoute($metadata = [], $options = []) {
+      return $this->_clientStreamRequest('/routeguide.RouteGuide/RecordRoute',
+      ['\Routeguide\RouteSummary','decode'],
+      $metadata, $options);
+    }
+
+    /**
+     * A Bidirectional streaming RPC.
+     *
+     * Accepts a stream of RouteNotes sent while a route is being traversed,
+     * while receiving other RouteNotes (e.g. from other users).
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function RouteChat($metadata = [], $options = []) {
+      return $this->_bidiRequest('/routeguide.RouteGuide/RouteChat',
+      ['\Routeguide\RouteNote','decode'],
+      $metadata, $options);
+    }
+
+  }
+
+}
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index aa3472d..beb7227 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -37,7 +37,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-Core'
-  version = '1.1.2'
+  version = '1.2.0-dev'
   s.version  = version
   s.summary  = 'Core cross-platform gRPC library, written in C'
   s.homepage = 'http://www.grpc.io'
@@ -162,6 +162,7 @@
                       'include/grpc/grpc.h',
                       'include/grpc/grpc_posix.h',
                       'include/grpc/grpc_security_constants.h',
+                      'include/grpc/load_reporting.h',
                       'include/grpc/slice.h',
                       'include/grpc/slice_buffer.h',
                       'include/grpc/status.h',
@@ -200,6 +201,7 @@
                       'src/core/lib/support/env.h',
                       'src/core/lib/support/mpscq.h',
                       'src/core/lib/support/murmur_hash.h',
+                      'src/core/lib/support/spinlock.h',
                       'src/core/lib/support/stack_lockfree.h',
                       'src/core/lib/support/string.h',
                       'src/core/lib/support/string_windows.h',
@@ -274,6 +276,7 @@
                       'src/core/lib/iomgr/endpoint.h',
                       'src/core/lib/iomgr/endpoint_pair.h',
                       'src/core/lib/iomgr/error.h',
+                      'src/core/lib/iomgr/error_internal.h',
                       'src/core/lib/iomgr/ev_epoll_linux.h',
                       'src/core/lib/iomgr/ev_poll_posix.h',
                       'src/core/lib/iomgr/ev_posix.h',
@@ -326,6 +329,7 @@
                       'src/core/lib/json/json_reader.h',
                       'src/core/lib/json/json_writer.h',
                       'src/core/lib/slice/percent_encoding.h',
+                      'src/core/lib/slice/slice_hash_table.h',
                       'src/core/lib/slice/slice_internal.h',
                       'src/core/lib/slice/slice_string_helpers.h',
                       'src/core/lib/surface/api_trace.h',
@@ -339,14 +343,18 @@
                       'src/core/lib/surface/init.h',
                       'src/core/lib/surface/lame_client.h',
                       'src/core/lib/surface/server.h',
+                      'src/core/lib/surface/validate_metadata.h',
+                      'src/core/lib/transport/bdp_estimator.h',
                       'src/core/lib/transport/byte_stream.h',
                       'src/core/lib/transport/connectivity_state.h',
-                      'src/core/lib/transport/mdstr_hash_table.h',
+                      'src/core/lib/transport/error_utils.h',
+                      'src/core/lib/transport/http2_errors.h',
                       'src/core/lib/transport/metadata.h',
                       'src/core/lib/transport/metadata_batch.h',
                       'src/core/lib/transport/pid_controller.h',
                       'src/core/lib/transport/service_config.h',
                       'src/core/lib/transport/static_metadata.h',
+                      'src/core/lib/transport/status_conversion.h',
                       'src/core/lib/transport/timeout_encoding.h',
                       'src/core/lib/transport/transport.h',
                       'src/core/lib/transport/transport_impl.h',
@@ -363,11 +371,9 @@
                       'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
                       'src/core/ext/transport/chttp2/transport/hpack_parser.h',
                       'src/core/ext/transport/chttp2/transport/hpack_table.h',
-                      'src/core/ext/transport/chttp2/transport/http2_errors.h',
                       'src/core/ext/transport/chttp2/transport/huffsyms.h',
                       'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
                       'src/core/ext/transport/chttp2/transport/internal.h',
-                      'src/core/ext/transport/chttp2/transport/status_conversion.h',
                       'src/core/ext/transport/chttp2/transport/stream_map.h',
                       'src/core/ext/transport/chttp2/transport/varint.h',
                       'src/core/ext/transport/chttp2/alpn/alpn.h',
@@ -384,6 +390,7 @@
                       'src/core/lib/security/credentials/plugin/plugin_credentials.h',
                       'src/core/lib/security/credentials/ssl/ssl_credentials.h',
                       'src/core/lib/security/transport/auth_filters.h',
+                      'src/core/lib/security/transport/lb_targets_info.h',
                       'src/core/lib/security/transport/secure_endpoint.h',
                       'src/core/lib/security/transport/security_connector.h',
                       'src/core/lib/security/transport/security_handshaker.h',
@@ -400,11 +407,14 @@
                       'src/core/ext/client_channel/client_channel_factory.h',
                       'src/core/ext/client_channel/connector.h',
                       'src/core/ext/client_channel/http_connect_handshaker.h',
+                      'src/core/ext/client_channel/http_proxy.h',
                       'src/core/ext/client_channel/initial_connect_string.h',
                       'src/core/ext/client_channel/lb_policy.h',
                       'src/core/ext/client_channel/lb_policy_factory.h',
                       'src/core/ext/client_channel/lb_policy_registry.h',
                       'src/core/ext/client_channel/parse_address.h',
+                      'src/core/ext/client_channel/proxy_mapper.h',
+                      'src/core/ext/client_channel/proxy_mapper_registry.h',
                       'src/core/ext/client_channel/resolver.h',
                       'src/core/ext/client_channel/resolver_factory.h',
                       'src/core/ext/client_channel/resolver_registry.h',
@@ -413,6 +423,7 @@
                       'src/core/ext/client_channel/uri_parser.h',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                       'src/core/ext/lb_policy/grpclb/grpclb.h',
+                      'src/core/ext/lb_policy/grpclb/grpclb_channel.h',
                       'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
                       'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
                       'third_party/nanopb/pb.h',
@@ -432,6 +443,11 @@
                       'src/core/ext/census/resource.h',
                       'src/core/ext/census/rpc_metric_id.h',
                       'src/core/ext/census/trace_context.h',
+                      'src/core/ext/census/trace_label.h',
+                      'src/core/ext/census/trace_propagation.h',
+                      'src/core/ext/census/trace_status.h',
+                      'src/core/ext/census/trace_string.h',
+                      'src/core/ext/census/tracing.h',
                       'src/core/lib/surface/init.c',
                       'src/core/lib/channel/channel_args.c',
                       'src/core/lib/channel/channel_stack.c',
@@ -517,6 +533,8 @@
                       'src/core/lib/slice/percent_encoding.c',
                       'src/core/lib/slice/slice.c',
                       'src/core/lib/slice/slice_buffer.c',
+                      'src/core/lib/slice/slice_hash_table.c',
+                      'src/core/lib/slice/slice_intern.c',
                       'src/core/lib/slice/slice_string_helpers.c',
                       'src/core/lib/surface/alarm.c',
                       'src/core/lib/surface/api_trace.c',
@@ -536,14 +554,16 @@
                       'src/core/lib/surface/server.c',
                       'src/core/lib/surface/validate_metadata.c',
                       'src/core/lib/surface/version.c',
+                      'src/core/lib/transport/bdp_estimator.c',
                       'src/core/lib/transport/byte_stream.c',
                       'src/core/lib/transport/connectivity_state.c',
-                      'src/core/lib/transport/mdstr_hash_table.c',
+                      'src/core/lib/transport/error_utils.c',
                       'src/core/lib/transport/metadata.c',
                       'src/core/lib/transport/metadata_batch.c',
                       'src/core/lib/transport/pid_controller.c',
                       'src/core/lib/transport/service_config.c',
                       'src/core/lib/transport/static_metadata.c',
+                      'src/core/lib/transport/status_conversion.c',
                       'src/core/lib/transport/timeout_encoding.c',
                       'src/core/lib/transport/transport.c',
                       'src/core/lib/transport/transport_op_string.c',
@@ -564,7 +584,6 @@
                       'src/core/ext/transport/chttp2/transport/huffsyms.c',
                       'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
                       'src/core/ext/transport/chttp2/transport/parsing.c',
-                      'src/core/ext/transport/chttp2/transport/status_conversion.c',
                       'src/core/ext/transport/chttp2/transport/stream_lists.c',
                       'src/core/ext/transport/chttp2/transport/stream_map.c',
                       'src/core/ext/transport/chttp2/transport/varint.c',
@@ -586,6 +605,7 @@
                       'src/core/lib/security/credentials/plugin/plugin_credentials.c',
                       'src/core/lib/security/credentials/ssl/ssl_credentials.c',
                       'src/core/lib/security/transport/client_auth_filter.c',
+                      'src/core/lib/security/transport/lb_targets_info.c',
                       'src/core/lib/security/transport/secure_endpoint.c',
                       'src/core/lib/security/transport/security_connector.c',
                       'src/core/lib/security/transport/security_handshaker.c',
@@ -606,11 +626,14 @@
                       'src/core/ext/client_channel/connector.c',
                       'src/core/ext/client_channel/default_initial_connect_string.c',
                       'src/core/ext/client_channel/http_connect_handshaker.c',
+                      'src/core/ext/client_channel/http_proxy.c',
                       'src/core/ext/client_channel/initial_connect_string.c',
                       'src/core/ext/client_channel/lb_policy.c',
                       'src/core/ext/client_channel/lb_policy_factory.c',
                       'src/core/ext/client_channel/lb_policy_registry.c',
                       'src/core/ext/client_channel/parse_address.c',
+                      'src/core/ext/client_channel/proxy_mapper.c',
+                      'src/core/ext/client_channel/proxy_mapper_registry.c',
                       'src/core/ext/client_channel/resolver.c',
                       'src/core/ext/client_channel/resolver_factory.c',
                       'src/core/ext/client_channel/resolver_registry.c',
@@ -623,6 +646,7 @@
                       'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
                       'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
                       'src/core/ext/lb_policy/grpclb/grpclb.c',
+                      'src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c',
                       'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
                       'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
                       'third_party/nanopb/pb_common.c',
@@ -656,6 +680,7 @@
                               'src/core/lib/support/env.h',
                               'src/core/lib/support/mpscq.h',
                               'src/core/lib/support/murmur_hash.h',
+                              'src/core/lib/support/spinlock.h',
                               'src/core/lib/support/stack_lockfree.h',
                               'src/core/lib/support/string.h',
                               'src/core/lib/support/string_windows.h',
@@ -686,6 +711,7 @@
                               'src/core/lib/iomgr/endpoint.h',
                               'src/core/lib/iomgr/endpoint_pair.h',
                               'src/core/lib/iomgr/error.h',
+                              'src/core/lib/iomgr/error_internal.h',
                               'src/core/lib/iomgr/ev_epoll_linux.h',
                               'src/core/lib/iomgr/ev_poll_posix.h',
                               'src/core/lib/iomgr/ev_posix.h',
@@ -738,6 +764,7 @@
                               'src/core/lib/json/json_reader.h',
                               'src/core/lib/json/json_writer.h',
                               'src/core/lib/slice/percent_encoding.h',
+                              'src/core/lib/slice/slice_hash_table.h',
                               'src/core/lib/slice/slice_internal.h',
                               'src/core/lib/slice/slice_string_helpers.h',
                               'src/core/lib/surface/api_trace.h',
@@ -751,14 +778,18 @@
                               'src/core/lib/surface/init.h',
                               'src/core/lib/surface/lame_client.h',
                               'src/core/lib/surface/server.h',
+                              'src/core/lib/surface/validate_metadata.h',
+                              'src/core/lib/transport/bdp_estimator.h',
                               'src/core/lib/transport/byte_stream.h',
                               'src/core/lib/transport/connectivity_state.h',
-                              'src/core/lib/transport/mdstr_hash_table.h',
+                              'src/core/lib/transport/error_utils.h',
+                              'src/core/lib/transport/http2_errors.h',
                               'src/core/lib/transport/metadata.h',
                               'src/core/lib/transport/metadata_batch.h',
                               'src/core/lib/transport/pid_controller.h',
                               'src/core/lib/transport/service_config.h',
                               'src/core/lib/transport/static_metadata.h',
+                              'src/core/lib/transport/status_conversion.h',
                               'src/core/lib/transport/timeout_encoding.h',
                               'src/core/lib/transport/transport.h',
                               'src/core/lib/transport/transport_impl.h',
@@ -775,11 +806,9 @@
                               'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
                               'src/core/ext/transport/chttp2/transport/hpack_parser.h',
                               'src/core/ext/transport/chttp2/transport/hpack_table.h',
-                              'src/core/ext/transport/chttp2/transport/http2_errors.h',
                               'src/core/ext/transport/chttp2/transport/huffsyms.h',
                               'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
                               'src/core/ext/transport/chttp2/transport/internal.h',
-                              'src/core/ext/transport/chttp2/transport/status_conversion.h',
                               'src/core/ext/transport/chttp2/transport/stream_map.h',
                               'src/core/ext/transport/chttp2/transport/varint.h',
                               'src/core/ext/transport/chttp2/alpn/alpn.h',
@@ -796,6 +825,7 @@
                               'src/core/lib/security/credentials/plugin/plugin_credentials.h',
                               'src/core/lib/security/credentials/ssl/ssl_credentials.h',
                               'src/core/lib/security/transport/auth_filters.h',
+                              'src/core/lib/security/transport/lb_targets_info.h',
                               'src/core/lib/security/transport/secure_endpoint.h',
                               'src/core/lib/security/transport/security_connector.h',
                               'src/core/lib/security/transport/security_handshaker.h',
@@ -812,11 +842,14 @@
                               'src/core/ext/client_channel/client_channel_factory.h',
                               'src/core/ext/client_channel/connector.h',
                               'src/core/ext/client_channel/http_connect_handshaker.h',
+                              'src/core/ext/client_channel/http_proxy.h',
                               'src/core/ext/client_channel/initial_connect_string.h',
                               'src/core/ext/client_channel/lb_policy.h',
                               'src/core/ext/client_channel/lb_policy_factory.h',
                               'src/core/ext/client_channel/lb_policy_registry.h',
                               'src/core/ext/client_channel/parse_address.h',
+                              'src/core/ext/client_channel/proxy_mapper.h',
+                              'src/core/ext/client_channel/proxy_mapper_registry.h',
                               'src/core/ext/client_channel/resolver.h',
                               'src/core/ext/client_channel/resolver_factory.h',
                               'src/core/ext/client_channel/resolver_registry.h',
@@ -825,6 +858,7 @@
                               'src/core/ext/client_channel/uri_parser.h',
                               'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                               'src/core/ext/lb_policy/grpclb/grpclb.h',
+                              'src/core/ext/lb_policy/grpclb/grpclb_channel.h',
                               'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
                               'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
                               'third_party/nanopb/pb.h',
@@ -843,12 +877,18 @@
                               'src/core/ext/census/mlog.h',
                               'src/core/ext/census/resource.h',
                               'src/core/ext/census/rpc_metric_id.h',
-                              'src/core/ext/census/trace_context.h'
+                              'src/core/ext/census/trace_context.h',
+                              'src/core/ext/census/trace_label.h',
+                              'src/core/ext/census/trace_propagation.h',
+                              'src/core/ext/census/trace_status.h',
+                              'src/core/ext/census/trace_string.h',
+                              'src/core/ext/census/tracing.h'
   end
 
   s.subspec 'Cronet-Interface' do |ss|
     ss.header_mappings_dir = 'include/grpc'
-    ss.source_files = 'include/grpc/grpc_cronet.h'
+    ss.source_files = 'include/grpc/grpc_cronet.h',
+                      'src/core/ext/transport/cronet/transport/cronet_transport.h'
   end
 
   s.subspec 'Cronet-Implementation' do |ss|
@@ -860,7 +900,7 @@
 
     ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c',
                       'src/core/ext/transport/cronet/transport/cronet_transport.c',
-                      'third_party/Cronet/bidirectional_stream_c.h'
+                      'third_party/objective_c/Cronet/bidirectional_stream_c.h'
   end
 
   s.subspec 'Tests' do |ss|
@@ -874,6 +914,7 @@
                       'test/core/end2end/end2end_test_utils.c',
                       'test/core/end2end/tests/*.{c,h}',
                       'test/core/end2end/data/*.{c,h}',
+                      'test/core/util/debugger_macros.c',
                       'test/core/util/test_config.{c,h}',
                       'test/core/util/port.h',
                       'test/core/util/port_posix.c',
diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec
index 2fb5a49..33ad74d 100644
--- a/gRPC-ProtoRPC.podspec
+++ b/gRPC-ProtoRPC.podspec
@@ -36,7 +36,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-ProtoRPC'
-  version = '1.1.2'
+  version = '1.2.0-dev'
   s.version  = version
   s.summary  = 'RPC library for Protocol Buffers, based on gRPC'
   s.homepage = 'http://www.grpc.io'
diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec
index 104a75c..35eb558 100644
--- a/gRPC-RxLibrary.podspec
+++ b/gRPC-RxLibrary.podspec
@@ -36,7 +36,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-RxLibrary'
-  version = '1.1.2'
+  version = '1.2.0-dev'
   s.version  = version
   s.summary  = 'Reactive Extensions library for iOS/OSX.'
   s.homepage = 'http://www.grpc.io'
diff --git a/gRPC.podspec b/gRPC.podspec
index 23d14df..6ba0c01 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -35,7 +35,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC'
-  version = '1.1.2'
+  version = '1.2.0-dev'
   s.version  = version
   s.summary  = 'gRPC client library for iOS/OSX'
   s.homepage = 'http://www.grpc.io'
diff --git a/grpc.def b/grpc.def
index 0162863..c660d36 100644
--- a/grpc.def
+++ b/grpc.def
@@ -69,6 +69,7 @@
     grpc_channel_create_registered_call
     grpc_call_start_batch
     grpc_call_get_peer
+    grpc_call_set_load_reporting_cost_context
     grpc_census_call_set_context
     grpc_census_call_get_context
     grpc_channel_get_target
@@ -141,17 +142,30 @@
     grpc_slice_new_with_user_data
     grpc_slice_new_with_len
     grpc_slice_malloc
+    grpc_slice_intern
     grpc_slice_from_copied_string
     grpc_slice_from_copied_buffer
     grpc_slice_from_static_string
+    grpc_slice_from_static_buffer
     grpc_slice_sub
     grpc_slice_sub_no_ref
     grpc_slice_split_tail
     grpc_slice_split_head
-    gpr_empty_slice
+    grpc_empty_slice
+    grpc_slice_default_hash_impl
+    grpc_slice_default_eq_impl
+    grpc_slice_eq
     grpc_slice_cmp
     grpc_slice_str_cmp
+    grpc_slice_buf_cmp
+    grpc_slice_buf_start_eq
+    grpc_slice_rchr
+    grpc_slice_chr
+    grpc_slice_slice
+    grpc_slice_hash
     grpc_slice_is_equivalent
+    grpc_slice_dup
+    grpc_slice_to_c_string
     grpc_slice_buffer_init
     grpc_slice_buffer_destroy
     grpc_slice_buffer_add
@@ -164,8 +178,11 @@
     grpc_slice_buffer_move_into
     grpc_slice_buffer_trim_end
     grpc_slice_buffer_move_first
+    grpc_slice_buffer_move_first_into_buffer
     grpc_slice_buffer_take_first
+    grpc_slice_buffer_undo_take_first
     gpr_malloc
+    gpr_zalloc
     gpr_free
     gpr_realloc
     gpr_malloc_aligned
diff --git a/grpc.gemspec b/grpc.gemspec
index e7844f2..8d5b7b2 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -87,6 +87,7 @@
   s.files += %w( src/core/lib/support/env.h )
   s.files += %w( src/core/lib/support/mpscq.h )
   s.files += %w( src/core/lib/support/murmur_hash.h )
+  s.files += %w( src/core/lib/support/spinlock.h )
   s.files += %w( src/core/lib/support/stack_lockfree.h )
   s.files += %w( src/core/lib/support/string.h )
   s.files += %w( src/core/lib/support/string_windows.h )
@@ -143,6 +144,7 @@
   s.files += %w( include/grpc/grpc.h )
   s.files += %w( include/grpc/grpc_posix.h )
   s.files += %w( include/grpc/grpc_security_constants.h )
+  s.files += %w( include/grpc/load_reporting.h )
   s.files += %w( include/grpc/slice.h )
   s.files += %w( include/grpc/slice_buffer.h )
   s.files += %w( include/grpc/status.h )
@@ -191,6 +193,7 @@
   s.files += %w( src/core/lib/iomgr/endpoint.h )
   s.files += %w( src/core/lib/iomgr/endpoint_pair.h )
   s.files += %w( src/core/lib/iomgr/error.h )
+  s.files += %w( src/core/lib/iomgr/error_internal.h )
   s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h )
   s.files += %w( src/core/lib/iomgr/ev_poll_posix.h )
   s.files += %w( src/core/lib/iomgr/ev_posix.h )
@@ -243,6 +246,7 @@
   s.files += %w( src/core/lib/json/json_reader.h )
   s.files += %w( src/core/lib/json/json_writer.h )
   s.files += %w( src/core/lib/slice/percent_encoding.h )
+  s.files += %w( src/core/lib/slice/slice_hash_table.h )
   s.files += %w( src/core/lib/slice/slice_internal.h )
   s.files += %w( src/core/lib/slice/slice_string_helpers.h )
   s.files += %w( src/core/lib/surface/api_trace.h )
@@ -256,14 +260,18 @@
   s.files += %w( src/core/lib/surface/init.h )
   s.files += %w( src/core/lib/surface/lame_client.h )
   s.files += %w( src/core/lib/surface/server.h )
+  s.files += %w( src/core/lib/surface/validate_metadata.h )
+  s.files += %w( src/core/lib/transport/bdp_estimator.h )
   s.files += %w( src/core/lib/transport/byte_stream.h )
   s.files += %w( src/core/lib/transport/connectivity_state.h )
-  s.files += %w( src/core/lib/transport/mdstr_hash_table.h )
+  s.files += %w( src/core/lib/transport/error_utils.h )
+  s.files += %w( src/core/lib/transport/http2_errors.h )
   s.files += %w( src/core/lib/transport/metadata.h )
   s.files += %w( src/core/lib/transport/metadata_batch.h )
   s.files += %w( src/core/lib/transport/pid_controller.h )
   s.files += %w( src/core/lib/transport/service_config.h )
   s.files += %w( src/core/lib/transport/static_metadata.h )
+  s.files += %w( src/core/lib/transport/status_conversion.h )
   s.files += %w( src/core/lib/transport/timeout_encoding.h )
   s.files += %w( src/core/lib/transport/transport.h )
   s.files += %w( src/core/lib/transport/transport_impl.h )
@@ -280,11 +288,9 @@
   s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/http2_errors.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/internal.h )
-  s.files += %w( src/core/ext/transport/chttp2/transport/status_conversion.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/varint.h )
   s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h )
@@ -301,6 +307,7 @@
   s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h )
   s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h )
   s.files += %w( src/core/lib/security/transport/auth_filters.h )
+  s.files += %w( src/core/lib/security/transport/lb_targets_info.h )
   s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
   s.files += %w( src/core/lib/security/transport/security_connector.h )
   s.files += %w( src/core/lib/security/transport/security_handshaker.h )
@@ -317,11 +324,14 @@
   s.files += %w( src/core/ext/client_channel/client_channel_factory.h )
   s.files += %w( src/core/ext/client_channel/connector.h )
   s.files += %w( src/core/ext/client_channel/http_connect_handshaker.h )
+  s.files += %w( src/core/ext/client_channel/http_proxy.h )
   s.files += %w( src/core/ext/client_channel/initial_connect_string.h )
   s.files += %w( src/core/ext/client_channel/lb_policy.h )
   s.files += %w( src/core/ext/client_channel/lb_policy_factory.h )
   s.files += %w( src/core/ext/client_channel/lb_policy_registry.h )
   s.files += %w( src/core/ext/client_channel/parse_address.h )
+  s.files += %w( src/core/ext/client_channel/proxy_mapper.h )
+  s.files += %w( src/core/ext/client_channel/proxy_mapper_registry.h )
   s.files += %w( src/core/ext/client_channel/resolver.h )
   s.files += %w( src/core/ext/client_channel/resolver_factory.h )
   s.files += %w( src/core/ext/client_channel/resolver_registry.h )
@@ -330,6 +340,7 @@
   s.files += %w( src/core/ext/client_channel/uri_parser.h )
   s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
   s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.h )
+  s.files += %w( src/core/ext/lb_policy/grpclb/grpclb_channel.h )
   s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h )
   s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
   s.files += %w( third_party/nanopb/pb.h )
@@ -349,6 +360,11 @@
   s.files += %w( src/core/ext/census/resource.h )
   s.files += %w( src/core/ext/census/rpc_metric_id.h )
   s.files += %w( src/core/ext/census/trace_context.h )
+  s.files += %w( src/core/ext/census/trace_label.h )
+  s.files += %w( src/core/ext/census/trace_propagation.h )
+  s.files += %w( src/core/ext/census/trace_status.h )
+  s.files += %w( src/core/ext/census/trace_string.h )
+  s.files += %w( src/core/ext/census/tracing.h )
   s.files += %w( src/core/lib/surface/init.c )
   s.files += %w( src/core/lib/channel/channel_args.c )
   s.files += %w( src/core/lib/channel/channel_stack.c )
@@ -434,6 +450,8 @@
   s.files += %w( src/core/lib/slice/percent_encoding.c )
   s.files += %w( src/core/lib/slice/slice.c )
   s.files += %w( src/core/lib/slice/slice_buffer.c )
+  s.files += %w( src/core/lib/slice/slice_hash_table.c )
+  s.files += %w( src/core/lib/slice/slice_intern.c )
   s.files += %w( src/core/lib/slice/slice_string_helpers.c )
   s.files += %w( src/core/lib/surface/alarm.c )
   s.files += %w( src/core/lib/surface/api_trace.c )
@@ -453,14 +471,16 @@
   s.files += %w( src/core/lib/surface/server.c )
   s.files += %w( src/core/lib/surface/validate_metadata.c )
   s.files += %w( src/core/lib/surface/version.c )
+  s.files += %w( src/core/lib/transport/bdp_estimator.c )
   s.files += %w( src/core/lib/transport/byte_stream.c )
   s.files += %w( src/core/lib/transport/connectivity_state.c )
-  s.files += %w( src/core/lib/transport/mdstr_hash_table.c )
+  s.files += %w( src/core/lib/transport/error_utils.c )
   s.files += %w( src/core/lib/transport/metadata.c )
   s.files += %w( src/core/lib/transport/metadata_batch.c )
   s.files += %w( src/core/lib/transport/pid_controller.c )
   s.files += %w( src/core/lib/transport/service_config.c )
   s.files += %w( src/core/lib/transport/static_metadata.c )
+  s.files += %w( src/core/lib/transport/status_conversion.c )
   s.files += %w( src/core/lib/transport/timeout_encoding.c )
   s.files += %w( src/core/lib/transport/transport.c )
   s.files += %w( src/core/lib/transport/transport_op_string.c )
@@ -481,7 +501,6 @@
   s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/parsing.c )
-  s.files += %w( src/core/ext/transport/chttp2/transport/status_conversion.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/stream_lists.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.c )
   s.files += %w( src/core/ext/transport/chttp2/transport/varint.c )
@@ -503,6 +522,7 @@
   s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.c )
   s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.c )
   s.files += %w( src/core/lib/security/transport/client_auth_filter.c )
+  s.files += %w( src/core/lib/security/transport/lb_targets_info.c )
   s.files += %w( src/core/lib/security/transport/secure_endpoint.c )
   s.files += %w( src/core/lib/security/transport/security_connector.c )
   s.files += %w( src/core/lib/security/transport/security_handshaker.c )
@@ -523,11 +543,14 @@
   s.files += %w( src/core/ext/client_channel/connector.c )
   s.files += %w( src/core/ext/client_channel/default_initial_connect_string.c )
   s.files += %w( src/core/ext/client_channel/http_connect_handshaker.c )
+  s.files += %w( src/core/ext/client_channel/http_proxy.c )
   s.files += %w( src/core/ext/client_channel/initial_connect_string.c )
   s.files += %w( src/core/ext/client_channel/lb_policy.c )
   s.files += %w( src/core/ext/client_channel/lb_policy_factory.c )
   s.files += %w( src/core/ext/client_channel/lb_policy_registry.c )
   s.files += %w( src/core/ext/client_channel/parse_address.c )
+  s.files += %w( src/core/ext/client_channel/proxy_mapper.c )
+  s.files += %w( src/core/ext/client_channel/proxy_mapper_registry.c )
   s.files += %w( src/core/ext/client_channel/resolver.c )
   s.files += %w( src/core/ext/client_channel/resolver_factory.c )
   s.files += %w( src/core/ext/client_channel/resolver_registry.c )
@@ -540,6 +563,7 @@
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c )
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c )
   s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.c )
+  s.files += %w( src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c )
   s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c )
   s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c )
   s.files += %w( third_party/nanopb/pb_common.c )
diff --git a/include/grpc++/ext/health_check_service_server_builder_option.h b/include/grpc++/ext/health_check_service_server_builder_option.h
new file mode 100644
index 0000000..4861daa
--- /dev/null
+++ b/include/grpc++/ext/health_check_service_server_builder_option.h
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPCXX_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H
+#define GRPCXX_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H
+
+#include <memory>
+
+#include <grpc++/health_check_service_interface.h>
+#include <grpc++/impl/server_builder_option.h>
+#include <grpc++/support/config.h>
+
+namespace grpc {
+
+class HealthCheckServiceServerBuilderOption : public ServerBuilderOption {
+ public:
+  // The ownership of hc will be taken and transferred to the grpc server.
+  // To explicitly disable default service, pass in a nullptr.
+  explicit HealthCheckServiceServerBuilderOption(
+      std::unique_ptr<HealthCheckServiceInterface> hc);
+  ~HealthCheckServiceServerBuilderOption() override {}
+  void UpdateArguments(ChannelArguments* args) override;
+  void UpdatePlugins(
+      std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override;
+
+ private:
+  std::unique_ptr<HealthCheckServiceInterface> hc_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCXX_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H
diff --git a/include/grpc++/health_check_service_interface.h b/include/grpc++/health_check_service_interface.h
new file mode 100644
index 0000000..0eed702
--- /dev/null
+++ b/include/grpc++/health_check_service_interface.h
@@ -0,0 +1,68 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPCXX_HEALTH_CHECK_SERVICE_INTERFACE_H
+#define GRPCXX_HEALTH_CHECK_SERVICE_INTERFACE_H
+
+#include <grpc++/support/config.h>
+
+namespace grpc {
+
+const char kHealthCheckServiceInterfaceArg[] =
+    "grpc.health_check_service_interface";
+
+// The gRPC server uses this interface to expose the health checking service
+// without depending on protobuf.
+class HealthCheckServiceInterface {
+ public:
+  virtual ~HealthCheckServiceInterface() {}
+
+  // Set or change the serving status of the given service_name.
+  virtual void SetServingStatus(const grpc::string& service_name,
+                                bool serving) = 0;
+  // Apply to all registered service names.
+  virtual void SetServingStatus(bool serving) = 0;
+};
+
+// Enable/disable the default health checking service. This applies to all C++
+// servers created afterwards. For each server, user can override the default
+// with a HealthCheckServiceServerBuilderOption.
+// NOT thread safe.
+void EnableDefaultHealthCheckService(bool enable);
+
+// NOT thread safe.
+bool DefaultHealthCheckServiceEnabled();
+
+}  // namespace grpc
+
+#endif  // GRPCXX_HEALTH_CHECK_SERVICE_INTERFACE_H
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 475f8d1..19a5ca2 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -45,6 +45,7 @@
 #include <grpc++/impl/codegen/config.h>
 #include <grpc++/impl/codegen/core_codegen_interface.h>
 #include <grpc++/impl/codegen/serialization_traits.h>
+#include <grpc++/impl/codegen/slice.h>
 #include <grpc++/impl/codegen/status.h>
 #include <grpc++/impl/codegen/status_helper.h>
 #include <grpc++/impl/codegen/string_ref.h>
@@ -62,19 +63,6 @@
 class CompletionQueue;
 extern CoreCodegenInterface* g_core_codegen_interface;
 
-inline void FillMetadataMap(
-    grpc_metadata_array* arr,
-    std::multimap<grpc::string_ref, grpc::string_ref>* metadata) {
-  for (size_t i = 0; i < arr->count; i++) {
-    // TODO(yangg) handle duplicates?
-    metadata->insert(std::pair<grpc::string_ref, grpc::string_ref>(
-        arr->metadata[i].key, grpc::string_ref(arr->metadata[i].value,
-                                               arr->metadata[i].value_length)));
-  }
-  g_core_codegen_interface->grpc_metadata_array_destroy(arr);
-  g_core_codegen_interface->grpc_metadata_array_init(arr);
-}
-
 // TODO(yangg) if the map is changed before we send, the pointers will be a
 // mess. Make sure it does not happen.
 inline grpc_metadata* FillMetadataArray(
@@ -87,9 +75,8 @@
           metadata.size() * sizeof(grpc_metadata)));
   size_t i = 0;
   for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
-    metadata_array[i].key = iter->first.c_str();
-    metadata_array[i].value = iter->second.c_str();
-    metadata_array[i].value_length = iter->second.size();
+    metadata_array[i].key = SliceReferencingString(iter->first);
+    metadata_array[i].value = SliceReferencingString(iter->second);
   }
   return metadata_array;
 }
@@ -175,7 +162,7 @@
 class CallNoOp {
  protected:
   void AddOp(grpc_op* ops, size_t* nops) {}
-  void FinishOp(bool* status, int max_receive_message_size) {}
+  void FinishOp(bool* status) {}
 };
 
 class CallOpSendInitialMetadata {
@@ -213,7 +200,7 @@
     op->data.send_initial_metadata.maybe_compression_level.level =
         maybe_compression_level_.level;
   }
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (!send_) return;
     g_core_codegen_interface->gpr_free(initial_metadata_);
     send_ = false;
@@ -253,7 +240,7 @@
     // Flags are per-message: clear them after use.
     write_options_.Clear();
   }
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
     send_buf_ = nullptr;
   }
@@ -301,14 +288,12 @@
     op->data.recv_message.recv_message = &recv_buf_;
   }
 
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (message_ == nullptr) return;
     if (recv_buf_) {
       if (*status) {
         got_message = *status =
-            SerializationTraits<R>::Deserialize(recv_buf_, message_,
-                                                max_receive_message_size)
-                .ok();
+            SerializationTraits<R>::Deserialize(recv_buf_, message_).ok();
       } else {
         got_message = false;
         g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@@ -331,8 +316,7 @@
 namespace CallOpGenericRecvMessageHelper {
 class DeserializeFunc {
  public:
-  virtual Status Deserialize(grpc_byte_buffer* buf,
-                             int max_receive_message_size) = 0;
+  virtual Status Deserialize(grpc_byte_buffer* buf) = 0;
   virtual ~DeserializeFunc() {}
 };
 
@@ -340,10 +324,8 @@
 class DeserializeFuncType final : public DeserializeFunc {
  public:
   DeserializeFuncType(R* message) : message_(message) {}
-  Status Deserialize(grpc_byte_buffer* buf,
-                     int max_receive_message_size) override {
-    return SerializationTraits<R>::Deserialize(buf, message_,
-                                               max_receive_message_size);
+  Status Deserialize(grpc_byte_buffer* buf) override {
+    return SerializationTraits<R>::Deserialize(buf, message_);
   }
 
   ~DeserializeFuncType() override {}
@@ -382,13 +364,12 @@
     op->data.recv_message.recv_message = &recv_buf_;
   }
 
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (!deserialize_) return;
     if (recv_buf_) {
       if (*status) {
         got_message = true;
-        *status =
-            deserialize_->Deserialize(recv_buf_, max_receive_message_size).ok();
+        *status = deserialize_->Deserialize(recv_buf_).ok();
       } else {
         got_message = false;
         g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@@ -422,7 +403,7 @@
     op->flags = 0;
     op->reserved = NULL;
   }
-  void FinishOp(bool* status, int max_receive_message_size) { send_ = false; }
+  void FinishOp(bool* status) { send_ = false; }
 
  private:
   bool send_;
@@ -451,13 +432,14 @@
         trailing_metadata_count_;
     op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
     op->data.send_status_from_server.status = send_status_code_;
+    status_details_slice_ = SliceReferencingString(send_status_details_);
     op->data.send_status_from_server.status_details =
-        send_status_details_.empty() ? nullptr : send_status_details_.c_str();
+        send_status_details_.empty() ? nullptr : &status_details_slice_;
     op->flags = 0;
     op->reserved = NULL;
   }
 
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (!send_status_available_) return;
     g_core_codegen_interface->gpr_free(trailing_metadata_);
     send_status_available_ = false;
@@ -469,37 +451,36 @@
   grpc::string send_status_details_;
   size_t trailing_metadata_count_;
   grpc_metadata* trailing_metadata_;
+  grpc_slice status_details_slice_;
 };
 
 class CallOpRecvInitialMetadata {
  public:
-  CallOpRecvInitialMetadata() : recv_initial_metadata_(nullptr) {}
+  CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
 
   void RecvInitialMetadata(ClientContext* context) {
     context->initial_metadata_received_ = true;
-    recv_initial_metadata_ = &context->recv_initial_metadata_;
+    metadata_map_ = &context->recv_initial_metadata_;
   }
 
  protected:
   void AddOp(grpc_op* ops, size_t* nops) {
-    if (!recv_initial_metadata_) return;
-    memset(&recv_initial_metadata_arr_, 0, sizeof(recv_initial_metadata_arr_));
+    if (metadata_map_ == nullptr) return;
     grpc_op* op = &ops[(*nops)++];
     op->op = GRPC_OP_RECV_INITIAL_METADATA;
-    op->data.recv_initial_metadata.recv_initial_metadata =
-        &recv_initial_metadata_arr_;
+    op->data.recv_initial_metadata.recv_initial_metadata = metadata_map_->arr();
     op->flags = 0;
     op->reserved = NULL;
   }
-  void FinishOp(bool* status, int max_receive_message_size) {
-    if (recv_initial_metadata_ == nullptr) return;
-    FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
-    recv_initial_metadata_ = nullptr;
+
+  void FinishOp(bool* status) {
+    if (metadata_map_ == nullptr) return;
+    metadata_map_->FillMap();
+    metadata_map_ = nullptr;
   }
 
  private:
-  std::multimap<grpc::string_ref, grpc::string_ref>* recv_initial_metadata_;
-  grpc_metadata_array recv_initial_metadata_arr_;
+  MetadataMap* metadata_map_;
 };
 
 class CallOpClientRecvStatus {
@@ -507,46 +488,37 @@
   CallOpClientRecvStatus() : recv_status_(nullptr) {}
 
   void ClientRecvStatus(ClientContext* context, Status* status) {
-    recv_trailing_metadata_ = &context->trailing_metadata_;
+    metadata_map_ = &context->trailing_metadata_;
     recv_status_ = status;
   }
 
  protected:
   void AddOp(grpc_op* ops, size_t* nops) {
     if (recv_status_ == nullptr) return;
-    memset(&recv_trailing_metadata_arr_, 0,
-           sizeof(recv_trailing_metadata_arr_));
-    status_details_ = nullptr;
-    status_details_capacity_ = 0;
     grpc_op* op = &ops[(*nops)++];
     op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
-    op->data.recv_status_on_client.trailing_metadata =
-        &recv_trailing_metadata_arr_;
+    op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr();
     op->data.recv_status_on_client.status = &status_code_;
     op->data.recv_status_on_client.status_details = &status_details_;
-    op->data.recv_status_on_client.status_details_capacity =
-        &status_details_capacity_;
     op->flags = 0;
     op->reserved = NULL;
   }
 
-  void FinishOp(bool* status, int max_receive_message_size) {
+  void FinishOp(bool* status) {
     if (recv_status_ == nullptr) return;
-    FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_);
-    *recv_status_ = Status(
-        static_cast<StatusCode>(status_code_),
-        status_details_ ? grpc::string(status_details_) : grpc::string());
-    g_core_codegen_interface->gpr_free(status_details_);
+    metadata_map_->FillMap();
+    *recv_status_ = Status(static_cast<StatusCode>(status_code_),
+                           grpc::string(GRPC_SLICE_START_PTR(status_details_),
+                                        GRPC_SLICE_END_PTR(status_details_)));
+    g_core_codegen_interface->grpc_slice_unref(status_details_);
     recv_status_ = nullptr;
   }
 
  private:
-  std::multimap<grpc::string_ref, grpc::string_ref>* recv_trailing_metadata_;
+  MetadataMap* metadata_map_;
   Status* recv_status_;
-  grpc_metadata_array recv_trailing_metadata_arr_;
   grpc_status_code status_code_;
-  char* status_details_;
-  size_t status_details_capacity_;
+  grpc_slice status_details_;
 };
 
 /// An abstract collection of CallOpSet's, to be used whenever
@@ -567,22 +539,17 @@
 /// API.
 class CallOpSetInterface : public CompletionQueueTag {
  public:
-  CallOpSetInterface() : max_receive_message_size_(0) {}
+  CallOpSetInterface() {}
   /// Fills in grpc_op, starting from ops[*nops] and moving
   /// upwards.
   virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
 
-  void set_max_receive_message_size(int max_receive_message_size) {
-    max_receive_message_size_ = max_receive_message_size;
-  }
-
   /// Mark this as belonging to a collection if needed
   void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) {
     collection_ = collection;
   }
 
  protected:
-  int max_receive_message_size_;
   std::shared_ptr<CallOpSetCollectionInterface> collection_;
 };
 
@@ -614,12 +581,12 @@
   }
 
   bool FinalizeResult(void** tag, bool* status) override {
-    this->Op1::FinishOp(status, max_receive_message_size_);
-    this->Op2::FinishOp(status, max_receive_message_size_);
-    this->Op3::FinishOp(status, max_receive_message_size_);
-    this->Op4::FinishOp(status, max_receive_message_size_);
-    this->Op5::FinishOp(status, max_receive_message_size_);
-    this->Op6::FinishOp(status, max_receive_message_size_);
+    this->Op1::FinishOp(status);
+    this->Op2::FinishOp(status);
+    this->Op3::FinishOp(status);
+    this->Op4::FinishOp(status);
+    this->Op5::FinishOp(status);
+    this->Op6::FinishOp(status);
     *tag = return_tag_;
     collection_.reset();  // drop the ref at this point
     return true;
@@ -664,16 +631,13 @@
         max_receive_message_size_(max_receive_message_size) {}
 
   void PerformOps(CallOpSetInterface* ops) {
-    if (max_receive_message_size_ > 0) {
-      ops->set_max_receive_message_size(max_receive_message_size_);
-    }
     call_hook_->PerformOpsOnCall(ops, this);
   }
 
   grpc_call* call() const { return call_; }
   CompletionQueue* cq() const { return cq_; }
 
-  int max_receive_message_size() { return max_receive_message_size_; }
+  int max_receive_message_size() const { return max_receive_message_size_; }
 
  private:
   CallHook* call_hook_;
diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h
index 777b2f8..b91c7f6 100644
--- a/include/grpc++/impl/codegen/client_context.h
+++ b/include/grpc++/impl/codegen/client_context.h
@@ -57,7 +57,9 @@
 #include <grpc++/impl/codegen/config.h>
 #include <grpc++/impl/codegen/core_codegen_interface.h>
 #include <grpc++/impl/codegen/create_auth_context.h>
+#include <grpc++/impl/codegen/metadata_map.h>
 #include <grpc++/impl/codegen/security/auth_context.h>
+#include <grpc++/impl/codegen/slice.h>
 #include <grpc++/impl/codegen/status.h>
 #include <grpc++/impl/codegen/string_ref.h>
 #include <grpc++/impl/codegen/time.h>
@@ -193,7 +195,7 @@
   const std::multimap<grpc::string_ref, grpc::string_ref>&
   GetServerInitialMetadata() const {
     GPR_CODEGEN_ASSERT(initial_metadata_received_);
-    return recv_initial_metadata_;
+    return *recv_initial_metadata_.map();
   }
 
   /// Return a collection of trailing metadata key-value pairs. Note that keys
@@ -205,7 +207,7 @@
   const std::multimap<grpc::string_ref, grpc::string_ref>&
   GetServerTrailingMetadata() const {
     // TODO(yangg) check finished
-    return trailing_metadata_;
+    return *trailing_metadata_.map();
   }
 
   /// Set the deadline for the client call.
@@ -375,8 +377,8 @@
   mutable std::shared_ptr<const AuthContext> auth_context_;
   struct census_context* census_context_;
   std::multimap<grpc::string, grpc::string> send_initial_metadata_;
-  std::multimap<grpc::string_ref, grpc::string_ref> recv_initial_metadata_;
-  std::multimap<grpc::string_ref, grpc::string_ref> trailing_metadata_;
+  MetadataMap recv_initial_metadata_;
+  MetadataMap trailing_metadata_;
 
   grpc_call* propagate_from_call_;
   PropagationOptions propagation_options_;
diff --git a/include/grpc++/impl/codegen/client_unary_call.h b/include/grpc++/impl/codegen/client_unary_call.h
index 70d6554..201e52a 100644
--- a/include/grpc++/impl/codegen/client_unary_call.h
+++ b/include/grpc++/impl/codegen/client_unary_call.h
@@ -69,7 +69,14 @@
   ops.ClientSendClose();
   ops.ClientRecvStatus(context, &status);
   call.PerformOps(&ops);
-  GPR_CODEGEN_ASSERT((cq.Pluck(&ops) && ops.got_message) || !status.ok());
+  if (cq.Pluck(&ops)) {
+    if (!ops.got_message && status.ok()) {
+      return Status(StatusCode::UNIMPLEMENTED,
+                    "No message returned for unary request");
+    }
+  } else {
+    GPR_CODEGEN_ASSERT(!status.ok());
+  }
   return status;
 }
 
diff --git a/include/grpc++/impl/codegen/core_codegen.h b/include/grpc++/impl/codegen/core_codegen.h
index 6b5e637..754bf14 100644
--- a/include/grpc++/impl/codegen/core_codegen.h
+++ b/include/grpc++/impl/codegen/core_codegen.h
@@ -81,7 +81,10 @@
   grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) override;
   void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) override;
   void grpc_slice_buffer_pop(grpc_slice_buffer* sb) override;
-
+  grpc_slice grpc_slice_from_static_buffer(const void* buffer,
+                                           size_t length) override;
+  grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
+                                           size_t length) override;
   void grpc_metadata_array_init(grpc_metadata_array* array) override;
   void grpc_metadata_array_destroy(grpc_metadata_array* array) override;
 
@@ -91,7 +94,8 @@
   virtual const Status& ok() override;
   virtual const Status& cancelled() override;
 
-  void assert_fail(const char* failed_assertion) override;
+  void assert_fail(const char* failed_assertion, const char* file,
+                   int line) override;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h
index 4783a43..45ea040 100644
--- a/include/grpc++/impl/codegen/core_codegen_interface.h
+++ b/include/grpc++/impl/codegen/core_codegen_interface.h
@@ -56,7 +56,8 @@
 class CoreCodegenInterface {
  public:
   /// Upon a failed assertion, log the error.
-  virtual void assert_fail(const char* failed_assertion) = 0;
+  virtual void assert_fail(const char* failed_assertion, const char* file,
+                           int line) = 0;
 
   virtual grpc_completion_queue* grpc_completion_queue_create(
       void* reserved) = 0;
@@ -99,6 +100,10 @@
   virtual void grpc_slice_buffer_add(grpc_slice_buffer* sb,
                                      grpc_slice slice) = 0;
   virtual void grpc_slice_buffer_pop(grpc_slice_buffer* sb) = 0;
+  virtual grpc_slice grpc_slice_from_static_buffer(const void* buffer,
+                                                   size_t length) = 0;
+  virtual grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
+                                                   size_t length) = 0;
 
   virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0;
   virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0;
@@ -113,11 +118,11 @@
 extern CoreCodegenInterface* g_core_codegen_interface;
 
 /// Codegen specific version of \a GPR_ASSERT.
-#define GPR_CODEGEN_ASSERT(x)                          \
-  do {                                                 \
-    if (!(x)) {                                        \
-      grpc::g_core_codegen_interface->assert_fail(#x); \
-    }                                                  \
+#define GPR_CODEGEN_ASSERT(x)                                              \
+  do {                                                                     \
+    if (!(x)) {                                                            \
+      grpc::g_core_codegen_interface->assert_fail(#x, __FILE__, __LINE__); \
+    }                                                                      \
   } while (0)
 
 }  // namespace grpc
diff --git a/include/grpc++/impl/codegen/metadata_map.h b/include/grpc++/impl/codegen/metadata_map.h
new file mode 100644
index 0000000..53b9d62
--- /dev/null
+++ b/include/grpc++/impl/codegen/metadata_map.h
@@ -0,0 +1,71 @@
+/*
+*
+* Copyright 2015, Google Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*
+*     * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following disclaimer
+* in the documentation and/or other materials provided with the
+* distribution.
+*     * Neither the name of Google Inc. nor the names of its
+* contributors may be used to endorse or promote products derived from
+* this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+#ifndef GRPCXX_IMPL_CODEGEN_METADATA_MAP_H
+#define GRPCXX_IMPL_CODEGEN_METADATA_MAP_H
+
+#include <grpc++/impl/codegen/slice.h>
+
+namespace grpc {
+
+class MetadataMap {
+ public:
+  MetadataMap() { memset(&arr_, 0, sizeof(arr_)); }
+
+  ~MetadataMap() {
+    g_core_codegen_interface->grpc_metadata_array_destroy(&arr_);
+  }
+
+  void FillMap() {
+    for (size_t i = 0; i < arr_.count; i++) {
+      // TODO(yangg) handle duplicates?
+      map_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
+          StringRefFromSlice(&arr_.metadata[i].key),
+          StringRefFromSlice(&arr_.metadata[i].value)));
+    }
+  }
+
+  std::multimap<grpc::string_ref, grpc::string_ref> *map() { return &map_; }
+  const std::multimap<grpc::string_ref, grpc::string_ref> *map() const {
+    return &map_;
+  }
+  grpc_metadata_array *arr() { return &arr_; }
+
+ private:
+  grpc_metadata_array arr_;
+  std::multimap<grpc::string_ref, grpc::string_ref> map_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCXX_IMPL_CODEGEN_METADATA_MAP_H
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h
index d5d27e1..83b569c 100644
--- a/include/grpc++/impl/codegen/method_handler_impl.h
+++ b/include/grpc++/impl/codegen/method_handler_impl.h
@@ -52,8 +52,8 @@
 
   void RunHandler(const HandlerParameter& param) final {
     RequestType req;
-    Status status = SerializationTraits<RequestType>::Deserialize(
-        param.request, &req, param.max_receive_message_size);
+    Status status =
+        SerializationTraits<RequestType>::Deserialize(param.request, &req);
     ResponseType rsp;
     if (status.ok()) {
       status = func_(service_, param.server_context, &req, &rsp);
@@ -138,8 +138,8 @@
 
   void RunHandler(const HandlerParameter& param) final {
     RequestType req;
-    Status status = SerializationTraits<RequestType>::Deserialize(
-        param.request, &req, param.max_receive_message_size);
+    Status status =
+        SerializationTraits<RequestType>::Deserialize(param.request, &req);
 
     if (status.ok()) {
       ServerWriter<ResponseType> writer(param.call, param.server_context);
diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h
index 2f15487..6df9de4 100644
--- a/include/grpc++/impl/codegen/proto_utils.h
+++ b/include/grpc++/impl/codegen/proto_utils.h
@@ -50,6 +50,8 @@
 
 namespace internal {
 
+class GrpcBufferWriterPeer;
+
 const int kGrpcBufferWriterMaxBufferLength = 8192;
 
 class GrpcBufferWriter final
@@ -91,13 +93,18 @@
           &slice_, GRPC_SLICE_LENGTH(slice_) - count);
       g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
     }
-    have_backup_ = true;
+    // It's dangerous to keep an inlined grpc_slice as the backup slice, since
+    // on a following Next() call, a reference will be returned to this slice
+    // via GRPC_SLICE_START_PTR, which will not be an adddress held by
+    // slice_buffer_.
+    have_backup_ = backup_slice_.refcount != NULL;
     byte_count_ -= count;
   }
 
   grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
 
  private:
+  friend class GrpcBufferWriterPeer;
   const int block_size_;
   int64_t byte_count_;
   grpc_slice_buffer* slice_buffer_;
@@ -203,8 +210,7 @@
   }
 
   static Status Deserialize(grpc_byte_buffer* buffer,
-                            grpc::protobuf::Message* msg,
-                            int max_receive_message_size) {
+                            grpc::protobuf::Message* msg) {
     if (buffer == nullptr) {
       return Status(StatusCode::INTERNAL, "No payload");
     }
@@ -215,10 +221,7 @@
         return reader.status();
       }
       ::grpc::protobuf::io::CodedInputStream decoder(&reader);
-      if (max_receive_message_size > 0) {
-        decoder.SetTotalBytesLimit(max_receive_message_size,
-                                   max_receive_message_size);
-      }
+      decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
       if (!msg->ParseFromCodedStream(&decoder)) {
         result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
       }
diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h
index 78c54e3..eb8f9a1 100644
--- a/include/grpc++/impl/codegen/rpc_service_method.h
+++ b/include/grpc++/impl/codegen/rpc_service_method.h
@@ -57,17 +57,12 @@
  public:
   virtual ~MethodHandler() {}
   struct HandlerParameter {
-    HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req,
-                     int max_size)
-        : call(c),
-          server_context(context),
-          request(req),
-          max_receive_message_size(max_size) {}
+    HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req)
+        : call(c), server_context(context), request(req) {}
     Call* call;
     ServerContext* server_context;
     // Handler required to grpc_byte_buffer_destroy this
     grpc_byte_buffer* request;
-    int max_receive_message_size;
   };
   virtual void RunHandler(const HandlerParameter& param) = 0;
 };
diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h
index dd30576..bf9a9b6 100644
--- a/include/grpc++/impl/codegen/server_context.h
+++ b/include/grpc++/impl/codegen/server_context.h
@@ -36,20 +36,23 @@
 
 #include <map>
 #include <memory>
+#include <vector>
+
+#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/load_reporting.h>
 
 #include <grpc++/impl/codegen/config.h>
 #include <grpc++/impl/codegen/create_auth_context.h>
+#include <grpc++/impl/codegen/metadata_map.h>
 #include <grpc++/impl/codegen/security/auth_context.h>
 #include <grpc++/impl/codegen/string_ref.h>
 #include <grpc++/impl/codegen/time.h>
-#include <grpc/impl/codegen/compression_types.h>
 
 struct grpc_metadata;
 struct grpc_call;
 struct census_context;
 
 namespace grpc {
-
 class ClientContext;
 template <class W, class R>
 class ServerAsyncReader;
@@ -123,7 +126,7 @@
 
   const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
       const {
-    return client_metadata_;
+    return *client_metadata_.map();
   }
 
   grpc_compression_level compression_level() const {
@@ -142,6 +145,9 @@
   }
   void set_compression_algorithm(grpc_compression_algorithm algorithm);
 
+  // Set the load reporting costs in \a cost_data for the call.
+  void SetLoadReportingCosts(const std::vector<grpc::string>& cost_data);
+
   std::shared_ptr<const AuthContext> auth_context() const {
     if (auth_context_.get() == nullptr) {
       auth_context_ = CreateAuthContext(call_);
@@ -207,8 +213,7 @@
 
   void BeginCompletionOp(Call* call);
 
-  ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
-                size_t metadata_count);
+  ServerContext(gpr_timespec deadline, grpc_metadata_array* arr);
 
   void set_call(grpc_call* call) { call_ = call; }
 
@@ -223,7 +228,7 @@
   CompletionQueue* cq_;
   bool sent_initial_metadata_;
   mutable std::shared_ptr<const AuthContext> auth_context_;
-  std::multimap<grpc::string_ref, grpc::string_ref> client_metadata_;
+  MetadataMap client_metadata_;
   std::multimap<grpc::string, grpc::string> initial_metadata_;
   std::multimap<grpc::string, grpc::string> trailing_metadata_;
 
diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h
index 666b9ff..bd1b36e 100644
--- a/include/grpc++/impl/codegen/server_interface.h
+++ b/include/grpc++/impl/codegen/server_interface.h
@@ -152,7 +152,6 @@
     void* const tag_;
     const bool delete_on_finalize_;
     grpc_call* call_;
-    grpc_metadata_array initial_metadata_array_;
   };
 
   class RegisteredAsyncRequest : public BaseAsyncRequest {
@@ -199,9 +198,7 @@
     bool FinalizeResult(void** tag, bool* status) override {
       bool serialization_status =
           *status && payload_ &&
-          SerializationTraits<Message>::Deserialize(
-              payload_, request_, server_->max_receive_message_size())
-              .ok();
+          SerializationTraits<Message>::Deserialize(payload_, request_).ok();
       bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
       *status = serialization_status && *status;
       return ret;
diff --git a/include/grpc++/impl/codegen/slice.h b/include/grpc++/impl/codegen/slice.h
new file mode 100644
index 0000000..04b2f9a
--- /dev/null
+++ b/include/grpc++/impl/codegen/slice.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPCXX_IMPL_CODEGEN_SLICE_H
+#define GRPCXX_IMPL_CODEGEN_SLICE_H
+
+#include <grpc++/impl/codegen/core_codegen_interface.h>
+#include <grpc++/impl/codegen/string_ref.h>
+
+namespace grpc {
+
+inline grpc::string_ref StringRefFromSlice(const grpc_slice* slice) {
+  return grpc::string_ref(
+      reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(*slice)),
+      GRPC_SLICE_LENGTH(*slice));
+}
+
+inline grpc::string StringFromCopiedSlice(grpc_slice slice) {
+  return grpc::string(reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
+                      GRPC_SLICE_LENGTH(slice));
+}
+
+inline grpc_slice SliceReferencingString(const grpc::string& str) {
+  return g_core_codegen_interface->grpc_slice_from_static_buffer(str.data(),
+                                                                 str.length());
+}
+
+inline grpc_slice SliceFromCopiedString(const grpc::string& str) {
+  return g_core_codegen_interface->grpc_slice_from_copied_buffer(str.data(),
+                                                                 str.length());
+}
+
+}  // namespace grpc
+
+#endif  // GRPCXX_IMPL_CODEGEN_SLICE_H
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index fba9952..3e54405 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -55,12 +55,10 @@
 
 namespace grpc {
 
-class GenericServerContext;
 class AsyncGenericService;
-class ServerAsyncStreamingInterface;
+class HealthCheckServiceInterface;
 class ServerContext;
 class ServerInitializer;
-class ThreadPoolInterface;
 
 /// Models a gRPC server.
 ///
@@ -88,6 +86,8 @@
     virtual void PreSynchronousRequest(ServerContext* context) = 0;
     /// Called after application callback for each synchronous server request
     virtual void PostSynchronousRequest(ServerContext* context) = 0;
+    /// Called before server is started.
+    virtual void PreServerStart(Server* server) {}
   };
   /// Set the global callback object. Can only be called once. Does not take
   /// ownership of callbacks, and expects the pointed to object to be alive
@@ -97,6 +97,11 @@
   // Returns a \em raw pointer to the underlying grpc_server instance.
   grpc_server* c_server();
 
+  /// Returns the health check service.
+  HealthCheckServiceInterface* GetHealthCheckService() const {
+    return health_check_service_.get();
+  }
+
  private:
   friend class AsyncGenericService;
   friend class ServerBuilder;
@@ -214,6 +219,9 @@
   grpc_server* server_;
 
   std::unique_ptr<ServerInitializer> server_initializer_;
+
+  std::unique_ptr<HealthCheckServiceInterface> health_check_service_;
+  bool health_check_service_disabled_;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/support/byte_buffer.h b/include/grpc++/support/byte_buffer.h
index 1f317df..064a03b 100644
--- a/include/grpc++/support/byte_buffer.h
+++ b/include/grpc++/support/byte_buffer.h
@@ -95,8 +95,7 @@
 template <>
 class SerializationTraits<ByteBuffer, void> {
  public:
-  static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest,
-                            int max_receive_message_size) {
+  static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest) {
     dest->set_buffer(byte_buffer);
     return Status::OK;
   }
diff --git a/include/grpc++/test/server_context_test_spouse.h b/include/grpc++/test/server_context_test_spouse.h
index b248285..bac0db7 100644
--- a/include/grpc++/test/server_context_test_spouse.h
+++ b/include/grpc++/test/server_context_test_spouse.h
@@ -48,10 +48,23 @@
 
   // Inject client metadata to the ServerContext for the test. The test spouse
   // must be alive when ServerContext::client_metadata is called.
-  void AddClientMetadata(const grpc::string& key, const grpc::string& value);
+  void AddClientMetadata(const grpc::string& key, const grpc::string& value) {
+    client_metadata_storage_.insert(
+        std::pair<grpc::string, grpc::string>(key, value));
+    ctx_->client_metadata_.map()->clear();
+    for (auto iter = client_metadata_storage_.begin();
+         iter != client_metadata_storage_.end(); ++iter) {
+      ctx_->client_metadata_.map()->insert(
+          std::pair<grpc::string_ref, grpc::string_ref>(
+              iter->first.c_str(),
+              grpc::string_ref(iter->second.data(), iter->second.size())));
+    }
+  }
+
   std::multimap<grpc::string, grpc::string> GetInitialMetadata() const {
     return ctx_->initial_metadata_;
   }
+
   std::multimap<grpc::string, grpc::string> GetTrailingMetadata() const {
     return ctx_->trailing_metadata_;
   }
diff --git a/include/grpc/census.h b/include/grpc/census.h
index 62ff45d..822c42c 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -156,7 +156,7 @@
 CENSUSAPI const census_context_status *census_context_get_status(
     const census_context *context);
 
-/* Structure used for iterating over the tegs in a context. API clients should
+/* Structure used for iterating over the tags in a context. API clients should
    not use or reference internal fields - neither their contents or
    presence/absence are guaranteed. */
 typedef struct {
@@ -180,7 +180,7 @@
 CENSUSAPI int census_context_get_tag(const census_context *context,
                                      const char *key, census_tag *tag);
 
-/* Tag set encode/decode functionality. These functionas are intended
+/* Tag set encode/decode functionality. These functions are intended
    for use by RPC systems only, for purposes of transmitting/receiving contexts.
    */
 
@@ -205,14 +205,14 @@
 };
 
 /** Get the current trace mask associated with this context. The value returned
-    will be the logical or of census_trace_mask_values values. */
+    will be the logical OR of census_trace_mask_values values. */
 CENSUSAPI int census_trace_mask(const census_context *context);
 
 /** Set the trace mask associated with a context. */
 CENSUSAPI void census_set_trace_mask(int trace_mask);
 
 /* The concept of "operation" is a fundamental concept for Census. In an RPC
-   system, and operation typcially represents a single RPC, or a significant
+   system, an operation typically represents a single RPC, or a significant
    sub-part thereof (e.g. a single logical "read" RPC to a distributed storage
    system might do several other actions in parallel, from looking up metadata
    indices to making requests of other services - each of these could be a
@@ -362,7 +362,7 @@
 
    @param context The base context. Can be NULL.
    @param family Family name to associate with the trace
-   @param name Name within family to associated with traces/stats
+   @param name Name within family to associate with traces/stats
    @param trace_mask An OR of census_trace_mask_values values. Only used if
                      context is NULL.
 
@@ -454,7 +454,7 @@
    protobuf, `resource_pb_size` being the size of the buffer. Returns a -ve
    value on error, or a positive (>= 0) resource id (for use in
    census_delete_resource() and census_record_values()). In order to be valid, a
-   resource must have a name, and at least one numerator in it's unit type. The
+   resource must have a name, and at least one numerator in its unit type. The
    resource name must be unique, and an error will be returned if it is not. */
 CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb,
                                          size_t resource_pb_size);
@@ -462,7 +462,7 @@
 /* Delete a resource created by census_define_resource(). */
 CENSUSAPI void census_delete_resource(int32_t resource_id);
 
-/* Determine the id of a resource, given it's name. returns -1 if the resource
+/* Determine the id of a resource, given its name. returns -1 if the resource
    does not exist. */
 CENSUSAPI int32_t census_resource_id(const char *name);
 
diff --git a/include/grpc/compression.h b/include/grpc/compression.h
index 5f285cd..659d6fe 100644
--- a/include/grpc/compression.h
+++ b/include/grpc/compression.h
@@ -34,11 +34,12 @@
 #ifndef GRPC_COMPRESSION_H
 #define GRPC_COMPRESSION_H
 
-#include <stdlib.h>
-
 #include <grpc/impl/codegen/port_platform.h>
 
+#include <stdlib.h>
+
 #include <grpc/impl/codegen/compression_types.h>
+#include <grpc/slice.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -48,8 +49,7 @@
  * grpc_compression_algorithm instance, updating \a algorithm. Returns 1 upon
  * success, 0 otherwise. */
 GRPCAPI int grpc_compression_algorithm_parse(
-    const char *name, size_t name_length,
-    grpc_compression_algorithm *algorithm);
+    grpc_slice value, grpc_compression_algorithm *algorithm);
 
 /** Updates \a name with the encoding name corresponding to a valid \a
  * algorithm. Note that \a name is statically allocated and must *not* be freed.
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 898f4d5..1b33d48 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -178,8 +178,8 @@
     possible values). */
 GRPCAPI grpc_call *grpc_channel_create_call(
     grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
-    grpc_completion_queue *completion_queue, const char *method,
-    const char *host, gpr_timespec deadline, void *reserved);
+    grpc_completion_queue *completion_queue, grpc_slice method,
+    const grpc_slice *host, gpr_timespec deadline, void *reserved);
 
 /** Ping the channels peer (load balanced channels will select one sub-channel
     to ping); if the channel is not connected, posts a failed. */
@@ -229,14 +229,20 @@
     functionality. Instead, use grpc_auth_context. */
 GRPCAPI char *grpc_call_get_peer(grpc_call *call);
 
+struct grpc_load_reporting_cost_context;
+
+/* Associate costs contained in \a cost_context to \a call. */
+GRPCAPI void grpc_call_set_load_reporting_cost_context(
+    grpc_call *call, struct grpc_load_reporting_cost_context *context);
+
 struct census_context;
 
-/* Set census context for a call; Must be called before first call to
+/** Set census context for a call; Must be called before first call to
    grpc_call_start_batch(). */
 GRPCAPI void grpc_census_call_set_context(grpc_call *call,
                                           struct census_context *context);
 
-/* Retrieve the calls current census context. */
+/** Retrieve the calls current census context. */
 GRPCAPI struct census_context *grpc_census_call_get_context(grpc_call *call);
 
 /** Return a newly allocated string representing the target a channel was
@@ -402,14 +408,14 @@
 GRPCAPI int grpc_tracer_set_enabled(const char *name, int enabled);
 
 /** Check whether a metadata key is legal (will be accepted by core) */
-GRPCAPI int grpc_header_key_is_legal(const char *key, size_t length);
+GRPCAPI int grpc_header_key_is_legal(grpc_slice slice);
 
 /** Check whether a non-binary metadata value is legal (will be accepted by
     core) */
-GRPCAPI int grpc_header_nonbin_value_is_legal(const char *value, size_t length);
+GRPCAPI int grpc_header_nonbin_value_is_legal(grpc_slice slice);
 
 /** Check whether a metadata key corresponds to a binary value */
-GRPCAPI int grpc_is_binary_header(const char *key, size_t length);
+GRPCAPI int grpc_is_binary_header(grpc_slice slice);
 
 /** Convert grpc_call_error values to a string */
 GRPCAPI const char *grpc_call_error_to_string(grpc_call_error error);
diff --git a/include/grpc/impl/codegen/atm_gcc_atomic.h b/include/grpc/impl/codegen/atm_gcc_atomic.h
index 7d4ae98..4bd3b25 100644
--- a/include/grpc/impl/codegen/atm_gcc_atomic.h
+++ b/include/grpc/impl/codegen/atm_gcc_atomic.h
@@ -40,6 +40,20 @@
 
 typedef intptr_t gpr_atm;
 
+#ifdef GPR_LOW_LEVEL_COUNTERS
+extern gpr_atm gpr_counter_atm_cas;
+extern gpr_atm gpr_counter_atm_add;
+#define GPR_ATM_INC_COUNTER(counter) \
+  __atomic_fetch_add(&counter, 1, __ATOMIC_RELAXED)
+#define GPR_ATM_INC_CAS_THEN(blah) \
+  (GPR_ATM_INC_COUNTER(gpr_counter_atm_cas), blah)
+#define GPR_ATM_INC_ADD_THEN(blah) \
+  (GPR_ATM_INC_COUNTER(gpr_counter_atm_add), blah)
+#else
+#define GPR_ATM_INC_CAS_THEN(blah) blah
+#define GPR_ATM_INC_ADD_THEN(blah) blah
+#endif
+
 #define gpr_atm_full_barrier() (__atomic_thread_fence(__ATOMIC_SEQ_CST))
 
 #define gpr_atm_acq_load(p) (__atomic_load_n((p), __ATOMIC_ACQUIRE))
@@ -50,25 +64,28 @@
   (__atomic_store_n((p), (intptr_t)(value), __ATOMIC_RELAXED))
 
 #define gpr_atm_no_barrier_fetch_add(p, delta) \
-  (__atomic_fetch_add((p), (intptr_t)(delta), __ATOMIC_RELAXED))
+  GPR_ATM_INC_ADD_THEN(                        \
+      __atomic_fetch_add((p), (intptr_t)(delta), __ATOMIC_RELAXED))
 #define gpr_atm_full_fetch_add(p, delta) \
-  (__atomic_fetch_add((p), (intptr_t)(delta), __ATOMIC_ACQ_REL))
+  GPR_ATM_INC_ADD_THEN(                  \
+      __atomic_fetch_add((p), (intptr_t)(delta), __ATOMIC_ACQ_REL))
 
 static __inline int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
-  return __atomic_compare_exchange_n(p, &o, n, 0, __ATOMIC_RELAXED,
-                                     __ATOMIC_RELAXED);
+  return GPR_ATM_INC_CAS_THEN(__atomic_compare_exchange_n(
+      p, &o, n, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED));
 }
 
 static __inline int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
-  return __atomic_compare_exchange_n(p, &o, n, 0, __ATOMIC_ACQUIRE,
-                                     __ATOMIC_RELAXED);
+  return GPR_ATM_INC_CAS_THEN(__atomic_compare_exchange_n(
+      p, &o, n, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED));
 }
 
 static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
-  return __atomic_compare_exchange_n(p, &o, n, 0, __ATOMIC_RELEASE,
-                                     __ATOMIC_RELAXED);
+  return GPR_ATM_INC_CAS_THEN(__atomic_compare_exchange_n(
+      p, &o, n, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED));
 }
 
-#define gpr_atm_full_xchg(p, n) __atomic_exchange_n((p), (n), __ATOMIC_ACQ_REL)
+#define gpr_atm_full_xchg(p, n) \
+  GPR_ATM_INC_CAS_THEN(__atomic_exchange_n((p), (n), __ATOMIC_ACQ_REL))
 
 #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_ATOMIC_H */
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 8d20f70..e5c7313 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -179,9 +179,30 @@
     Larger values give lower CPU usage for large messages, but more head of line
     blocking for small messages. */
 #define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size"
+/** Should BDP probing be performed? */
+#define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe"
+/** Minimum time (in milliseconds) between successive ping frames being sent */
+#define GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS \
+  "grpc.http2.min_time_between_pings_ms"
+/** How many pings can we send before needing to send a data frame or header
+    frame?
+    (0 indicates that an infinite number of pings can be sent without sending
+     a data frame or header frame) */
+#define GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA \
+  "grpc.http2.max_pings_without_data"
 /** How much data are we willing to queue up per stream if
     GRPC_WRITE_BUFFER_HINT is set? This is an upper bound */
 #define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size"
+/** After a duration of this time the client pings the server to see if the
+    transport is still alive. Int valued, seconds. */
+#define GRPC_ARG_HTTP2_KEEPALIVE_TIME "grpc.http2.keepalive_time"
+/** After waiting for a duration of this time, if the client does not receive
+    the ping ack, it will close the transport. Int valued, seconds. */
+#define GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT "grpc.http2.keepalive_timeout"
+/** Is it permissible to send keepalive pings without any outstanding streams.
+    Int valued, 0(false)/1(true). */
+#define GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS \
+  "grpc.http2.keepalive_permit_without_calls"
 /** Default authority to pass if none specified on call construction. A string.
  * */
 #define GRPC_ARG_DEFAULT_AUTHORITY "grpc.default_authority"
@@ -211,12 +232,18 @@
 /** If non-zero, a pointer to a buffer pool (use grpc_resource_quota_arg_vtable
    to fetch an appropriate pointer arg vtable) */
 #define GRPC_ARG_RESOURCE_QUOTA "grpc.resource_quota"
+/** If non-zero, expand wildcard addresses to a list of local addresses. */
+#define GRPC_ARG_EXPAND_WILDCARD_ADDRS "grpc.expand_wildcard_addrs"
 /** Service config data in JSON form. Not intended for use outside of tests. */
 #define GRPC_ARG_SERVICE_CONFIG "grpc.service_config"
 /** LB policy name. */
 #define GRPC_ARG_LB_POLICY_NAME "grpc.lb_policy_name"
 /** The grpc_socket_mutator instance that set the socket options. A pointer. */
 #define GRPC_ARG_SOCKET_MUTATOR "grpc.socket_mutator"
+/** If non-zero, Cronet transport will coalesce packets to fewer frames when
+ * possible. */
+#define GRPC_ARG_USE_CRONET_PACKET_COALESCING \
+  "grpc.use_cronet_packet_coalescing"
 /** \} */
 
 /** Result of a grpc call. If the caller satisfies the prerequisites of a
@@ -294,9 +321,11 @@
 
 /** A single metadata element */
 typedef struct grpc_metadata {
-  const char *key;
-  const char *value;
-  size_t value_length;
+  /* the key, value values are expected to line up with grpc_mdelem: if changing
+     them, update metadata.h at the same time. */
+  grpc_slice key;
+  grpc_slice value;
+
   uint32_t flags;
 
   /** The following fields are reserved for grpc internal use.
@@ -338,10 +367,8 @@
 } grpc_metadata_array;
 
 typedef struct {
-  char *method;
-  size_t method_capacity;
-  char *host;
-  size_t host_capacity;
+  grpc_slice method;
+  grpc_slice host;
   gpr_timespec deadline;
   uint32_t flags;
   void *reserved;
@@ -425,7 +452,10 @@
       size_t trailing_metadata_count;
       grpc_metadata *trailing_metadata;
       grpc_status_code status;
-      const char *status_details;
+      /* optional: set to NULL if no details need sending, non-NULL if they do
+       * pointer will not be retained past the start_batch call
+       */
+      grpc_slice *status_details;
     } send_status_from_server;
     /** ownership of the array is with the caller, but ownership of the elements
         stays with the call object (ie key, value members are owned by the call
@@ -450,28 +480,7 @@
           value, or reuse it in a future op. */
       grpc_metadata_array *trailing_metadata;
       grpc_status_code *status;
-      /** status_details is a buffer owned by the application before the op
-          completes and after the op has completed. During the operation
-          status_details may be reallocated to a size larger than
-          *status_details_capacity, in which case *status_details_capacity will
-          be updated with the new array capacity.
-
-          Pre-allocating space:
-          size_t my_capacity = 8;
-          char *my_details = gpr_malloc(my_capacity);
-          x.status_details = &my_details;
-          x.status_details_capacity = &my_capacity;
-
-          Not pre-allocating space:
-          size_t my_capacity = 0;
-          char *my_details = NULL;
-          x.status_details = &my_details;
-          x.status_details_capacity = &my_capacity;
-
-          After the call:
-          gpr_free(my_details); */
-      char **status_details;
-      size_t *status_details_capacity;
+      grpc_slice *status_details;
     } recv_status_on_client;
     struct {
       /** out argument, set to 1 if the call failed in any way (seen as a
diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h
index 00781bb..0b09a0b 100644
--- a/include/grpc/impl/codegen/slice.h
+++ b/include/grpc/impl/codegen/slice.h
@@ -40,6 +40,8 @@
 #include <grpc/impl/codegen/exec_ctx_fwd.h>
 #include <grpc/impl/codegen/gpr_slice.h>
 
+typedef struct grpc_slice grpc_slice;
+
 /* Slice API
 
    A slice represents a contiguous reference counted array of bytes.
@@ -53,14 +55,25 @@
    reference ownership semantics (who should call unref?) and mutability
    constraints (is the callee allowed to modify the slice?) */
 
+typedef struct grpc_slice_refcount_vtable {
+  void (*ref)(void *);
+  void (*unref)(grpc_exec_ctx *exec_ctx, void *);
+  int (*eq)(grpc_slice a, grpc_slice b);
+  uint32_t (*hash)(grpc_slice slice);
+} grpc_slice_refcount_vtable;
+
 /* Reference count container for grpc_slice. Contains function pointers to
    increment and decrement reference counts. Implementations should cleanup
    when the reference count drops to zero.
    Typically client code should not touch this, and use grpc_slice_malloc,
    grpc_slice_new, or grpc_slice_new_with_len instead. */
 typedef struct grpc_slice_refcount {
-  void (*ref)(void *);
-  void (*unref)(grpc_exec_ctx *exec_ctx, void *);
+  const grpc_slice_refcount_vtable *vtable;
+  /* If a subset of this slice is taken, use this pointer for the refcount.
+     Typically points back to the refcount itself, however iterning
+     implementations can use this to avoid a verification step on each hash
+     or equality check */
+  struct grpc_slice_refcount *sub_refcount;
 } grpc_slice_refcount;
 
 #define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1)
@@ -74,7 +87,7 @@
 
    If the slice does not have a refcount, it represents an inlined small piece
    of data that is copied by value. */
-typedef struct grpc_slice {
+struct grpc_slice {
   struct grpc_slice_refcount *refcount;
   union {
     struct {
@@ -86,18 +99,23 @@
       uint8_t bytes[GRPC_SLICE_INLINED_SIZE];
     } inlined;
   } data;
-} grpc_slice;
+};
 
 #define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8
 
 /* Represents an expandable array of slices, to be interpreted as a
    single item. */
 typedef struct {
-  /* slices in the array */
+  /* This is for internal use only. External users (i.e any code outside grpc
+   * core) MUST NOT use this field */
+  grpc_slice *base_slices;
+
+  /* slices in the array (Points to the first valid grpc_slice in the array) */
   grpc_slice *slices;
   /* the number of slices in the array */
   size_t count;
-  /* the number of slices allocated in the array */
+  /* the number of slices allocated in the array. External users (i.e any code
+   * outside grpc core) MUST NOT use this field */
   size_t capacity;
   /* the combined length of all slices in the array */
   size_t length;
diff --git a/include/grpc/load_reporting.h b/include/grpc/load_reporting.h
new file mode 100644
index 0000000..c833ce5
--- /dev/null
+++ b/include/grpc/load_reporting.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_LOAD_REPORTING_H
+#define GRPC_LOAD_REPORTING_H
+
+#include <grpc/impl/codegen/port_platform.h>
+#include <grpc/slice.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Metadata key for the gRPC LB load balancer token.
+ *
+ * The value corresponding to this key is an opaque token that is given to the
+ * frontend as part of each pick; the frontend sends this token to the backend
+ * in each request it sends when using that pick. The token is used by the
+ * backend to verify the request and to allow the backend to report load to the
+ * gRPC LB system. */
+#define GRPC_LB_TOKEN_MD_KEY "lb-token"
+
+/** A sequence of values for load reporting purposes */
+typedef struct grpc_load_reporting_cost_context {
+  grpc_slice *values;
+  size_t values_count;
+} grpc_load_reporting_cost_context;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_LOAD_REPORTING_H */
diff --git a/include/grpc/slice.h b/include/grpc/slice.h
index 1f181aa..ea66e09 100644
--- a/include/grpc/slice.h
+++ b/include/grpc/slice.h
@@ -76,6 +76,12 @@
    Aborts if malloc() fails. */
 GPRAPI grpc_slice grpc_slice_malloc(size_t length);
 
+/* Intern a slice:
+
+   The return value for two invocations of this function with  the same sequence
+   of bytes is a slice which points to the same memory. */
+GPRAPI grpc_slice grpc_slice_intern(grpc_slice slice);
+
 /* Create a slice by copying a string.
    Does not preserve null terminators.
    Equivalent to:
@@ -93,6 +99,9 @@
 /* Create a slice pointing to constant memory */
 GPRAPI grpc_slice grpc_slice_from_static_string(const char *source);
 
+/* Create a slice pointing to constant memory */
+GPRAPI grpc_slice grpc_slice_from_static_buffer(const void *source, size_t len);
+
 /* Return a result slice derived from s, which shares a ref count with s, where
    result.data==s.data+begin, and result.length==end-begin.
    The ref count of s is increased by one.
@@ -113,18 +122,45 @@
    Requires s intialized, split <= s.length */
 GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split);
 
-GPRAPI grpc_slice gpr_empty_slice(void);
+GPRAPI grpc_slice grpc_empty_slice(void);
+
+GPRAPI uint32_t grpc_slice_default_hash_impl(grpc_slice s);
+GPRAPI int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b);
+
+GPRAPI int grpc_slice_eq(grpc_slice a, grpc_slice b);
 
 /* Returns <0 if a < b, ==0 if a == b, >0 if a > b
    The order is arbitrary, and is not guaranteed to be stable across different
    versions of the API. */
 GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b);
 GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b);
+GPRAPI int grpc_slice_buf_cmp(grpc_slice a, const void *b, size_t blen);
+
+/* return non-zero if the first blen bytes of a are equal to b */
+GPRAPI int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t blen);
+
+/* return the index of the last instance of \a c in \a s, or -1 if not found */
+GPRAPI int grpc_slice_rchr(grpc_slice s, char c);
+GPRAPI int grpc_slice_chr(grpc_slice s, char c);
+
+/* return the index of the first occurance of \a needle in \a haystack, or -1 if
+ * it's not found */
+GPRAPI int grpc_slice_slice(grpc_slice haystack, grpc_slice needle);
+
+GPRAPI uint32_t grpc_slice_hash(grpc_slice s);
 
 /* Do two slices point at the same memory, with the same length
    If a or b is inlined, actually compares data */
 GPRAPI int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b);
 
+/* Return a slice pointing to newly allocated memory that has the same contents
+ * as \a s */
+GPRAPI grpc_slice grpc_slice_dup(grpc_slice a);
+
+/* Return a copy of slice as a C string. Offers no protection against embedded
+   NULL's. Returned string must be freed with gpr_free. */
+GPRAPI char *grpc_slice_to_c_string(grpc_slice s);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/grpc/slice_buffer.h b/include/grpc/slice_buffer.h
index f1de653..2ed8966 100644
--- a/include/grpc/slice_buffer.h
+++ b/include/grpc/slice_buffer.h
@@ -77,8 +77,15 @@
 /* move the first n bytes of src into dst */
 GPRAPI void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
                                          grpc_slice_buffer *dst);
+/* move the first n bytes of src into dst (copying them) */
+GPRAPI void grpc_slice_buffer_move_first_into_buffer(grpc_exec_ctx *exec_ctx,
+                                                     grpc_slice_buffer *src,
+                                                     size_t n, void *dst);
 /* take the first slice in the slice buffer */
 GPRAPI grpc_slice grpc_slice_buffer_take_first(grpc_slice_buffer *src);
+/* undo the above with (a possibly different) \a slice */
+GPRAPI void grpc_slice_buffer_undo_take_first(grpc_slice_buffer *src,
+                                              grpc_slice slice);
 
 #ifdef __cplusplus
 }
diff --git a/include/grpc/support/alloc.h b/include/grpc/support/alloc.h
index 7209bec..541433c 100644
--- a/include/grpc/support/alloc.h
+++ b/include/grpc/support/alloc.h
@@ -44,6 +44,7 @@
 
 typedef struct gpr_allocation_functions {
   void *(*malloc_fn)(size_t size);
+  void *(*zalloc_fn)(size_t size); /* if NULL, uses malloc_fn then memset */
   void *(*realloc_fn)(void *ptr, size_t size);
   void (*free_fn)(void *ptr);
 } gpr_allocation_functions;
@@ -54,6 +55,8 @@
  * contain.
  */
 GPRAPI void *gpr_malloc(size_t size);
+/* like malloc, but zero all bytes before returning them */
+GPRAPI void *gpr_zalloc(size_t size);
 /* free */
 GPRAPI void gpr_free(void *ptr);
 /* realloc, never returns NULL */
diff --git a/include/grpc/support/useful.h b/include/grpc/support/useful.h
index 003e096..9d8314e 100644
--- a/include/grpc/support/useful.h
+++ b/include/grpc/support/useful.h
@@ -74,4 +74,7 @@
 
 #define GPR_ICMP(a, b) ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0))
 
+#define GPR_HASH_POINTER(x, range) \
+  ((((size_t)x) >> 4) ^ (((size_t)x) >> 9) ^ (((size_t)x) >> 14)) % (range)
+
 #endif /* GRPC_SUPPORT_USEFUL_H */
diff --git a/package.json b/package.json
index 66e2ab0..d729f3d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "grpc",
-  "version": "1.1.2",
+  "version": "1.2.0-dev",
   "author": "Google Inc.",
   "description": "gRPC Library for Node",
   "homepage": "http://www.grpc.io/",
diff --git a/package.xml b/package.xml
index c96a5ef..d82f2e4 100644
--- a/package.xml
+++ b/package.xml
@@ -13,8 +13,8 @@
  <date>2017-01-13</date>
  <time>16:06:07</time>
  <version>
-  <release>1.1.2</release>
-  <api>1.1.2</api>
+  <release>1.2.0dev</release>
+  <api>1.2.0dev</api>
  </version>
  <stability>
   <release>beta</release>
@@ -96,6 +96,7 @@
     <file baseinstalldir="/" name="src/core/lib/support/env.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/mpscq.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/murmur_hash.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/spinlock.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/string.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/string_windows.h" role="src" />
@@ -152,6 +153,7 @@
     <file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" />
+    <file baseinstalldir="/" name="include/grpc/load_reporting.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/slice.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/slice_buffer.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/status.h" role="src" />
@@ -200,6 +202,7 @@
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/error.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/iomgr/error_internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_linux.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.h" role="src" />
@@ -252,6 +255,7 @@
     <file baseinstalldir="/" name="src/core/lib/json/json_reader.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/json/json_writer.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
@@ -265,14 +269,18 @@
     <file baseinstalldir="/" name="src/core/lib/surface/init.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/lame_client.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/server.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/surface/validate_metadata.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/error_utils.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/http2_errors.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/service_config.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/status_conversion.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/transport_impl.h" role="src" />
@@ -289,11 +297,9 @@
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_encoder.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_parser.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_table.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http2_errors.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/status_conversion.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.h" role="src" />
@@ -310,6 +316,7 @@
     <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/lb_targets_info.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.h" role="src" />
@@ -326,11 +333,14 @@
     <file baseinstalldir="/" name="src/core/ext/client_channel/client_channel_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/connector.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/http_connect_handshaker.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/http_proxy.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/initial_connect_string.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/parse_address.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/proxy_mapper.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/proxy_mapper_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.h" role="src" />
@@ -339,6 +349,7 @@
     <file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb_channel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
@@ -358,6 +369,11 @@
     <file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/trace_context.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/trace_label.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/trace_propagation.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/trace_status.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/trace_string.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/tracing.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/channel_args.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/channel_stack.c" role="src" />
@@ -443,6 +459,8 @@
     <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_buffer.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/slice/slice_intern.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/alarm.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/api_trace.c" role="src" />
@@ -462,14 +480,16 @@
     <file baseinstalldir="/" name="src/core/lib/surface/server.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/validate_metadata.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/version.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.c" role="src" />
-    <file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/error_utils.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/service_config.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/transport/status_conversion.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/transport/transport_op_string.c" role="src" />
@@ -490,7 +510,6 @@
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/parsing.c" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/status_conversion.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_lists.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.c" role="src" />
@@ -512,6 +531,7 @@
     <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/client_auth_filter.c" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/security/transport/lb_targets_info.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.c" role="src" />
@@ -532,11 +552,14 @@
     <file baseinstalldir="/" name="src/core/ext/client_channel/connector.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/default_initial_connect_string.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/http_connect_handshaker.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/http_proxy.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/initial_connect_string.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_factory.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_registry.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/parse_address.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/proxy_mapper.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/client_channel/proxy_mapper_registry.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.c" role="src" />
@@ -549,6 +572,7 @@
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />
diff --git a/src/compiler/php_generator.cc b/src/compiler/php_generator.cc
index 5dac02c..fba8cba 100644
--- a/src/compiler/php_generator.cc
+++ b/src/compiler/php_generator.cc
@@ -134,29 +134,15 @@
   out->Outdent();
   out->Print("}\n\n");
 }
-
-void PrintServices(const FileDescriptor *file, Printer *out) {
-  map<grpc::string, grpc::string> vars;
-  vars["package"] = MessageIdentifierName(file->package());
-  out->Print(vars, "namespace $package$ {\n\n");
-  out->Indent();
-  for (int i = 0; i < file->service_count(); i++) {
-    PrintService(file->service(i), out);
-  }
-  out->Outdent();
-  out->Print("}\n");
-}
 }
 
-grpc::string GenerateFile(const FileDescriptor *file) {
+grpc::string GenerateFile(const FileDescriptor *file,
+                          const ServiceDescriptor *service) {
   grpc::string output;
   {
     StringOutputStream output_stream(&output);
     Printer out(&output_stream, '$');
 
-    if (file->service_count() == 0) {
-      return output;
-    }
     out.Print("<?php\n");
     out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");
 
@@ -166,7 +152,15 @@
       out.Print(leading_comments.c_str());
     }
 
-    PrintServices(file, &out);
+    map<grpc::string, grpc::string> vars;
+    vars["package"] = MessageIdentifierName(file->package());
+    out.Print(vars, "namespace $package$ {\n\n");
+    out.Indent();
+
+    PrintService(service, &out);
+
+    out.Outdent();
+    out.Print("}\n");
   }
   return output;
 }
diff --git a/src/compiler/php_generator.h b/src/compiler/php_generator.h
index 905dc90..c3061f1 100644
--- a/src/compiler/php_generator.h
+++ b/src/compiler/php_generator.h
@@ -38,7 +38,8 @@
 
 namespace grpc_php_generator {
 
-grpc::string GenerateFile(const grpc::protobuf::FileDescriptor *file);
+grpc::string GenerateFile(const grpc::protobuf::FileDescriptor *file,
+                          const grpc::protobuf::ServiceDescriptor *service);
 
 }  // namespace grpc_php_generator
 
diff --git a/src/compiler/php_generator_helpers.h b/src/compiler/php_generator_helpers.h
index 61c4d21..97eb2d3 100644
--- a/src/compiler/php_generator_helpers.h
+++ b/src/compiler/php_generator_helpers.h
@@ -41,14 +41,23 @@
 
 namespace grpc_php_generator {
 
-inline grpc::string GetPHPServiceFilename(const grpc::string& filename) {
-  return grpc_generator::StripProto(filename) + "_grpc_pb.php";
+inline grpc::string GetPHPServiceFilename(
+    const grpc::protobuf::FileDescriptor *file,
+    const grpc::protobuf::ServiceDescriptor *service) {
+  std::vector<grpc::string> tokens =
+      grpc_generator::tokenize(file->package(), ".");
+  std::ostringstream oss;
+  for (unsigned int i = 0; i < tokens.size(); i++) {
+    oss << (i == 0 ? "" : "/")
+        << grpc_generator::CapitalizeFirstLetter(tokens[i]);
+  }
+  return oss.str() + "/" + service->name() + "Client.php";
 }
 
 // Get leading or trailing comments in a string. Comment lines start with "// ".
 // Leading detached comments are put in in front of leading comments.
 template <typename DescriptorType>
-inline grpc::string GetPHPComments(const DescriptorType* desc,
+inline grpc::string GetPHPComments(const DescriptorType *desc,
                                    grpc::string prefix) {
   return grpc_generator::GetPrefixedComments(desc, true, prefix);
 }
diff --git a/src/compiler/php_plugin.cc b/src/compiler/php_plugin.cc
index 88acad6..00d4cd5 100644
--- a/src/compiler/php_plugin.cc
+++ b/src/compiler/php_plugin.cc
@@ -51,18 +51,22 @@
                 const grpc::string &parameter,
                 grpc::protobuf::compiler::GeneratorContext *context,
                 grpc::string *error) const {
-    grpc::string code = GenerateFile(file);
-    if (code.size() == 0) {
+    if (file->service_count() == 0) {
       return true;
     }
 
-    // Get output file name
-    grpc::string file_name = GetPHPServiceFilename(file->name());
+    for (int i = 0; i < file->service_count(); i++) {
+      grpc::string code = GenerateFile(file, file->service(i));
 
-    std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
-        context->Open(file_name));
-    grpc::protobuf::io::CodedOutputStream coded_out(output.get());
-    coded_out.WriteRaw(code.data(), code.size());
+      // Get output file name
+      grpc::string file_name = GetPHPServiceFilename(file, file->service(i));
+
+      std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
+          context->Open(file_name));
+      grpc::protobuf::io::CodedOutputStream coded_out(output.get());
+      coded_out.WriteRaw(code.data(), code.size());
+    }
+
     return true;
   }
 };
diff --git a/src/core/ext/census/gen/census.pb.h b/src/core/ext/census/gen/census.pb.h
index dae583f..c8546ea 100644
--- a/src/core/ext/census/gen/census.pb.h
+++ b/src/core/ext/census/gen/census.pb.h
@@ -292,4 +292,4 @@
 } /* extern "C" */
 #endif
 
-#endif
+#endif /* GRPC_CORE_EXT_CENSUS_GEN_CENSUS_PB_H */
diff --git a/src/core/ext/census/gen/trace_context.pb.c b/src/core/ext/census/gen/trace_context.pb.c
index c8aea32..f4126d4 100644
--- a/src/core/ext/census/gen/trace_context.pb.c
+++ b/src/core/ext/census/gen/trace_context.pb.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2016, Google Inc.
+ * Copyright 2017, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,51 +31,24 @@
  *
  */
 /* Automatically generated nanopb constant definitions */
-/* Generated by nanopb-0.3.5-dev */
+/* Generated by nanopb-0.3.7-dev at Fri Jan 20 16:14:22 2017. */
 
 #include "src/core/ext/census/gen/trace_context.pb.h"
 
+/* @@protoc_insertion_point(includes) */
 #if PB_PROTO_HEADER_VERSION != 30
 #error Regenerate this file with the current version of nanopb generator.
 #endif
 
 
 
-const pb_field_t google_trace_TraceId_fields[3] = {
-    PB_FIELD(  1, FIXED64 , OPTIONAL, STATIC  , FIRST, google_trace_TraceId, hi, hi, 0),
-    PB_FIELD(  2, FIXED64 , OPTIONAL, STATIC  , OTHER, google_trace_TraceId, lo, hi, 0),
-    PB_LAST_FIELD
-};
-
-const pb_field_t google_trace_TraceContext_fields[4] = {
-    PB_FIELD(  1, MESSAGE , OPTIONAL, STATIC  , FIRST, google_trace_TraceContext, trace_id, trace_id, &google_trace_TraceId_fields),
-    PB_FIELD(  2, FIXED64 , OPTIONAL, STATIC  , OTHER, google_trace_TraceContext, span_id, trace_id, 0),
-    PB_FIELD(  3, BOOL    , OPTIONAL, STATIC  , OTHER, google_trace_TraceContext, is_sampled, span_id, 0),
+const pb_field_t google_trace_TraceContext_fields[5] = {
+    PB_FIELD(  1, FIXED64 , OPTIONAL, STATIC  , FIRST, google_trace_TraceContext, trace_id_hi, trace_id_hi, 0),
+    PB_FIELD(  2, FIXED64 , OPTIONAL, STATIC  , OTHER, google_trace_TraceContext, trace_id_lo, trace_id_hi, 0),
+    PB_FIELD(  3, FIXED64 , OPTIONAL, STATIC  , OTHER, google_trace_TraceContext, span_id, trace_id_lo, 0),
+    PB_FIELD(  4, FIXED32 , OPTIONAL, STATIC  , OTHER, google_trace_TraceContext, span_options, span_id, 0),
     PB_LAST_FIELD
 };
 
 
-/* Check that field information fits in pb_field_t */
-#if !defined(PB_FIELD_32BIT)
-/* If you get an error here, it means that you need to define PB_FIELD_32BIT
- * compile-time option. You can do that in pb.h or on compiler command line.
- * 
- * The reason you need to do this is that some of your messages contain tag
- * numbers or field sizes that are larger than what can fit in 8 or 16 bit
- * field descriptors.
- */
-PB_STATIC_ASSERT((pb_membersize(google_trace_TraceContext, trace_id) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_trace_TraceId_google_trace_TraceContext)
-#endif
-
-#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
-/* If you get an error here, it means that you need to define PB_FIELD_16BIT
- * compile-time option. You can do that in pb.h or on compiler command line.
- * 
- * The reason you need to do this is that some of your messages contain tag
- * numbers or field sizes that are larger than what can fit in the default
- * 8 bit descriptors.
- */
-PB_STATIC_ASSERT((pb_membersize(google_trace_TraceContext, trace_id) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_trace_TraceId_google_trace_TraceContext)
-#endif
-
-
+/* @@protoc_insertion_point(eof) */
diff --git a/src/core/ext/census/gen/trace_context.pb.h b/src/core/ext/census/gen/trace_context.pb.h
index 263c4c5..ea127bf 100644
--- a/src/core/ext/census/gen/trace_context.pb.h
+++ b/src/core/ext/census/gen/trace_context.pb.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2016, Google Inc.
+ * Copyright 2017, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,11 +31,13 @@
  *
  */
 /* Automatically generated nanopb header */
-/* Generated by nanopb-0.3.5-dev */
+/* Generated by nanopb-0.3.7-dev at Fri Jan 20 16:14:22 2017. */
 
 #ifndef GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H
 #define GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H
 #include "third_party/nanopb/pb.h"
+
+/* @@protoc_insertion_point(includes) */
 #if PB_PROTO_HEADER_VERSION != 30
 #error Regenerate this file with the current version of nanopb generator.
 #endif
@@ -45,44 +47,35 @@
 #endif
 
 /* Struct definitions */
-typedef struct _google_trace_TraceId {
-    bool has_hi;
-    uint64_t hi;
-    bool has_lo;
-    uint64_t lo;
-} google_trace_TraceId;
-
 typedef struct _google_trace_TraceContext {
-    bool has_trace_id;
-    google_trace_TraceId trace_id;
+    bool has_trace_id_hi;
+    uint64_t trace_id_hi;
+    bool has_trace_id_lo;
+    uint64_t trace_id_lo;
     bool has_span_id;
     uint64_t span_id;
-    bool has_is_sampled;
-    bool is_sampled;
+    bool has_span_options;
+    uint32_t span_options;
+/* @@protoc_insertion_point(struct:google_trace_TraceContext) */
 } google_trace_TraceContext;
 
 /* Default values for struct fields */
 
 /* Initializer values for message structs */
-#define google_trace_TraceId_init_default        {false, 0, false, 0}
-#define google_trace_TraceContext_init_default   {false, google_trace_TraceId_init_default, false, 0, false, 0}
-#define google_trace_TraceId_init_zero           {false, 0, false, 0}
-#define google_trace_TraceContext_init_zero      {false, google_trace_TraceId_init_zero, false, 0, false, 0}
+#define google_trace_TraceContext_init_default   {false, 0, false, 0, false, 0, false, 0}
+#define google_trace_TraceContext_init_zero      {false, 0, false, 0, false, 0, false, 0}
 
 /* Field tags (for use in manual encoding/decoding) */
-#define google_trace_TraceId_hi_tag              1
-#define google_trace_TraceId_lo_tag              2
-#define google_trace_TraceContext_trace_id_tag   1
-#define google_trace_TraceContext_span_id_tag    2
-#define google_trace_TraceContext_is_sampled_tag 3
+#define google_trace_TraceContext_trace_id_hi_tag 1
+#define google_trace_TraceContext_trace_id_lo_tag 2
+#define google_trace_TraceContext_span_id_tag    3
+#define google_trace_TraceContext_span_options_tag 4
 
 /* Struct field encoding specification for nanopb */
-extern const pb_field_t google_trace_TraceId_fields[3];
-extern const pb_field_t google_trace_TraceContext_fields[4];
+extern const pb_field_t google_trace_TraceContext_fields[5];
 
 /* Maximum encoded size of messages (where known) */
-#define google_trace_TraceId_size                18
-#define google_trace_TraceContext_size           31
+#define google_trace_TraceContext_size           32
 
 /* Message IDs (where set with "msgid" option) */
 #ifdef PB_MSGID
@@ -95,5 +88,6 @@
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
+/* @@protoc_insertion_point(eof) */
 
 #endif
diff --git a/src/core/ext/census/grpc_filter.c b/src/core/ext/census/grpc_filter.c
index 8e4d473..b80d831 100644
--- a/src/core/ext/census/grpc_filter.c
+++ b/src/core/ext/census/grpc_filter.c
@@ -67,9 +67,7 @@
                                             channel_data *chand) {
   grpc_linked_mdelem *m;
   for (m = md->list.head; m != NULL; m = m->next) {
-    if (m->md->key == GRPC_MDSTR_PATH) {
-      gpr_log(GPR_DEBUG, "%s",
-              (const char *)GRPC_SLICE_START_PTR(m->md->value->slice));
+    if (grpc_slice_eq(GRPC_MDKEY(m->md), GRPC_MDSTR_PATH)) {
       /* Add method tag here */
     }
   }
@@ -129,7 +127,7 @@
 
 static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx,
                                          grpc_call_element *elem,
-                                         grpc_call_element_args *args) {
+                                         const grpc_call_element_args *args) {
   call_data *d = elem->call_data;
   GPR_ASSERT(d != NULL);
   memset(d, 0, sizeof(*d));
@@ -148,7 +146,7 @@
 
 static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx,
                                          grpc_call_element *elem,
-                                         grpc_call_element_args *args) {
+                                         const grpc_call_element_args *args) {
   call_data *d = elem->call_data;
   GPR_ASSERT(d != NULL);
   memset(d, 0, sizeof(*d));
diff --git a/src/core/ext/census/trace_context.c b/src/core/ext/census/trace_context.c
index fbb20d3..47d0de1 100644
--- a/src/core/ext/census/trace_context.c
+++ b/src/core/ext/census/trace_context.c
@@ -73,7 +73,7 @@
   }
 
   // check fields
-  if (!ctxt->has_trace_id) {
+  if (!ctxt->has_trace_id_hi || !ctxt->has_trace_id_lo) {
     gpr_log(GPR_DEBUG, "Invalid TraceContext: missing trace_id");
     return false;
   }
diff --git a/src/core/ext/census/trace_context.h b/src/core/ext/census/trace_context.h
index 1cb5e26..f391a1b 100644
--- a/src/core/ext/census/trace_context.h
+++ b/src/core/ext/census/trace_context.h
@@ -38,6 +38,9 @@
 
 #include "src/core/ext/census/gen/trace_context.pb.h"
 
+/* Span option flags. */
+#define SPAN_OPTIONS_IS_SAMPLED 0x01
+
 /* Maximum number of bytes required to encode a TraceContext (31)
 1 byte for trace_id field
 1 byte for trace_id length
diff --git a/src/core/ext/census/trace_label.h b/src/core/ext/census/trace_label.h
new file mode 100644
index 0000000..0e4a8d8
--- /dev/null
+++ b/src/core/ext/census/trace_label.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_TRACE_LABEL_H
+#define GRPC_CORE_EXT_CENSUS_TRACE_LABEL_H
+
+#include "src/core/ext/census/trace_string.h"
+
+/* Trace label (key/value pair) stores a label name and the label value. The
+   value can be one of trace_string/int64_t/bool. */
+typedef struct trace_label {
+  trace_string key;
+  enum label_type {
+    /* Unknown value for debugging/error purposes */
+    LABEL_UNKNOWN = 0,
+    /* A string value */
+    LABEL_STRING = 1,
+    /* An integer value. */
+    LABEL_INT = 2,
+    /* A boolean value. */
+    LABEL_BOOL = 3,
+  } value_type;
+
+  union value {
+    trace_string label_str;
+    int64_t label_int;
+    bool label_bool;
+  } value;
+} trace_label;
+
+#endif
diff --git a/src/core/ext/census/trace_propagation.h b/src/core/ext/census/trace_propagation.h
new file mode 100644
index 0000000..75c4eba
--- /dev/null
+++ b/src/core/ext/census/trace_propagation.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H
+#define GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H
+
+#include "src/core/ext/census/tracing.h"
+
+/* Encoding and decoding functions for receiving and sending trace contexts
+   over the wire.  Only RPC libraries should be calling these
+   functions.  These functions return the number of bytes encoded/decoded
+   (0 if a failure has occurred). buf_size indicates the size of the
+   input/output buffer. trace_span_context is a struct that includes the
+   trace ID, span ID, and a set of option flags (is_sampled, etc.). */
+
+/* Converts a span context to a binary byte buffer. */
+size_t trace_span_context_to_binary(const trace_span_context *ctxt,
+                                    uint8_t *buf, size_t buf_size);
+
+/* Reads a binary byte buffer and populates a span context structure. */
+size_t binary_to_trace_span_context(const uint8_t *buf, size_t buf_size,
+                                    trace_span_context *ctxt);
+
+/* Converts a span context to an http metadata compatible string. */
+size_t trace_span_context_to_http_format(const trace_span_context *ctxt,
+                                         char *buf, size_t buf_size);
+
+/* Reads an http metadata compatible string and populates a span context
+   structure. */
+size_t http_format_to_trace_span_context(const char *buf, size_t buf_size,
+                                         trace_span_context *ctxt);
+
+#endif
diff --git a/src/core/ext/census/trace_status.h b/src/core/ext/census/trace_status.h
new file mode 100644
index 0000000..adc0ebd
--- /dev/null
+++ b/src/core/ext/census/trace_status.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_TRACE_STATUS_H
+#define GRPC_CORE_EXT_CENSUS_TRACE_STATUS_H
+
+#include "src/core/ext/census/trace_string.h"
+
+/* Stores a status code and status message for a trace. */
+typedef struct trace_status {
+  int64_t errorCode;
+  trace_string errorMessage;
+} trace_status;
+
+#endif
diff --git a/src/core/ext/census/trace_string.h b/src/core/ext/census/trace_string.h
new file mode 100644
index 0000000..8e77ee9
--- /dev/null
+++ b/src/core/ext/census/trace_string.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_TRACE_STRING_H
+#define GRPC_CORE_EXT_CENSUS_TRACE_STRING_H
+
+#include <grpc/slice.h>
+
+/* String struct for tracing messages. Since this is a C API, we do not have
+   access to a string class.  This is intended for use by higher level
+   languages which wrap around the C API, as most of them have a string class.
+   This will also be more efficient when copying, as we have an explicitly
+   specified length.  Also, grpc_slice has reference counting which allows for
+   interning. */
+typedef struct trace_string {
+  char *string;
+  size_t length;
+} trace_string;
+
+#endif
diff --git a/src/core/ext/census/tracing.c b/src/core/ext/census/tracing.c
index 9371fff..8b74628 100644
--- a/src/core/ext/census/tracing.c
+++ b/src/core/ext/census/tracing.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,21 +31,41 @@
  *
  */
 
-//#include "src/core/ext/census/tracing.h"
+#include "src/core/ext/census/tracing.h"
 
 #include <grpc/census.h>
-#include <stdlib.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <openssl/rand.h>
+#include "src/core/ext/census/mlog.h"
 
-/* TODO(aveitch): These are all placeholder implementations. */
-
-int census_trace_mask(const census_context *context) {
-  abort();
-  return CENSUS_TRACE_MASK_NONE;
+void trace_start_span(const trace_span_context *span_ctxt,
+                      const trace_string name, const start_span_options *opts,
+                      trace_span_context *new_span_ctxt,
+                      bool has_remote_parent) {
+  // Noop implementation.
 }
 
-void census_set_trace_mask(int trace_mask) { abort(); }
+void trace_add_span_annotation(const trace_string description,
+                               const trace_label *labels, const size_t n_labels,
+                               trace_span_context *span_ctxt) {
+  // Noop implementation.
+}
 
-void census_trace_print(census_context *context, uint32_t type,
-                        const char *buffer, size_t n) {
-  abort();
+void trace_add_span_network_event_annotation(const trace_string description,
+                                             const trace_label *labels,
+                                             const size_t n_labels,
+                                             const gpr_timespec timestamp,
+                                             bool sent, uint64_t id,
+                                             trace_span_context *span_ctxt) {
+  // Noop implementation.
+}
+
+void trace_add_span_labels(const trace_label *labels, const size_t n_labels,
+                           trace_span_context *span_ctxt) {
+  // Noop implementation.
+}
+
+void trace_end_span(const trace_status *status, trace_span_context *span_ctxt) {
+  // Noop implementation.
 }
diff --git a/src/core/ext/census/tracing.h b/src/core/ext/census/tracing.h
new file mode 100644
index 0000000..c2b947a
--- /dev/null
+++ b/src/core/ext/census/tracing.h
@@ -0,0 +1,124 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_TRACING_H
+#define GRPC_CORE_EXT_CENSUS_TRACING_H
+
+#include <grpc/support/time.h>
+#include <stdbool.h>
+#include "src/core/ext/census/trace_context.h"
+#include "src/core/ext/census/trace_label.h"
+#include "src/core/ext/census/trace_status.h"
+
+/* This is the low level tracing API that other languages will interface with.
+   This is not intended to be accessed by the end-user, therefore it has been
+   designed with performance in mind rather than ease of use. */
+
+/* The tracing level. */
+enum TraceLevel {
+  /* Annotations on this context will be silently discarded. */
+  NO_TRACING = 0,
+  /* Annotations will not be saved to a persistent store. They will be
+     available via local APIs only. This setting is not propagated to child
+     spans. */
+  TRANSIENT_TRACING = 1,
+  /* Annotations are recorded for the entire distributed trace and they are
+     saved to a persistent store. This setting is propagated to child spans. */
+  PERSISTENT_TRACING = 2,
+};
+
+typedef struct trace_span_context {
+  /* Trace span context stores Span ID, Trace ID, and option flags. */
+  /* Trace ID is 128 bits split into 2 64-bit chunks (hi and lo). */
+  uint64_t trace_id_hi;
+  uint64_t trace_id_lo;
+  /* Span ID is 64 bits. */
+  uint64_t span_id;
+  /* Span-options is 32-bit value which contains flag options. */
+  uint32_t span_options;
+} trace_span_context;
+
+typedef struct start_span_options {
+  /* If set, this will override the Span.local_start_time for the Span. */
+  gpr_timespec local_start_timestamp;
+
+  /* Linked spans can be used to identify spans that are linked to this span in
+     a different trace.  This can be used (for example) in batching operations,
+     where a single batch handler processes multiple requests from different
+     traces. If set, points to a list of Spans are linked to the created Span.*/
+  trace_span_context *linked_spans;
+  /* The number of linked spans. */
+  size_t n_linked_spans;
+} start_span_options;
+
+/* Create a new child Span (or root if parent is NULL), with parent being the
+   designated Span. The child span will have the provided name and starting
+   span options (optional). The bool has_remote_parent marks whether the
+   context refers to a remote parent span or not. */
+void trace_start_span(const trace_span_context *span_ctxt,
+                      const trace_string name, const start_span_options *opts,
+                      trace_span_context *new_span_ctxt,
+                      bool has_remote_parent);
+
+/* Add a new Annotation to the Span. Annotations consist of a description
+   (trace_string) and a set of n labels (trace_label).  This can be populated
+   with arbitrary user data. */
+void trace_add_span_annotation(const trace_string description,
+                               const trace_label *labels, const size_t n_labels,
+                               trace_span_context *span_ctxt);
+
+/* Add a new NetworkEvent annotation to a Span. This function is only intended
+  to be used by RPC systems (either client or server), not by higher level
+  applications. The timestamp type will be system-defined, the sent argument
+  designates whether this is a network send event (client request, server
+  reply)or receive (server request, client reply). The id argument corresponds
+  to Span.Annotation.NetworkEvent.id from the data model, and serves to uniquely
+  identify each network message. */
+void trace_add_span_network_event(const trace_string description,
+                                  const trace_label *labels,
+                                  const size_t n_labels,
+                                  const gpr_timespec timestamp, bool sent,
+                                  uint64_t id, trace_span_context *span_ctxt);
+
+/* Add a set of labels to the Span. These will correspond to the field
+Span.labels in the data model. */
+void trace_add_span_labels(const trace_label *labels, const size_t n_labels,
+                           trace_span_context *span_ctxt);
+
+/* Mark the end of Span Execution with the given status. Only the timing of the
+first EndSpan call for a given Span will be recorded, and implementations are
+free to ignore all further calls using the Span. EndSpanOptions can
+optionally be NULL. */
+void trace_end_span(const trace_status *status, trace_span_context *span_ctxt);
+
+#endif
diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c
index 2f25fef..34015c5 100644
--- a/src/core/ext/client_channel/client_channel.c
+++ b/src/core/ext/client_channel/client_channel.c
@@ -43,15 +43,19 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/useful.h>
 
+#include "src/core/ext/client_channel/http_connect_handshaker.h"
 #include "src/core/ext/client_channel/lb_policy_registry.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/ext/client_channel/subchannel.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/channel/deadline_filter.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/polling_entity.h"
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/transport/connectivity_state.h"
@@ -87,7 +91,7 @@
   gpr_free(p);
 }
 
-static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
+static const grpc_slice_hash_table_vtable method_parameters_vtable = {
     method_parameters_free, method_parameters_copy};
 
 static void *method_parameters_create_from_json(const grpc_json *json) {
@@ -157,15 +161,12 @@
   /** client channel factory */
   grpc_client_channel_factory *client_channel_factory;
 
-  /** mutex protecting all variables below in this data structure */
-  gpr_mu mu;
+  /** combiner protecting all variables below in this data structure */
+  grpc_combiner *combiner;
   /** currently active load balancer */
-  char *lb_policy_name;
   grpc_lb_policy *lb_policy;
-  /** service config in JSON form */
-  char *service_config_json;
   /** maps method names to method_parameters structs */
-  grpc_mdstr_hash_table *method_params_table;
+  grpc_slice_hash_table *method_params_table;
   /** incoming resolver result - set by resolver.next() */
   grpc_channel_args *resolver_result;
   /** a list of closures that are all waiting for config to come in */
@@ -180,6 +181,13 @@
   grpc_channel_stack *owning_stack;
   /** interested parties (owned) */
   grpc_pollset_set *interested_parties;
+
+  /* the following properties are guarded by a mutex since API's require them
+     to be instantaneously available */
+  gpr_mu info_mu;
+  char *info_lb_policy_name;
+  /** service config in JSON form */
+  char *info_service_config_json;
 } channel_data;
 
 /** We create one watcher for each new lb_policy that is returned from a
@@ -192,9 +200,9 @@
   grpc_lb_policy *lb_policy;
 } lb_policy_connectivity_watcher;
 
-static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
-                            grpc_lb_policy *lb_policy,
-                            grpc_connectivity_state current_state);
+static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
+                                   grpc_lb_policy *lb_policy,
+                                   grpc_connectivity_state current_state);
 
 static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
                                                   channel_data *chand,
@@ -205,7 +213,7 @@
        state == GRPC_CHANNEL_SHUTDOWN) &&
       chand->lb_policy != NULL) {
     /* cancel picks with wait_for_ready=false */
-    grpc_lb_policy_cancel_picks(
+    grpc_lb_policy_cancel_picks_locked(
         exec_ctx, chand->lb_policy,
         /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
         /* check= */ 0, GRPC_ERROR_REF(error));
@@ -215,59 +223,50 @@
 }
 
 static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
-                                              lb_policy_connectivity_watcher *w,
-                                              grpc_error *error) {
-  grpc_connectivity_state publish_state = w->state;
-  /* check if the notification is for a stale policy */
-  if (w->lb_policy != w->chand->lb_policy) return;
-
-  if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
-    publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
-    grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
-    GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
-    w->chand->lb_policy = NULL;
-  }
-  set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
-                                        GRPC_ERROR_REF(error), "lb_changed");
-  if (w->state != GRPC_CHANNEL_SHUTDOWN) {
-    watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
-  }
-}
-
-static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                       grpc_error *error) {
+                                              void *arg, grpc_error *error) {
   lb_policy_connectivity_watcher *w = arg;
-
-  gpr_mu_lock(&w->chand->mu);
-  on_lb_policy_state_changed_locked(exec_ctx, w, error);
-  gpr_mu_unlock(&w->chand->mu);
+  grpc_connectivity_state publish_state = w->state;
+  /* check if the notification is for the latest policy */
+  if (w->lb_policy == w->chand->lb_policy) {
+    if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
+      publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
+      grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
+      GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
+      w->chand->lb_policy = NULL;
+    }
+    set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
+                                          GRPC_ERROR_REF(error), "lb_changed");
+    if (w->state != GRPC_CHANNEL_SHUTDOWN) {
+      watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
+    }
+  }
 
   GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
   gpr_free(w);
 }
 
-static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
-                            grpc_lb_policy *lb_policy,
-                            grpc_connectivity_state current_state) {
+static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
+                                   grpc_lb_policy *lb_policy,
+                                   grpc_connectivity_state current_state) {
   lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
   GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
 
   w->chand = chand;
-  grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w,
-                    grpc_schedule_on_exec_ctx);
+  grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
+                    grpc_combiner_scheduler(chand->combiner, false));
   w->state = current_state;
   w->lb_policy = lb_policy;
-  grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
-                                        &w->on_changed);
+  grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
+                                               &w->on_changed);
 }
 
-static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                       grpc_error *error) {
+static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
+                                              void *arg, grpc_error *error) {
   channel_data *chand = arg;
   char *lb_policy_name = NULL;
   grpc_lb_policy *lb_policy = NULL;
   grpc_lb_policy *old_lb_policy;
-  grpc_mdstr_hash_table *method_params_table = NULL;
+  grpc_slice_hash_table *method_params_table = NULL;
   grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
   bool exit_idle = false;
   grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
@@ -314,13 +313,14 @@
     grpc_lb_policy_args lb_policy_args;
     lb_policy_args.args = chand->resolver_result;
     lb_policy_args.client_channel_factory = chand->client_channel_factory;
+    lb_policy_args.combiner = chand->combiner;
     lb_policy =
         grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
     if (lb_policy != NULL) {
       GRPC_LB_POLICY_REF(lb_policy, "config_change");
       GRPC_ERROR_UNREF(state_error);
-      state =
-          grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
+      state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
+                                                       &state_error);
     }
     // Find service config.
     channel_arg =
@@ -350,19 +350,20 @@
                                      chand->interested_parties);
   }
 
-  gpr_mu_lock(&chand->mu);
+  gpr_mu_lock(&chand->info_mu);
   if (lb_policy_name != NULL) {
-    gpr_free(chand->lb_policy_name);
-    chand->lb_policy_name = lb_policy_name;
+    gpr_free(chand->info_lb_policy_name);
+    chand->info_lb_policy_name = lb_policy_name;
   }
   old_lb_policy = chand->lb_policy;
   chand->lb_policy = lb_policy;
   if (service_config_json != NULL) {
-    gpr_free(chand->service_config_json);
-    chand->service_config_json = service_config_json;
+    gpr_free(chand->info_service_config_json);
+    chand->info_service_config_json = service_config_json;
   }
+  gpr_mu_unlock(&chand->info_mu);
   if (chand->method_params_table != NULL) {
-    grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
+    grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
   }
   chand->method_params_table = method_params_table;
   if (lb_policy != NULL) {
@@ -383,15 +384,15 @@
     set_channel_connectivity_state_locked(
         exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
     if (lb_policy != NULL) {
-      watch_lb_policy(exec_ctx, chand, lb_policy, state);
+      watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
     }
     GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
-    grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
-                       &chand->on_resolver_result_changed);
-    gpr_mu_unlock(&chand->mu);
+    grpc_resolver_next_locked(exec_ctx, chand->resolver,
+                              &chand->resolver_result,
+                              &chand->on_resolver_result_changed);
   } else {
     if (chand->resolver != NULL) {
-      grpc_resolver_shutdown(exec_ctx, chand->resolver);
+      grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
       GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
       chand->resolver = NULL;
     }
@@ -401,11 +402,10 @@
         GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
                                       GPR_ARRAY_SIZE(refs)),
         "resolver_gone");
-    gpr_mu_unlock(&chand->mu);
   }
 
   if (exit_idle) {
-    grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
+    grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
     GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
   }
 
@@ -423,20 +423,12 @@
   GRPC_ERROR_UNREF(state_error);
 }
 
-static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
-                                  grpc_channel_element *elem,
-                                  grpc_transport_op *op) {
+static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                      grpc_error *error_ignored) {
+  grpc_transport_op *op = arg;
+  grpc_channel_element *elem = op->transport_private.args[0];
   channel_data *chand = elem->channel_data;
 
-  grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
-
-  GPR_ASSERT(op->set_accept_stream == false);
-  if (op->bind_pollset != NULL) {
-    grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
-                                 op->bind_pollset);
-  }
-
-  gpr_mu_lock(&chand->mu);
   if (op->on_connectivity_state_change != NULL) {
     grpc_connectivity_state_notify_on_state_change(
         exec_ctx, &chand->state_tracker, op->connectivity_state,
@@ -450,7 +442,7 @@
       grpc_closure_sched(exec_ctx, op->send_ping,
                          GRPC_ERROR_CREATE("Ping with no load balancing"));
     } else {
-      grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
+      grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
       op->bind_pollset = NULL;
     }
     op->send_ping = NULL;
@@ -461,7 +453,7 @@
       set_channel_connectivity_state_locked(
           exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
           GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
-      grpc_resolver_shutdown(exec_ctx, chand->resolver);
+      grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
       GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
       chand->resolver = NULL;
       if (!chand->started_resolving) {
@@ -479,25 +471,48 @@
     }
     GRPC_ERROR_UNREF(op->disconnect_with_error);
   }
-  gpr_mu_unlock(&chand->mu);
+  GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
+
+  grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
+}
+
+static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
+                                  grpc_channel_element *elem,
+                                  grpc_transport_op *op) {
+  channel_data *chand = elem->channel_data;
+
+  GPR_ASSERT(op->set_accept_stream == false);
+  if (op->bind_pollset != NULL) {
+    grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
+                                 op->bind_pollset);
+  }
+
+  op->transport_private.args[0] = elem;
+  GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
+  grpc_closure_sched(
+      exec_ctx, grpc_closure_init(
+                    &op->transport_private.closure, start_transport_op_locked,
+                    op, grpc_combiner_scheduler(chand->combiner, false)),
+      GRPC_ERROR_NONE);
 }
 
 static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
                                 grpc_channel_element *elem,
                                 const grpc_channel_info *info) {
   channel_data *chand = elem->channel_data;
-  gpr_mu_lock(&chand->mu);
+  gpr_mu_lock(&chand->info_mu);
   if (info->lb_policy_name != NULL) {
-    *info->lb_policy_name = chand->lb_policy_name == NULL
+    *info->lb_policy_name = chand->info_lb_policy_name == NULL
                                 ? NULL
-                                : gpr_strdup(chand->lb_policy_name);
+                                : gpr_strdup(chand->info_lb_policy_name);
   }
   if (info->service_config_json != NULL) {
-    *info->service_config_json = chand->service_config_json == NULL
-                                     ? NULL
-                                     : gpr_strdup(chand->service_config_json);
+    *info->service_config_json =
+        chand->info_service_config_json == NULL
+            ? NULL
+            : gpr_strdup(chand->info_service_config_json);
   }
-  gpr_mu_unlock(&chand->mu);
+  gpr_mu_unlock(&chand->info_mu);
 }
 
 /* Constructor for channel_data */
@@ -505,15 +520,15 @@
                                         grpc_channel_element *elem,
                                         grpc_channel_element_args *args) {
   channel_data *chand = elem->channel_data;
-  memset(chand, 0, sizeof(*chand));
   GPR_ASSERT(args->is_last);
   GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
   // Initialize data members.
-  gpr_mu_init(&chand->mu);
+  chand->combiner = grpc_combiner_create(NULL);
+  gpr_mu_init(&chand->info_mu);
   chand->owning_stack = args->channel_stack;
   grpc_closure_init(&chand->on_resolver_result_changed,
-                    on_resolver_result_changed, chand,
-                    grpc_schedule_on_exec_ctx);
+                    on_resolver_result_changed_locked, chand,
+                    grpc_combiner_scheduler(chand->combiner, false));
   chand->interested_parties = grpc_pollset_set_create();
   grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
                                "client_channel");
@@ -524,27 +539,44 @@
   GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
   grpc_client_channel_factory_ref(arg->value.pointer.p);
   chand->client_channel_factory = arg->value.pointer.p;
-  // Instantiate resolver.
+  // Get server name to resolve, using proxy mapper if needed.
   arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
   GPR_ASSERT(arg != NULL);
   GPR_ASSERT(arg->type == GRPC_ARG_STRING);
-  chand->resolver =
-      grpc_resolver_create(exec_ctx, arg->value.string, args->channel_args,
-                           chand->interested_parties);
+  char *proxy_name = NULL;
+  grpc_channel_args *new_args = NULL;
+  grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
+                              &proxy_name, &new_args);
+  // Instantiate resolver.
+  chand->resolver = grpc_resolver_create(
+      exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
+      new_args != NULL ? new_args : args->channel_args,
+      chand->interested_parties, chand->combiner);
+  if (proxy_name != NULL) gpr_free(proxy_name);
+  if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
   if (chand->resolver == NULL) {
     return GRPC_ERROR_CREATE("resolver creation failed");
   }
   return GRPC_ERROR_NONE;
 }
 
+static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                     grpc_error *error) {
+  grpc_resolver *resolver = arg;
+  grpc_resolver_shutdown_locked(exec_ctx, resolver);
+  GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
+}
+
 /* Destructor for channel_data */
 static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
                                     grpc_channel_element *elem) {
   channel_data *chand = elem->channel_data;
-
   if (chand->resolver != NULL) {
-    grpc_resolver_shutdown(exec_ctx, chand->resolver);
-    GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
+    grpc_closure_sched(
+        exec_ctx,
+        grpc_closure_create(shutdown_resolver_locked, chand->resolver,
+                            grpc_combiner_scheduler(chand->combiner, false)),
+        GRPC_ERROR_NONE);
   }
   if (chand->client_channel_factory != NULL) {
     grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
@@ -555,14 +587,15 @@
                                      chand->interested_parties);
     GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
   }
-  gpr_free(chand->lb_policy_name);
-  gpr_free(chand->service_config_json);
+  gpr_free(chand->info_lb_policy_name);
+  gpr_free(chand->info_service_config_json);
   if (chand->method_params_table != NULL) {
-    grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
+    grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
   }
   grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
-  grpc_pollset_set_destroy(chand->interested_parties);
-  gpr_mu_destroy(&chand->mu);
+  grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
+  GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
+  gpr_mu_destroy(&chand->info_mu);
 }
 
 /*************************************************************************
@@ -593,7 +626,7 @@
   // to avoid this without breaking the grpc_deadline_state abstraction.
   grpc_deadline_state deadline_state;
 
-  grpc_mdstr *path;  // Request path.
+  grpc_slice path;  // Request path.
   gpr_timespec call_start_time;
   gpr_timespec deadline;
   wait_for_ready_value wait_for_ready_from_service_config;
@@ -605,8 +638,6 @@
       grpc_subchannel_call */
   gpr_atm subchannel_call;
 
-  gpr_mu mu;
-
   subchannel_creation_phase creation_phase;
   grpc_connected_subchannel *connected_subchannel;
   grpc_polling_entity *pollent;
@@ -622,6 +653,12 @@
   grpc_linked_mdelem lb_token_mdelem;
 } call_data;
 
+grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
+    grpc_call_element *call_elem) {
+  grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
+  return scc == CANCELLED_CALL ? NULL : scc;
+}
+
 static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
   GPR_TIMER_BEGIN("add_waiting_locked", 0);
   if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
@@ -645,52 +682,32 @@
   GRPC_ERROR_UNREF(error);
 }
 
-typedef struct {
-  grpc_transport_stream_op **ops;
-  size_t nops;
-  grpc_subchannel_call *call;
-} retry_ops_args;
-
-static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
-  retry_ops_args *a = args;
-  size_t i;
-  for (i = 0; i < a->nops; i++) {
-    grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]);
-  }
-  GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
-  gpr_free(a->ops);
-  gpr_free(a);
-}
-
 static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
   if (calld->waiting_ops_count == 0) {
     return;
   }
 
-  retry_ops_args *a = gpr_malloc(sizeof(*a));
-  a->ops = calld->waiting_ops;
-  a->nops = calld->waiting_ops_count;
-  a->call = GET_CALL(calld);
-  if (a->call == CANCELLED_CALL) {
-    gpr_free(a);
+  grpc_subchannel_call *call = GET_CALL(calld);
+  grpc_transport_stream_op **ops = calld->waiting_ops;
+  size_t nops = calld->waiting_ops_count;
+  if (call == CANCELLED_CALL) {
     fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
     return;
   }
   calld->waiting_ops = NULL;
   calld->waiting_ops_count = 0;
   calld->waiting_ops_capacity = 0;
-  GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
-  grpc_closure_sched(
-      exec_ctx, grpc_closure_create(retry_ops, a, grpc_schedule_on_exec_ctx),
-      GRPC_ERROR_NONE);
+  for (size_t i = 0; i < nops; i++) {
+    grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
+  }
+  gpr_free(ops);
 }
 
-static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
-                             grpc_error *error) {
+static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                    grpc_error *error) {
   grpc_call_element *elem = arg;
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
-  gpr_mu_lock(&calld->mu);
   GPR_ASSERT(calld->creation_phase ==
              GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
   grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
@@ -726,7 +743,6 @@
                       (gpr_atm)(uintptr_t)subchannel_call);
     retry_waiting_locked(exec_ctx, calld);
   }
-  gpr_mu_unlock(&calld->mu);
   GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
 }
 
@@ -752,37 +768,35 @@
 /** Return true if subchannel is available immediately (in which case on_ready
     should not be called), or false otherwise (in which case on_ready should be
     called when the subchannel is available). */
-static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                            grpc_metadata_batch *initial_metadata,
-                            uint32_t initial_metadata_flags,
-                            grpc_connected_subchannel **connected_subchannel,
-                            grpc_closure *on_ready, grpc_error *error);
+static bool pick_subchannel_locked(
+    grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+    grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
+    grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
+    grpc_error *error);
 
-static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
-                             grpc_error *error) {
+static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                    grpc_error *error) {
   continue_picking_args *cpa = arg;
   if (cpa->connected_subchannel == NULL) {
     /* cancelled, do nothing */
   } else if (error != GRPC_ERROR_NONE) {
     grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
   } else {
-    call_data *calld = cpa->elem->call_data;
-    gpr_mu_lock(&calld->mu);
-    if (pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
-                        cpa->initial_metadata_flags, cpa->connected_subchannel,
-                        cpa->on_ready, GRPC_ERROR_NONE)) {
+    if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
+                               cpa->initial_metadata_flags,
+                               cpa->connected_subchannel, cpa->on_ready,
+                               GRPC_ERROR_NONE)) {
       grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
     }
-    gpr_mu_unlock(&calld->mu);
   }
   gpr_free(cpa);
 }
 
-static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                            grpc_metadata_batch *initial_metadata,
-                            uint32_t initial_metadata_flags,
-                            grpc_connected_subchannel **connected_subchannel,
-                            grpc_closure *on_ready, grpc_error *error) {
+static bool pick_subchannel_locked(
+    grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+    grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
+    grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
+    grpc_error *error) {
   GPR_TIMER_BEGIN("pick_subchannel", 0);
 
   channel_data *chand = elem->channel_data;
@@ -792,11 +806,11 @@
 
   GPR_ASSERT(connected_subchannel);
 
-  gpr_mu_lock(&chand->mu);
   if (initial_metadata == NULL) {
     if (chand->lb_policy != NULL) {
-      grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
-                                 connected_subchannel, GRPC_ERROR_REF(error));
+      grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
+                                        connected_subchannel,
+                                        GRPC_ERROR_REF(error));
     }
     for (closure = chand->waiting_for_config_closures.head; closure != NULL;
          closure = closure->next_data.next) {
@@ -808,7 +822,6 @@
             GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
       }
     }
-    gpr_mu_unlock(&chand->mu);
     GPR_TIMER_END("pick_subchannel", 0);
     GRPC_ERROR_UNREF(error);
     return true;
@@ -817,7 +830,6 @@
   if (chand->lb_policy != NULL) {
     grpc_lb_policy *lb_policy = chand->lb_policy;
     GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
-    gpr_mu_unlock(&chand->mu);
     // If the application explicitly set wait_for_ready, use that.
     // Otherwise, if the service config specified a value for this
     // method, use that.
@@ -837,7 +849,7 @@
     const grpc_lb_policy_pick_args inputs = {
         initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
         gpr_inf_future(GPR_CLOCK_MONOTONIC)};
-    const bool result = grpc_lb_policy_pick(
+    const bool result = grpc_lb_policy_pick_locked(
         exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
     GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
     GPR_TIMER_END("pick_subchannel", 0);
@@ -846,8 +858,9 @@
   if (chand->resolver != NULL && !chand->started_resolving) {
     chand->started_resolving = true;
     GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
-    grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
-                       &chand->on_resolver_result_changed);
+    grpc_resolver_next_locked(exec_ctx, chand->resolver,
+                              &chand->resolver_result,
+                              &chand->on_resolver_result_changed);
   }
   if (chand->resolver != NULL) {
     cpa = gpr_malloc(sizeof(*cpa));
@@ -856,88 +869,66 @@
     cpa->connected_subchannel = connected_subchannel;
     cpa->on_ready = on_ready;
     cpa->elem = elem;
-    grpc_closure_init(&cpa->closure, continue_picking, cpa,
-                      grpc_schedule_on_exec_ctx);
+    grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
+                      grpc_combiner_scheduler(chand->combiner, true));
     grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
                              GRPC_ERROR_NONE);
   } else {
     grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
   }
-  gpr_mu_unlock(&chand->mu);
 
   GPR_TIMER_END("pick_subchannel", 0);
   return false;
 }
 
-// The logic here is fairly complicated, due to (a) the fact that we
-// need to handle the case where we receive the send op before the
-// initial metadata op, and (b) the need for efficiency, especially in
-// the streaming case.
-// TODO(ctiller): Explain this more thoroughly.
-static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
-                                         grpc_call_element *elem,
-                                         grpc_transport_stream_op *op) {
-  call_data *calld = elem->call_data;
+static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
+                                                   grpc_transport_stream_op *op,
+                                                   grpc_call_element *elem) {
   channel_data *chand = elem->channel_data;
-  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
-  /* try to (atomically) get the call */
-  grpc_subchannel_call *call = GET_CALL(calld);
-  GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
-  if (call == CANCELLED_CALL) {
-    grpc_transport_stream_op_finish_with_failure(
-        exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
-    GPR_TIMER_END("cc_start_transport_stream_op", 0);
-    return;
-  }
-  if (call != NULL) {
-    grpc_subchannel_call_process_op(exec_ctx, call, op);
-    GPR_TIMER_END("cc_start_transport_stream_op", 0);
-    return;
-  }
-  /* we failed; lock and figure out what to do */
-  gpr_mu_lock(&calld->mu);
-retry:
+  call_data *calld = elem->call_data;
+  grpc_subchannel_call *call;
+
   /* need to recheck that another thread hasn't set the call */
   call = GET_CALL(calld);
   if (call == CANCELLED_CALL) {
-    gpr_mu_unlock(&calld->mu);
     grpc_transport_stream_op_finish_with_failure(
         exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
-    GPR_TIMER_END("cc_start_transport_stream_op", 0);
+    /* early out */
     return;
   }
   if (call != NULL) {
-    gpr_mu_unlock(&calld->mu);
     grpc_subchannel_call_process_op(exec_ctx, call, op);
-    GPR_TIMER_END("cc_start_transport_stream_op", 0);
+    /* early out */
     return;
   }
   /* if this is a cancellation, then we can raise our cancelled flag */
   if (op->cancel_error != GRPC_ERROR_NONE) {
     if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
                          (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
-      goto retry;
+      /* recurse to retry */
+      start_transport_stream_op_locked_inner(exec_ctx, op, elem);
+      /* early out */
+      return;
     } else {
-      // Stash a copy of cancel_error in our call data, so that we can use
-      // it for subsequent operations.  This ensures that if the call is
-      // cancelled before any ops are passed down (e.g., if the deadline
-      // is in the past when the call starts), we can return the right
-      // error to the caller when the first op does get passed down.
+      /* Stash a copy of cancel_error in our call data, so that we can use
+         it for subsequent operations.  This ensures that if the call is
+         cancelled before any ops are passed down (e.g., if the deadline
+         is in the past when the call starts), we can return the right
+         error to the caller when the first op does get passed down. */
       calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
       switch (calld->creation_phase) {
         case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
           fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
           break;
         case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
-          pick_subchannel(exec_ctx, elem, NULL, 0, &calld->connected_subchannel,
-                          NULL, GRPC_ERROR_REF(op->cancel_error));
+          pick_subchannel_locked(exec_ctx, elem, NULL, 0,
+                                 &calld->connected_subchannel, NULL,
+                                 GRPC_ERROR_REF(op->cancel_error));
           break;
       }
-      gpr_mu_unlock(&calld->mu);
       grpc_transport_stream_op_finish_with_failure(
           exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
-      GPR_TIMER_END("cc_start_transport_stream_op", 0);
+      /* early out */
       return;
     }
   }
@@ -946,16 +937,16 @@
       calld->connected_subchannel == NULL &&
       op->send_initial_metadata != NULL) {
     calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
-    grpc_closure_init(&calld->next_step, subchannel_ready, elem,
-                      grpc_schedule_on_exec_ctx);
+    grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
+                      grpc_combiner_scheduler(chand->combiner, true));
     GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
     /* If a subchannel is not available immediately, the polling entity from
        call_data should be provided to channel_data's interested_parties, so
        that IO of the lb_policy and resolver could be done under it. */
-    if (pick_subchannel(exec_ctx, elem, op->send_initial_metadata,
-                        op->send_initial_metadata_flags,
-                        &calld->connected_subchannel, &calld->next_step,
-                        GRPC_ERROR_NONE)) {
+    if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
+                               op->send_initial_metadata_flags,
+                               &calld->connected_subchannel, &calld->next_step,
+                               GRPC_ERROR_NONE)) {
       calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
       GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
     } else {
@@ -978,31 +969,89 @@
     gpr_atm_rel_store(&calld->subchannel_call,
                       (gpr_atm)(uintptr_t)subchannel_call);
     retry_waiting_locked(exec_ctx, calld);
-    goto retry;
+    /* recurse to retry */
+    start_transport_stream_op_locked_inner(exec_ctx, op, elem);
+    /* early out */
+    return;
   }
   /* nothing to be done but wait */
   add_waiting_locked(calld, op);
-  gpr_mu_unlock(&calld->mu);
+}
+
+static void cc_start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx,
+                                                void *arg,
+                                                grpc_error *error_ignored) {
+  GPR_TIMER_BEGIN("cc_start_transport_stream_op_locked", 0);
+
+  grpc_transport_stream_op *op = arg;
+  grpc_call_element *elem = op->handler_private.args[0];
+  call_data *calld = elem->call_data;
+
+  start_transport_stream_op_locked_inner(exec_ctx, op, elem);
+
+  GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
+                        "start_transport_stream_op");
+  GPR_TIMER_END("cc_start_transport_stream_op_locked", 0);
+}
+
+/* The logic here is fairly complicated, due to (a) the fact that we
+   need to handle the case where we receive the send op before the
+   initial metadata op, and (b) the need for efficiency, especially in
+   the streaming case.
+
+   We use double-checked locking to initially see if initialization has been
+   performed. If it has not, we acquire the combiner and perform initialization.
+   If it has, we proceed on the fast path. */
+static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
+                                         grpc_call_element *elem,
+                                         grpc_transport_stream_op *op) {
+  call_data *calld = elem->call_data;
+  channel_data *chand = elem->channel_data;
+  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
+  grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
+  /* try to (atomically) get the call */
+  grpc_subchannel_call *call = GET_CALL(calld);
+  GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
+  if (call == CANCELLED_CALL) {
+    grpc_transport_stream_op_finish_with_failure(
+        exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
+    GPR_TIMER_END("cc_start_transport_stream_op", 0);
+    /* early out */
+    return;
+  }
+  if (call != NULL) {
+    grpc_subchannel_call_process_op(exec_ctx, call, op);
+    GPR_TIMER_END("cc_start_transport_stream_op", 0);
+    /* early out */
+    return;
+  }
+  /* we failed; lock and figure out what to do */
+  GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
+  op->handler_private.args[0] = elem;
+  grpc_closure_sched(
+      exec_ctx,
+      grpc_closure_init(&op->handler_private.closure,
+                        cc_start_transport_stream_op_locked, op,
+                        grpc_combiner_scheduler(chand->combiner, false)),
+      GRPC_ERROR_NONE);
   GPR_TIMER_END("cc_start_transport_stream_op", 0);
 }
 
 // Gets data from the service config.  Invoked when the resolver returns
 // its initial result.
-static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
-                                grpc_error *error) {
+static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                       grpc_error *error) {
   grpc_call_element *elem = arg;
   channel_data *chand = elem->channel_data;
   call_data *calld = elem->call_data;
   // If this is an error, there's no point in looking at the service config.
   if (error == GRPC_ERROR_NONE) {
     // Get the method config table from channel data.
-    gpr_mu_lock(&chand->mu);
-    grpc_mdstr_hash_table *method_params_table = NULL;
+    grpc_slice_hash_table *method_params_table = NULL;
     if (chand->method_params_table != NULL) {
       method_params_table =
-          grpc_mdstr_hash_table_ref(chand->method_params_table);
+          grpc_slice_hash_table_ref(chand->method_params_table);
     }
-    gpr_mu_unlock(&chand->mu);
     // If the method config table was present, use it.
     if (method_params_table != NULL) {
       const method_parameters *method_params = grpc_method_config_table_get(
@@ -1012,7 +1061,6 @@
             gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
         if (have_method_timeout ||
             method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
-          gpr_mu_lock(&calld->mu);
           if (have_method_timeout) {
             const gpr_timespec per_method_deadline =
                 gpr_time_add(calld->call_start_time, method_params->timeout);
@@ -1026,52 +1074,33 @@
             calld->wait_for_ready_from_service_config =
                 method_params->wait_for_ready;
           }
-          gpr_mu_unlock(&calld->mu);
         }
       }
-      grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
+      grpc_slice_hash_table_unref(exec_ctx, method_params_table);
     }
   }
   GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
 }
 
-/* Constructor for call_data */
-static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
-                                     grpc_call_element *elem,
-                                     grpc_call_element_args *args) {
+static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
+                                               void *arg,
+                                               grpc_error *error_ignored) {
+  grpc_call_element *elem = arg;
   channel_data *chand = elem->channel_data;
   call_data *calld = elem->call_data;
-  // Initialize data members.
-  grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
-  calld->path = GRPC_MDSTR_REF(args->path);
-  calld->call_start_time = args->start_time;
-  calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
-  calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
-  calld->cancel_error = GRPC_ERROR_NONE;
-  gpr_atm_rel_store(&calld->subchannel_call, 0);
-  gpr_mu_init(&calld->mu);
-  calld->connected_subchannel = NULL;
-  calld->waiting_ops = NULL;
-  calld->waiting_ops_count = 0;
-  calld->waiting_ops_capacity = 0;
-  calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
-  calld->owning_call = args->call_stack;
-  calld->pollent = NULL;
   // If the resolver has already returned results, then we can access
   // the service config parameters immediately.  Otherwise, we need to
   // defer that work until the resolver returns an initial result.
   // TODO(roth): This code is almost but not quite identical to the code
   // in read_service_config() above.  It would be nice to find a way to
   // combine them, to avoid having to maintain it twice.
-  gpr_mu_lock(&chand->mu);
   if (chand->lb_policy != NULL) {
     // We already have a resolver result, so check for service config.
     if (chand->method_params_table != NULL) {
-      grpc_mdstr_hash_table *method_params_table =
-          grpc_mdstr_hash_table_ref(chand->method_params_table);
-      gpr_mu_unlock(&chand->mu);
+      grpc_slice_hash_table *method_params_table =
+          grpc_slice_hash_table_ref(chand->method_params_table);
       method_parameters *method_params = grpc_method_config_table_get(
-          exec_ctx, method_params_table, args->path);
+          exec_ctx, method_params_table, calld->path);
       if (method_params != NULL) {
         if (gpr_time_cmp(method_params->timeout,
                          gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
@@ -1084,25 +1113,54 @@
               method_params->wait_for_ready;
         }
       }
-      grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
-    } else {
-      gpr_mu_unlock(&chand->mu);
+      grpc_slice_hash_table_unref(exec_ctx, method_params_table);
     }
   } else {
     // We don't yet have a resolver result, so register a callback to
     // get the service config data once the resolver returns.
     // Take a reference to the call stack to be owned by the callback.
     GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
-    grpc_closure_init(&calld->read_service_config, read_service_config, elem,
-                      grpc_schedule_on_exec_ctx);
+    grpc_closure_init(&calld->read_service_config, read_service_config_locked,
+                      elem, grpc_combiner_scheduler(chand->combiner, false));
     grpc_closure_list_append(&chand->waiting_for_config_closures,
                              &calld->read_service_config, GRPC_ERROR_NONE);
-    gpr_mu_unlock(&chand->mu);
   }
   // Start the deadline timer with the current deadline value.  If we
   // do not yet have service config data, then the timer may be reset
   // later.
   grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
+  GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
+                        "initial_read_service_config");
+}
+
+/* Constructor for call_data */
+static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
+                                     grpc_call_element *elem,
+                                     const grpc_call_element_args *args) {
+  channel_data *chand = elem->channel_data;
+  call_data *calld = elem->call_data;
+  // Initialize data members.
+  grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
+  calld->path = grpc_slice_ref_internal(args->path);
+  calld->call_start_time = args->start_time;
+  calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
+  calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
+  calld->cancel_error = GRPC_ERROR_NONE;
+  gpr_atm_rel_store(&calld->subchannel_call, 0);
+  calld->connected_subchannel = NULL;
+  calld->waiting_ops = NULL;
+  calld->waiting_ops_count = 0;
+  calld->waiting_ops_capacity = 0;
+  calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
+  calld->owning_call = args->call_stack;
+  calld->pollent = NULL;
+  GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
+  grpc_closure_sched(
+      exec_ctx,
+      grpc_closure_init(&calld->read_service_config,
+                        initial_read_service_config_locked, elem,
+                        grpc_combiner_scheduler(chand->combiner, false)),
+      GRPC_ERROR_NONE);
   return GRPC_ERROR_NONE;
 }
 
@@ -1113,14 +1171,13 @@
                                  void *and_free_memory) {
   call_data *calld = elem->call_data;
   grpc_deadline_state_destroy(exec_ctx, elem);
-  GRPC_MDSTR_UNREF(exec_ctx, calld->path);
+  grpc_slice_unref_internal(exec_ctx, calld->path);
   GRPC_ERROR_UNREF(calld->cancel_error);
   grpc_subchannel_call *call = GET_CALL(calld);
   if (call != NULL && call != CANCELLED_CALL) {
     GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
   }
   GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
-  gpr_mu_destroy(&calld->mu);
   GPR_ASSERT(calld->waiting_ops_count == 0);
   if (calld->connected_subchannel != NULL) {
     GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
@@ -1156,26 +1213,37 @@
     "client-channel",
 };
 
+static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                  grpc_error *error_ignored) {
+  channel_data *chand = arg;
+  if (chand->lb_policy != NULL) {
+    grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
+  } else {
+    chand->exit_idle_when_lb_policy_arrives = true;
+    if (!chand->started_resolving && chand->resolver != NULL) {
+      GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
+      chand->started_resolving = true;
+      grpc_resolver_next_locked(exec_ctx, chand->resolver,
+                                &chand->resolver_result,
+                                &chand->on_resolver_result_changed);
+    }
+  }
+  GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
+}
+
 grpc_connectivity_state grpc_client_channel_check_connectivity_state(
     grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
   channel_data *chand = elem->channel_data;
-  grpc_connectivity_state out;
-  gpr_mu_lock(&chand->mu);
-  out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
+  grpc_connectivity_state out =
+      grpc_connectivity_state_check(&chand->state_tracker);
   if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
-    if (chand->lb_policy != NULL) {
-      grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
-    } else {
-      chand->exit_idle_when_lb_policy_arrives = true;
-      if (!chand->started_resolving && chand->resolver != NULL) {
-        GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
-        chand->started_resolving = true;
-        grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
-                           &chand->on_resolver_result_changed);
-      }
-    }
+    GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
+    grpc_closure_sched(
+        exec_ctx,
+        grpc_closure_create(try_to_connect_locked, chand,
+                            grpc_combiner_scheduler(chand->combiner, false)),
+        GRPC_ERROR_NONE);
   }
-  gpr_mu_unlock(&chand->mu);
   return out;
 }
 
@@ -1183,6 +1251,7 @@
   channel_data *chand;
   grpc_pollset *pollset;
   grpc_closure *on_complete;
+  grpc_connectivity_state *state;
   grpc_closure my_closure;
 } external_connectivity_watcher;
 
@@ -1195,7 +1264,16 @@
   GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
                            "external_connectivity_watcher");
   gpr_free(w);
-  follow_up->cb(exec_ctx, follow_up->cb_arg, error);
+  grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
+}
+
+static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                            grpc_error *error_ignored) {
+  external_connectivity_watcher *w = arg;
+  grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
+                    grpc_schedule_on_exec_ctx);
+  grpc_connectivity_state_notify_on_state_change(
+      exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
 }
 
 void grpc_client_channel_watch_connectivity_state(
@@ -1206,13 +1284,13 @@
   w->chand = chand;
   w->pollset = pollset;
   w->on_complete = on_complete;
+  w->state = state;
   grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
-  grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
-                    grpc_schedule_on_exec_ctx);
   GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
                          "external_connectivity_watcher");
-  gpr_mu_lock(&chand->mu);
-  grpc_connectivity_state_notify_on_state_change(
-      exec_ctx, &chand->state_tracker, state, &w->my_closure);
-  gpr_mu_unlock(&chand->mu);
+  grpc_closure_sched(
+      exec_ctx,
+      grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
+                        grpc_combiner_scheduler(chand->combiner, true)),
+      GRPC_ERROR_NONE);
 }
diff --git a/src/core/ext/client_channel/client_channel.h b/src/core/ext/client_channel/client_channel.h
index f02587d..5e6e64e 100644
--- a/src/core/ext/client_channel/client_channel.h
+++ b/src/core/ext/client_channel/client_channel.h
@@ -57,4 +57,8 @@
     grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
     grpc_connectivity_state *state, grpc_closure *on_complete);
 
+/* Debug helper: pull the subchannel call from a call stack element */
+grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
+    grpc_call_element *elem);
+
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CLIENT_CHANNEL_H */
diff --git a/src/core/ext/client_channel/client_channel_plugin.c b/src/core/ext/client_channel/client_channel_plugin.c
index d50bba6..6f9df3e 100644
--- a/src/core/ext/client_channel/client_channel_plugin.c
+++ b/src/core/ext/client_channel/client_channel_plugin.c
@@ -39,7 +39,9 @@
 
 #include "src/core/ext/client_channel/client_channel.h"
 #include "src/core/ext/client_channel/http_connect_handshaker.h"
+#include "src/core/ext/client_channel/http_proxy.h"
 #include "src/core/ext/client_channel/lb_policy_registry.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/ext/client_channel/subchannel_index.h"
 #include "src/core/lib/surface/channel_init.h"
@@ -80,6 +82,8 @@
 void grpc_client_channel_init(void) {
   grpc_lb_policy_registry_init();
   grpc_resolver_registry_init();
+  grpc_proxy_mapper_registry_init();
+  grpc_register_http_proxy_mapper();
   grpc_subchannel_index_init();
   grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN,
                                    set_default_host_if_unset, NULL);
@@ -91,6 +95,7 @@
 void grpc_client_channel_shutdown(void) {
   grpc_subchannel_index_shutdown();
   grpc_channel_init_shutdown();
+  grpc_proxy_mapper_registry_shutdown();
   grpc_resolver_registry_shutdown();
   grpc_lb_policy_registry_shutdown();
 }
diff --git a/src/core/ext/client_channel/connector.c b/src/core/ext/client_channel/connector.c
index 0582e5b..7a720fd 100644
--- a/src/core/ext/client_channel/connector.c
+++ b/src/core/ext/client_channel/connector.c
@@ -49,7 +49,7 @@
   connector->vtable->connect(exec_ctx, connector, in_args, out_args, notify);
 }
 
-void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx,
-                             grpc_connector* connector) {
-  connector->vtable->shutdown(exec_ctx, connector);
+void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx, grpc_connector* connector,
+                             grpc_error* why) {
+  connector->vtable->shutdown(exec_ctx, connector, why);
 }
diff --git a/src/core/ext/client_channel/connector.h b/src/core/ext/client_channel/connector.h
index 395f89b..9bff41f 100644
--- a/src/core/ext/client_channel/connector.h
+++ b/src/core/ext/client_channel/connector.h
@@ -68,7 +68,8 @@
   void (*ref)(grpc_connector *connector);
   void (*unref)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
   /** Implementation of grpc_connector_shutdown */
-  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
+  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
+                   grpc_error *why);
   /** Implementation of grpc_connector_connect */
   void (*connect)(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
                   const grpc_connect_in_args *in_args,
@@ -83,7 +84,7 @@
                             grpc_connect_out_args *out_args,
                             grpc_closure *notify);
 /** Cancel any pending connection */
-void grpc_connector_shutdown(grpc_exec_ctx *exec_ctx,
-                             grpc_connector *connector);
+void grpc_connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
+                             grpc_error *why);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CONNECTOR_H */
diff --git a/src/core/ext/client_channel/http_connect_handshaker.c b/src/core/ext/client_channel/http_connect_handshaker.c
index fba3256..58ab233 100644
--- a/src/core/ext/client_channel/http_connect_handshaker.c
+++ b/src/core/ext/client_channel/http_connect_handshaker.c
@@ -49,15 +49,12 @@
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
 
 typedef struct http_connect_handshaker {
   // Base class.  Must be first.
   grpc_handshaker base;
 
-  char* proxy_server;
-  grpc_http_header* headers;
-  size_t num_headers;
-
   gpr_refcount refcount;
   gpr_mu mu;
 
@@ -91,12 +88,6 @@
                                          handshaker->read_buffer_to_destroy);
       gpr_free(handshaker->read_buffer_to_destroy);
     }
-    gpr_free(handshaker->proxy_server);
-    for (size_t i = 0; i < handshaker->num_headers; ++i) {
-      gpr_free(handshaker->headers[i].key);
-      gpr_free(handshaker->headers[i].value);
-    }
-    gpr_free(handshaker->headers);
     grpc_slice_buffer_destroy_internal(exec_ctx, &handshaker->write_buffer);
     grpc_http_parser_destroy(&handshaker->http_parser);
     grpc_http_response_destroy(&handshaker->http_response);
@@ -132,7 +123,8 @@
     // before destroying them, even if we know that there are no
     // pending read/write callbacks.  This should be fixed, at which
     // point this can be removed.
-    grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint);
+    grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint,
+                           GRPC_ERROR_REF(error));
     // Not shutting down, so the handshake failed.  Clean up before
     // invoking the callback.
     cleanup_args_for_failure_locked(exec_ctx, handshaker);
@@ -260,15 +252,18 @@
 }
 
 static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
-                                             grpc_handshaker* handshaker_in) {
+                                             grpc_handshaker* handshaker_in,
+                                             grpc_error* why) {
   http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in;
   gpr_mu_lock(&handshaker->mu);
   if (!handshaker->shutdown) {
     handshaker->shutdown = true;
-    grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint);
+    grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint,
+                           GRPC_ERROR_REF(why));
     cleanup_args_for_failure_locked(exec_ctx, handshaker);
   }
   gpr_mu_unlock(&handshaker->mu);
+  GRPC_ERROR_UNREF(why);
 }
 
 static void http_connect_handshaker_do_handshake(
@@ -276,64 +271,88 @@
     grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done,
     grpc_handshaker_args* args) {
   http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in;
-  // Get server name from channel args.
-  const grpc_arg* arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
-  GPR_ASSERT(arg != NULL);
+  // Check for HTTP CONNECT channel arg.
+  // If not found, invoke on_handshake_done without doing anything.
+  const grpc_arg* arg =
+      grpc_channel_args_find(args->args, GRPC_ARG_HTTP_CONNECT_SERVER);
+  if (arg == NULL) {
+    // Set shutdown to true so that subsequent calls to
+    // http_connect_handshaker_shutdown() do nothing.
+    gpr_mu_lock(&handshaker->mu);
+    handshaker->shutdown = true;
+    gpr_mu_unlock(&handshaker->mu);
+    grpc_closure_sched(exec_ctx, on_handshake_done, GRPC_ERROR_NONE);
+    return;
+  }
   GPR_ASSERT(arg->type == GRPC_ARG_STRING);
-  char* canonical_uri =
-      grpc_resolver_factory_add_default_prefix_if_needed(arg->value.string);
-  grpc_uri* uri = grpc_uri_parse(canonical_uri, 1);
-  char* server_name = uri->path;
-  if (server_name[0] == '/') ++server_name;
+  char* server_name = arg->value.string;
+  // Get headers from channel args.
+  arg = grpc_channel_args_find(args->args, GRPC_ARG_HTTP_CONNECT_HEADERS);
+  grpc_http_header* headers = NULL;
+  size_t num_headers = 0;
+  char** header_strings = NULL;
+  size_t num_header_strings = 0;
+  if (arg != NULL) {
+    GPR_ASSERT(arg->type == GRPC_ARG_STRING);
+    gpr_string_split(arg->value.string, "\n", &header_strings,
+                     &num_header_strings);
+    headers = gpr_malloc(sizeof(grpc_http_header) * num_header_strings);
+    for (size_t i = 0; i < num_header_strings; ++i) {
+      char* sep = strchr(header_strings[i], ':');
+      if (sep == NULL) {
+        gpr_log(GPR_ERROR, "skipping unparseable HTTP CONNECT header: %s",
+                header_strings[i]);
+        continue;
+      }
+      *sep = '\0';
+      headers[num_headers].key = header_strings[i];
+      headers[num_headers].value = sep + 1;
+      ++num_headers;
+    }
+  }
   // Save state in the handshaker object.
   gpr_mu_lock(&handshaker->mu);
   handshaker->args = args;
   handshaker->on_handshake_done = on_handshake_done;
-  // Send HTTP CONNECT request.
+  // Log connection via proxy.
+  char* proxy_name = grpc_endpoint_get_peer(args->endpoint);
   gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", server_name,
-          handshaker->proxy_server);
+          proxy_name);
+  gpr_free(proxy_name);
+  // Construct HTTP CONNECT request.
   grpc_httpcli_request request;
   memset(&request, 0, sizeof(request));
   request.host = server_name;
   request.http.method = "CONNECT";
   request.http.path = server_name;
-  request.http.hdrs = handshaker->headers;
-  request.http.hdr_count = handshaker->num_headers;
+  request.http.hdrs = headers;
+  request.http.hdr_count = num_headers;
   request.handshaker = &grpc_httpcli_plaintext;
   grpc_slice request_slice = grpc_httpcli_format_connect_request(&request);
   grpc_slice_buffer_add(&handshaker->write_buffer, request_slice);
+  // Clean up.
+  gpr_free(headers);
+  for (size_t i = 0; i < num_header_strings; ++i) {
+    gpr_free(header_strings[i]);
+  }
+  gpr_free(header_strings);
   // Take a new ref to be held by the write callback.
   gpr_ref(&handshaker->refcount);
   grpc_endpoint_write(exec_ctx, args->endpoint, &handshaker->write_buffer,
                       &handshaker->request_done_closure);
   gpr_mu_unlock(&handshaker->mu);
-  // Clean up.
-  gpr_free(canonical_uri);
-  grpc_uri_destroy(uri);
 }
 
 static const grpc_handshaker_vtable http_connect_handshaker_vtable = {
     http_connect_handshaker_destroy, http_connect_handshaker_shutdown,
     http_connect_handshaker_do_handshake};
 
-grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server,
-                                                     grpc_http_header* headers,
-                                                     size_t num_headers) {
-  GPR_ASSERT(proxy_server != NULL);
+static grpc_handshaker* grpc_http_connect_handshaker_create() {
   http_connect_handshaker* handshaker = gpr_malloc(sizeof(*handshaker));
   memset(handshaker, 0, sizeof(*handshaker));
   grpc_handshaker_init(&http_connect_handshaker_vtable, &handshaker->base);
   gpr_mu_init(&handshaker->mu);
   gpr_ref_init(&handshaker->refcount, 1);
-  handshaker->proxy_server = gpr_strdup(proxy_server);
-  if (num_headers > 0) {
-    handshaker->headers = gpr_malloc(sizeof(grpc_http_header) * num_headers);
-    for (size_t i = 0; i < num_headers; ++i) {
-      handshaker->headers[i].key = gpr_strdup(headers[i].key);
-      handshaker->headers[i].value = gpr_strdup(headers[i].value);
-    }
-    handshaker->num_headers = num_headers;
-  }
   grpc_slice_buffer_init(&handshaker->write_buffer);
   grpc_closure_init(&handshaker->request_done_closure, on_write_done,
                     handshaker, grpc_schedule_on_exec_ctx);
@@ -344,30 +363,6 @@
   return &handshaker->base;
 }
 
-char* grpc_get_http_proxy_server() {
-  char* uri_str = gpr_getenv("http_proxy");
-  if (uri_str == NULL) return NULL;
-  grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */);
-  char* proxy_name = NULL;
-  if (uri == NULL || uri->authority == NULL) {
-    gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var");
-    goto done;
-  }
-  if (strcmp(uri->scheme, "http") != 0) {
-    gpr_log(GPR_ERROR, "'%s' scheme not supported in proxy URI", uri->scheme);
-    goto done;
-  }
-  if (strchr(uri->authority, '@') != NULL) {
-    gpr_log(GPR_ERROR, "userinfo not supported in proxy URI");
-    goto done;
-  }
-  proxy_name = gpr_strdup(uri->authority);
-done:
-  gpr_free(uri_str);
-  grpc_uri_destroy(uri);
-  return proxy_name;
-}
-
 //
 // handshaker factory
 //
@@ -375,13 +370,8 @@
 static void handshaker_factory_add_handshakers(
     grpc_exec_ctx* exec_ctx, grpc_handshaker_factory* factory,
     const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr) {
-  char* proxy_name = grpc_get_http_proxy_server();
-  if (proxy_name != NULL) {
-    grpc_handshake_manager_add(
-        handshake_mgr,
-        grpc_http_connect_handshaker_create(proxy_name, NULL, 0));
-    gpr_free(proxy_name);
-  }
+  grpc_handshake_manager_add(handshake_mgr,
+                             grpc_http_connect_handshaker_create());
 }
 
 static void handshaker_factory_destroy(grpc_exec_ctx* exec_ctx,
diff --git a/src/core/ext/client_channel/http_connect_handshaker.h b/src/core/ext/client_channel/http_connect_handshaker.h
index c2e68de..3059d55 100644
--- a/src/core/ext/client_channel/http_connect_handshaker.h
+++ b/src/core/ext/client_channel/http_connect_handshaker.h
@@ -34,17 +34,14 @@
 #ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H
 #define GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H
 
-#include "src/core/lib/channel/handshaker.h"
-#include "src/core/lib/http/parser.h"
+/// Channel arg indicating the server in HTTP CONNECT request (string).
+/// The presence of this arg triggers the use of HTTP CONNECT.
+#define GRPC_ARG_HTTP_CONNECT_SERVER "grpc.http_connect_server"
 
-/// Creates a new HTTP CONNECT handshaker.
-grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server,
-                                                     grpc_http_header* headers,
-                                                     size_t num_headers);
-
-/// Returns the name of the proxy to use, or NULL if no proxy is configured.
-/// Caller takes ownership of result.
-char* grpc_get_http_proxy_server();
+/// Channel arg indicating HTTP CONNECT headers (string).
+/// Multiple headers are separated by newlines.  Key/value pairs are
+/// seperated by colons.
+#define GRPC_ARG_HTTP_CONNECT_HEADERS "grpc.http_connect_headers"
 
 /// Registers handshaker factory.
 void grpc_http_connect_register_handshaker_factory();
diff --git a/src/core/ext/client_channel/http_proxy.c b/src/core/ext/client_channel/http_proxy.c
new file mode 100644
index 0000000..bbe4ff5
--- /dev/null
+++ b/src/core/ext/client_channel/http_proxy.c
@@ -0,0 +1,123 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/ext/client_channel/http_proxy.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/client_channel/http_connect_handshaker.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
+#include "src/core/ext/client_channel/uri_parser.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/support/env.h"
+
+static char* grpc_get_http_proxy_server() {
+  char* uri_str = gpr_getenv("http_proxy");
+  if (uri_str == NULL) return NULL;
+  grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */);
+  char* proxy_name = NULL;
+  if (uri == NULL || uri->authority == NULL) {
+    gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var");
+    goto done;
+  }
+  if (strcmp(uri->scheme, "http") != 0) {
+    gpr_log(GPR_ERROR, "'%s' scheme not supported in proxy URI", uri->scheme);
+    goto done;
+  }
+  if (strchr(uri->authority, '@') != NULL) {
+    gpr_log(GPR_ERROR, "userinfo not supported in proxy URI");
+    goto done;
+  }
+  proxy_name = gpr_strdup(uri->authority);
+done:
+  gpr_free(uri_str);
+  grpc_uri_destroy(uri);
+  return proxy_name;
+}
+
+static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+                                  grpc_proxy_mapper* mapper,
+                                  const char* server_uri,
+                                  const grpc_channel_args* args,
+                                  char** name_to_resolve,
+                                  grpc_channel_args** new_args) {
+  *name_to_resolve = grpc_get_http_proxy_server();
+  if (*name_to_resolve == NULL) return false;
+  grpc_uri* uri = grpc_uri_parse(server_uri, false /* suppress_errors */);
+  if (uri == NULL || uri->path[0] == '\0') {
+    gpr_log(GPR_ERROR,
+            "'http_proxy' environment variable set, but cannot "
+            "parse server URI '%s' -- not using proxy",
+            server_uri);
+    if (uri != NULL) grpc_uri_destroy(uri);
+    return false;
+  }
+  if (strcmp(uri->scheme, "unix") == 0) {
+    gpr_log(GPR_INFO, "not using proxy for Unix domain socket '%s'",
+            server_uri);
+    grpc_uri_destroy(uri);
+    return false;
+  }
+  grpc_arg new_arg;
+  new_arg.key = GRPC_ARG_HTTP_CONNECT_SERVER;
+  new_arg.type = GRPC_ARG_STRING;
+  new_arg.value.string = uri->path[0] == '/' ? uri->path + 1 : uri->path;
+  *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
+  grpc_uri_destroy(uri);
+  return true;
+}
+
+static bool proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+                                     grpc_proxy_mapper* mapper,
+                                     const grpc_resolved_address* address,
+                                     const grpc_channel_args* args,
+                                     grpc_resolved_address** new_address,
+                                     grpc_channel_args** new_args) {
+  return false;
+}
+
+static void proxy_mapper_destroy(grpc_proxy_mapper* mapper) {}
+
+static const grpc_proxy_mapper_vtable proxy_mapper_vtable = {
+    proxy_mapper_map_name, proxy_mapper_map_address, proxy_mapper_destroy};
+
+static grpc_proxy_mapper proxy_mapper = {&proxy_mapper_vtable};
+
+void grpc_register_http_proxy_mapper() {
+  grpc_proxy_mapper_register(true /* at_start */, &proxy_mapper);
+}
diff --git a/src/core/ext/client_channel/http_proxy.h b/src/core/ext/client_channel/http_proxy.h
new file mode 100644
index 0000000..c8882b1
--- /dev/null
+++ b/src/core/ext/client_channel/http_proxy.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H
+#define GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H
+
+void grpc_register_http_proxy_mapper();
+
+#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H */
diff --git a/src/core/ext/client_channel/lb_policy.c b/src/core/ext/client_channel/lb_policy.c
index 45ee72e..aba51ad 100644
--- a/src/core/ext/client_channel/lb_policy.c
+++ b/src/core/ext/client_channel/lb_policy.c
@@ -32,14 +32,17 @@
  */
 
 #include "src/core/ext/client_channel/lb_policy.h"
+#include "src/core/lib/iomgr/combiner.h"
 
 #define WEAK_REF_BITS 16
 
 void grpc_lb_policy_init(grpc_lb_policy *policy,
-                         const grpc_lb_policy_vtable *vtable) {
+                         const grpc_lb_policy_vtable *vtable,
+                         grpc_combiner *combiner) {
   policy->vtable = vtable;
   gpr_atm_no_barrier_store(&policy->ref_pair, 1 << WEAK_REF_BITS);
   policy->interested_parties = grpc_pollset_set_create();
+  policy->combiner = GRPC_COMBINER_REF(combiner, "lb_policy");
 }
 
 #ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
@@ -71,6 +74,13 @@
   ref_mutate(policy, 1 << WEAK_REF_BITS, 0 REF_MUTATE_PASS_ARGS("STRONG_REF"));
 }
 
+static void shutdown_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                            grpc_error *error) {
+  grpc_lb_policy *policy = arg;
+  policy->vtable->shutdown_locked(exec_ctx, policy);
+  GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, policy, "strong-unref");
+}
+
 void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx,
                           grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
   gpr_atm old_val =
@@ -79,10 +89,15 @@
   gpr_atm mask = ~(gpr_atm)((1 << WEAK_REF_BITS) - 1);
   gpr_atm check = 1 << WEAK_REF_BITS;
   if ((old_val & mask) == check) {
-    policy->vtable->shutdown(exec_ctx, policy);
+    grpc_closure_sched(
+        exec_ctx,
+        grpc_closure_create(shutdown_locked, policy,
+                            grpc_combiner_scheduler(policy->combiner, false)),
+        GRPC_ERROR_NONE);
+  } else {
+    grpc_lb_policy_weak_unref(exec_ctx,
+                              policy REF_FUNC_PASS_ARGS("strong-unref"));
   }
-  grpc_lb_policy_weak_unref(exec_ctx,
-                            policy REF_FUNC_PASS_ARGS("strong-unref"));
 }
 
 void grpc_lb_policy_weak_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
@@ -94,53 +109,59 @@
   gpr_atm old_val =
       ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF"));
   if (old_val == 1) {
-    grpc_pollset_set_destroy(policy->interested_parties);
+    grpc_pollset_set_destroy(exec_ctx, policy->interested_parties);
+    grpc_combiner *combiner = policy->combiner;
     policy->vtable->destroy(exec_ctx, policy);
+    GRPC_COMBINER_UNREF(exec_ctx, combiner, "lb_policy");
   }
 }
 
-int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                        const grpc_lb_policy_pick_args *pick_args,
-                        grpc_connected_subchannel **target, void **user_data,
-                        grpc_closure *on_complete) {
-  return policy->vtable->pick(exec_ctx, policy, pick_args, target, user_data,
-                              on_complete);
+int grpc_lb_policy_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                               const grpc_lb_policy_pick_args *pick_args,
+                               grpc_connected_subchannel **target,
+                               void **user_data, grpc_closure *on_complete) {
+  return policy->vtable->pick_locked(exec_ctx, policy, pick_args, target,
+                                     user_data, on_complete);
 }
 
-void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                                grpc_connected_subchannel **target,
-                                grpc_error *error) {
-  policy->vtable->cancel_pick(exec_ctx, policy, target, error);
+void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx *exec_ctx,
+                                       grpc_lb_policy *policy,
+                                       grpc_connected_subchannel **target,
+                                       grpc_error *error) {
+  policy->vtable->cancel_pick_locked(exec_ctx, policy, target, error);
 }
 
-void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
-                                 grpc_lb_policy *policy,
-                                 uint32_t initial_metadata_flags_mask,
-                                 uint32_t initial_metadata_flags_eq,
-                                 grpc_error *error) {
-  policy->vtable->cancel_picks(exec_ctx, policy, initial_metadata_flags_mask,
-                               initial_metadata_flags_eq, error);
+void grpc_lb_policy_cancel_picks_locked(grpc_exec_ctx *exec_ctx,
+                                        grpc_lb_policy *policy,
+                                        uint32_t initial_metadata_flags_mask,
+                                        uint32_t initial_metadata_flags_eq,
+                                        grpc_error *error) {
+  policy->vtable->cancel_picks_locked(exec_ctx, policy,
+                                      initial_metadata_flags_mask,
+                                      initial_metadata_flags_eq, error);
 }
 
-void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
-  policy->vtable->exit_idle(exec_ctx, policy);
+void grpc_lb_policy_exit_idle_locked(grpc_exec_ctx *exec_ctx,
+                                     grpc_lb_policy *policy) {
+  policy->vtable->exit_idle_locked(exec_ctx, policy);
 }
 
-void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                             grpc_closure *closure) {
-  policy->vtable->ping_one(exec_ctx, policy, closure);
+void grpc_lb_policy_ping_one_locked(grpc_exec_ctx *exec_ctx,
+                                    grpc_lb_policy *policy,
+                                    grpc_closure *closure) {
+  policy->vtable->ping_one_locked(exec_ctx, policy, closure);
 }
 
-void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
-                                           grpc_lb_policy *policy,
-                                           grpc_connectivity_state *state,
-                                           grpc_closure *closure) {
-  policy->vtable->notify_on_state_change(exec_ctx, policy, state, closure);
+void grpc_lb_policy_notify_on_state_change_locked(
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+    grpc_connectivity_state *state, grpc_closure *closure) {
+  policy->vtable->notify_on_state_change_locked(exec_ctx, policy, state,
+                                                closure);
 }
 
-grpc_connectivity_state grpc_lb_policy_check_connectivity(
+grpc_connectivity_state grpc_lb_policy_check_connectivity_locked(
     grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
     grpc_error **connectivity_error) {
-  return policy->vtable->check_connectivity(exec_ctx, policy,
-                                            connectivity_error);
+  return policy->vtable->check_connectivity_locked(exec_ctx, policy,
+                                                   connectivity_error);
 }
diff --git a/src/core/ext/client_channel/lb_policy.h b/src/core/ext/client_channel/lb_policy.h
index 120c641..3405709 100644
--- a/src/core/ext/client_channel/lb_policy.h
+++ b/src/core/ext/client_channel/lb_policy.h
@@ -51,6 +51,8 @@
   gpr_atm ref_pair;
   /* owned pointer to interested parties in load balancing decisions */
   grpc_pollset_set *interested_parties;
+  /* combiner under which lb_policy actions take place */
+  grpc_combiner *combiner;
 };
 
 /** Extra arguments for an LB pick */
@@ -69,42 +71,44 @@
 
 struct grpc_lb_policy_vtable {
   void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
-  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+  void (*shutdown_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
 
   /** \see grpc_lb_policy_pick */
-  int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-              const grpc_lb_policy_pick_args *pick_args,
-              grpc_connected_subchannel **target, void **user_data,
-              grpc_closure *on_complete);
+  int (*pick_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                     const grpc_lb_policy_pick_args *pick_args,
+                     grpc_connected_subchannel **target, void **user_data,
+                     grpc_closure *on_complete);
 
   /** \see grpc_lb_policy_cancel_pick */
-  void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                      grpc_connected_subchannel **target, grpc_error *error);
+  void (*cancel_pick_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                             grpc_connected_subchannel **target,
+                             grpc_error *error);
 
   /** \see grpc_lb_policy_cancel_picks */
-  void (*cancel_picks)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                       uint32_t initial_metadata_flags_mask,
-                       uint32_t initial_metadata_flags_eq, grpc_error *error);
+  void (*cancel_picks_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                              uint32_t initial_metadata_flags_mask,
+                              uint32_t initial_metadata_flags_eq,
+                              grpc_error *error);
 
   /** \see grpc_lb_policy_ping_one */
-  void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                   grpc_closure *closure);
+  void (*ping_one_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                          grpc_closure *closure);
 
   /** Try to enter a READY connectivity state */
-  void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+  void (*exit_idle_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
 
   /** check the current connectivity of the lb_policy */
-  grpc_connectivity_state (*check_connectivity)(
+  grpc_connectivity_state (*check_connectivity_locked)(
       grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
       grpc_error **connectivity_error);
 
   /** call notify when the connectivity state of a channel changes from *state.
       Updates *state with the new state of the policy. Calling with a NULL \a
       state cancels the subscription.  */
-  void (*notify_on_state_change)(grpc_exec_ctx *exec_ctx,
-                                 grpc_lb_policy *policy,
-                                 grpc_connectivity_state *state,
-                                 grpc_closure *closure);
+  void (*notify_on_state_change_locked)(grpc_exec_ctx *exec_ctx,
+                                        grpc_lb_policy *policy,
+                                        grpc_connectivity_state *state,
+                                        grpc_closure *closure);
 };
 
 /*#define GRPC_LB_POLICY_REFCOUNT_DEBUG*/
@@ -144,7 +148,8 @@
 
 /** called by concrete implementations to initialize the base struct */
 void grpc_lb_policy_init(grpc_lb_policy *policy,
-                         const grpc_lb_policy_vtable *vtable);
+                         const grpc_lb_policy_vtable *vtable,
+                         grpc_combiner *combiner);
 
 /** Finds an appropriate subchannel for a call, based on \a pick_args.
 
@@ -159,43 +164,45 @@
 
     Any IO should be done under the \a interested_parties \a grpc_pollset_set
     in the \a grpc_lb_policy struct. */
-int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                        const grpc_lb_policy_pick_args *pick_args,
-                        grpc_connected_subchannel **target, void **user_data,
-                        grpc_closure *on_complete);
+int grpc_lb_policy_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                               const grpc_lb_policy_pick_args *pick_args,
+                               grpc_connected_subchannel **target,
+                               void **user_data, grpc_closure *on_complete);
 
 /** Perform a connected subchannel ping (see \a grpc_connected_subchannel_ping)
     against one of the connected subchannels managed by \a policy. */
-void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                             grpc_closure *closure);
+void grpc_lb_policy_ping_one_locked(grpc_exec_ctx *exec_ctx,
+                                    grpc_lb_policy *policy,
+                                    grpc_closure *closure);
 
 /** Cancel picks for \a target.
     The \a on_complete callback of the pending picks will be invoked with \a
     *target set to NULL. */
-void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                                grpc_connected_subchannel **target,
-                                grpc_error *error);
+void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx *exec_ctx,
+                                       grpc_lb_policy *policy,
+                                       grpc_connected_subchannel **target,
+                                       grpc_error *error);
 
 /** Cancel all pending picks for which their \a initial_metadata_flags (as given
     in the call to \a grpc_lb_policy_pick) matches \a initial_metadata_flags_eq
     when AND'd with \a initial_metadata_flags_mask */
-void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
-                                 grpc_lb_policy *policy,
-                                 uint32_t initial_metadata_flags_mask,
-                                 uint32_t initial_metadata_flags_eq,
-                                 grpc_error *error);
+void grpc_lb_policy_cancel_picks_locked(grpc_exec_ctx *exec_ctx,
+                                        grpc_lb_policy *policy,
+                                        uint32_t initial_metadata_flags_mask,
+                                        uint32_t initial_metadata_flags_eq,
+                                        grpc_error *error);
 
 /** Try to enter a READY connectivity state */
-void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+void grpc_lb_policy_exit_idle_locked(grpc_exec_ctx *exec_ctx,
+                                     grpc_lb_policy *policy);
 
 /* Call notify when the connectivity state of a channel changes from \a *state.
  * Updates \a *state with the new state of the policy */
-void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
-                                           grpc_lb_policy *policy,
-                                           grpc_connectivity_state *state,
-                                           grpc_closure *closure);
+void grpc_lb_policy_notify_on_state_change_locked(
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+    grpc_connectivity_state *state, grpc_closure *closure);
 
-grpc_connectivity_state grpc_lb_policy_check_connectivity(
+grpc_connectivity_state grpc_lb_policy_check_connectivity_locked(
     grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
     grpc_error **connectivity_error);
 
diff --git a/src/core/ext/client_channel/lb_policy_factory.h b/src/core/ext/client_channel/lb_policy_factory.h
index 9b8b03f..27c12c0 100644
--- a/src/core/ext/client_channel/lb_policy_factory.h
+++ b/src/core/ext/client_channel/lb_policy_factory.h
@@ -107,6 +107,7 @@
 typedef struct grpc_lb_policy_args {
   grpc_client_channel_factory *client_channel_factory;
   grpc_channel_args *args;
+  grpc_combiner *combiner;
 } grpc_lb_policy_args;
 
 struct grpc_lb_policy_factory_vtable {
diff --git a/src/core/ext/client_channel/parse_address.c b/src/core/ext/client_channel/parse_address.c
index b1d55ad..8e4da03 100644
--- a/src/core/ext/client_channel/parse_address.c
+++ b/src/core/ext/client_channel/parse_address.c
@@ -49,11 +49,12 @@
 
 int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
   struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
-
+  const size_t maxlen = sizeof(un->sun_path);
+  const size_t path_len = strnlen(uri->path, maxlen);
+  if (path_len == maxlen) return 0;
   un->sun_family = AF_UNIX;
   strcpy(un->sun_path, uri->path);
-  resolved_addr->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
-
+  resolved_addr->len = sizeof(*un);
   return 1;
 }
 
diff --git a/src/core/ext/client_channel/proxy_mapper.c b/src/core/ext/client_channel/proxy_mapper.c
new file mode 100644
index 0000000..f92afe8
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper.c
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/ext/client_channel/proxy_mapper.h"
+
+void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
+                            grpc_proxy_mapper* mapper) {
+  mapper->vtable = vtable;
+}
+
+bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+                                grpc_proxy_mapper* mapper,
+                                const char* server_uri,
+                                const grpc_channel_args* args,
+                                char** name_to_resolve,
+                                grpc_channel_args** new_args) {
+  return mapper->vtable->map_name(exec_ctx, mapper, server_uri, args,
+                                  name_to_resolve, new_args);
+}
+
+bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+                                   grpc_proxy_mapper* mapper,
+                                   const grpc_resolved_address* address,
+                                   const grpc_channel_args* args,
+                                   grpc_resolved_address** new_address,
+                                   grpc_channel_args** new_args) {
+  return mapper->vtable->map_address(exec_ctx, mapper, address, args,
+                                     new_address, new_args);
+}
+
+void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) {
+  mapper->vtable->destroy(mapper);
+}
diff --git a/src/core/ext/client_channel/proxy_mapper.h b/src/core/ext/client_channel/proxy_mapper.h
new file mode 100644
index 0000000..6e4607f
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H
+#define GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H
+
+#include <stdbool.h>
+
+#include <grpc/impl/codegen/grpc_types.h>
+
+#include "src/core/lib/iomgr/resolve_address.h"
+
+typedef struct grpc_proxy_mapper grpc_proxy_mapper;
+
+typedef struct {
+  /// Determines the proxy name to resolve for \a server_uri.
+  /// If no proxy is needed, returns false.
+  /// Otherwise, sets \a name_to_resolve, optionally sets \a new_args,
+  /// and returns true.
+  bool (*map_name)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+                   const char* server_uri, const grpc_channel_args* args,
+                   char** name_to_resolve, grpc_channel_args** new_args);
+  /// Determines the proxy address to use to contact \a address.
+  /// If no proxy is needed, returns false.
+  /// Otherwise, sets \a new_address, optionally sets \a new_args, and
+  /// returns true.
+  bool (*map_address)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+                      const grpc_resolved_address* address,
+                      const grpc_channel_args* args,
+                      grpc_resolved_address** new_address,
+                      grpc_channel_args** new_args);
+  /// Destroys \a mapper.
+  void (*destroy)(grpc_proxy_mapper* mapper);
+} grpc_proxy_mapper_vtable;
+
+struct grpc_proxy_mapper {
+  const grpc_proxy_mapper_vtable* vtable;
+};
+
+void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
+                            grpc_proxy_mapper* mapper);
+
+bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+                                grpc_proxy_mapper* mapper,
+                                const char* server_uri,
+                                const grpc_channel_args* args,
+                                char** name_to_resolve,
+                                grpc_channel_args** new_args);
+
+bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+                                   grpc_proxy_mapper* mapper,
+                                   const grpc_resolved_address* address,
+                                   const grpc_channel_args* args,
+                                   grpc_resolved_address** new_address,
+                                   grpc_channel_args** new_args);
+
+void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H */
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.c b/src/core/ext/client_channel/proxy_mapper_registry.c
new file mode 100644
index 0000000..2c44b9d
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper_registry.c
@@ -0,0 +1,133 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
+//
+// grpc_proxy_mapper_list
+//
+
+typedef struct {
+  grpc_proxy_mapper** list;
+  size_t num_mappers;
+} grpc_proxy_mapper_list;
+
+static void grpc_proxy_mapper_list_register(grpc_proxy_mapper_list* list,
+                                            bool at_start,
+                                            grpc_proxy_mapper* mapper) {
+  list->list = gpr_realloc(
+      list->list, (list->num_mappers + 1) * sizeof(grpc_proxy_mapper*));
+  if (at_start) {
+    memmove(list->list + 1, list->list,
+            sizeof(grpc_proxy_mapper*) * list->num_mappers);
+    list->list[0] = mapper;
+  } else {
+    list->list[list->num_mappers] = mapper;
+  }
+  ++list->num_mappers;
+}
+
+static bool grpc_proxy_mapper_list_map_name(grpc_exec_ctx* exec_ctx,
+                                            grpc_proxy_mapper_list* list,
+                                            const char* server_uri,
+                                            const grpc_channel_args* args,
+                                            char** name_to_resolve,
+                                            grpc_channel_args** new_args) {
+  for (size_t i = 0; i < list->num_mappers; ++i) {
+    if (grpc_proxy_mapper_map_name(exec_ctx, list->list[i], server_uri, args,
+                                   name_to_resolve, new_args)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static bool grpc_proxy_mapper_list_map_address(
+    grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list,
+    const grpc_resolved_address* address, const grpc_channel_args* args,
+    grpc_resolved_address** new_address, grpc_channel_args** new_args) {
+  for (size_t i = 0; i < list->num_mappers; ++i) {
+    if (grpc_proxy_mapper_map_address(exec_ctx, list->list[i], address, args,
+                                      new_address, new_args)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static void grpc_proxy_mapper_list_destroy(grpc_proxy_mapper_list* list) {
+  for (size_t i = 0; i < list->num_mappers; ++i) {
+    grpc_proxy_mapper_destroy(list->list[i]);
+  }
+  gpr_free(list->list);
+}
+
+//
+// plugin
+//
+
+static grpc_proxy_mapper_list g_proxy_mapper_list;
+
+void grpc_proxy_mapper_registry_init() {
+  memset(&g_proxy_mapper_list, 0, sizeof(g_proxy_mapper_list));
+}
+
+void grpc_proxy_mapper_registry_shutdown() {
+  grpc_proxy_mapper_list_destroy(&g_proxy_mapper_list);
+}
+
+void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper) {
+  grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper);
+}
+
+bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx,
+                                 const char* server_uri,
+                                 const grpc_channel_args* args,
+                                 char** name_to_resolve,
+                                 grpc_channel_args** new_args) {
+  return grpc_proxy_mapper_list_map_name(exec_ctx, &g_proxy_mapper_list,
+                                         server_uri, args, name_to_resolve,
+                                         new_args);
+}
+bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx,
+                                    const grpc_resolved_address* address,
+                                    const grpc_channel_args* args,
+                                    grpc_resolved_address** new_address,
+                                    grpc_channel_args** new_args) {
+  return grpc_proxy_mapper_list_map_address(
+      exec_ctx, &g_proxy_mapper_list, address, args, new_address, new_args);
+}
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.h b/src/core/ext/client_channel/proxy_mapper_registry.h
new file mode 100644
index 0000000..742b57a
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper_registry.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H
+#define GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H
+
+#include "src/core/ext/client_channel/proxy_mapper.h"
+
+void grpc_proxy_mapper_registry_init();
+void grpc_proxy_mapper_registry_shutdown();
+
+/// Registers a new proxy mapper.  Takes ownership.
+/// If \a at_start is true, the new mapper will be at the beginning of
+/// the list.  Otherwise, it will be added to the end.
+void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper);
+
+bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx,
+                                 const char* server_uri,
+                                 const grpc_channel_args* args,
+                                 char** name_to_resolve,
+                                 grpc_channel_args** new_args);
+
+bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx,
+                                    const grpc_resolved_address* address,
+                                    const grpc_channel_args* args,
+                                    grpc_resolved_address** new_address,
+                                    grpc_channel_args** new_args);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */
diff --git a/src/core/ext/client_channel/resolver.c b/src/core/ext/client_channel/resolver.c
index 2ae4fe8..b1a1faa 100644
--- a/src/core/ext/client_channel/resolver.c
+++ b/src/core/ext/client_channel/resolver.c
@@ -32,10 +32,13 @@
  */
 
 #include "src/core/ext/client_channel/resolver.h"
+#include "src/core/lib/iomgr/combiner.h"
 
 void grpc_resolver_init(grpc_resolver *resolver,
-                        const grpc_resolver_vtable *vtable) {
+                        const grpc_resolver_vtable *vtable,
+                        grpc_combiner *combiner) {
   resolver->vtable = vtable;
+  resolver->combiner = GRPC_COMBINER_REF(combiner, "resolver");
   gpr_ref_init(&resolver->refs, 1);
 }
 
@@ -62,20 +65,24 @@
 void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
 #endif
   if (gpr_unref(&resolver->refs)) {
+    grpc_combiner *combiner = resolver->combiner;
     resolver->vtable->destroy(exec_ctx, resolver);
+    GRPC_COMBINER_UNREF(exec_ctx, combiner, "resolver");
   }
 }
 
-void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
-  resolver->vtable->shutdown(exec_ctx, resolver);
+void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx,
+                                   grpc_resolver *resolver) {
+  resolver->vtable->shutdown_locked(exec_ctx, resolver);
 }
 
-void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                     grpc_resolver *resolver) {
-  resolver->vtable->channel_saw_error(exec_ctx, resolver);
+void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+                                            grpc_resolver *resolver) {
+  resolver->vtable->channel_saw_error_locked(exec_ctx, resolver);
 }
 
-void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                        grpc_channel_args **result, grpc_closure *on_complete) {
-  resolver->vtable->next(exec_ctx, resolver, result, on_complete);
+void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                               grpc_channel_args **result,
+                               grpc_closure *on_complete) {
+  resolver->vtable->next_locked(exec_ctx, resolver, result, on_complete);
 }
diff --git a/src/core/ext/client_channel/resolver.h b/src/core/ext/client_channel/resolver.h
index 96ece92..bbba424 100644
--- a/src/core/ext/client_channel/resolver.h
+++ b/src/core/ext/client_channel/resolver.h
@@ -44,14 +44,16 @@
 struct grpc_resolver {
   const grpc_resolver_vtable *vtable;
   gpr_refcount refs;
+  grpc_combiner *combiner;
 };
 
 struct grpc_resolver_vtable {
   void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
-  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
-  void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
-  void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-               grpc_channel_args **result, grpc_closure *on_complete);
+  void (*shutdown_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+  void (*channel_saw_error_locked)(grpc_exec_ctx *exec_ctx,
+                                   grpc_resolver *resolver);
+  void (*next_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                      grpc_channel_args **result, grpc_closure *on_complete);
 };
 
 #ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
@@ -70,21 +72,30 @@
 #endif
 
 void grpc_resolver_init(grpc_resolver *resolver,
-                        const grpc_resolver_vtable *vtable);
+                        const grpc_resolver_vtable *vtable,
+                        grpc_combiner *combiner);
 
-void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx,
+                                   grpc_resolver *resolver);
 
 /** Notification that the channel has seen an error on some address.
-    Can be used as a hint that re-resolution is desirable soon. */
-void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                     grpc_resolver *resolver);
+    Can be used as a hint that re-resolution is desirable soon.
+
+    Must be called from the combiner passed as a resolver_arg at construction
+    time.*/
+void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+                                            grpc_resolver *resolver);
 
 /** Get the next result from the resolver.  Expected to set \a *result with
     new channel args and then schedule \a on_complete for execution.
 
     If resolution is fatally broken, set \a *result to NULL and
-    schedule \a on_complete. */
-void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                        grpc_channel_args **result, grpc_closure *on_complete);
+    schedule \a on_complete.
+
+    Must be called from the combiner passed as a resolver_arg at construction
+    time.*/
+void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                               grpc_channel_args **result,
+                               grpc_closure *on_complete);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */
diff --git a/src/core/ext/client_channel/resolver_factory.h b/src/core/ext/client_channel/resolver_factory.h
index 3792ddc..e3cd99e 100644
--- a/src/core/ext/client_channel/resolver_factory.h
+++ b/src/core/ext/client_channel/resolver_factory.h
@@ -50,6 +50,7 @@
   grpc_uri *uri;
   const grpc_channel_args *args;
   grpc_pollset_set *pollset_set;
+  grpc_combiner *combiner;
 } grpc_resolver_args;
 
 struct grpc_resolver_factory_vtable {
diff --git a/src/core/ext/client_channel/resolver_registry.c b/src/core/ext/client_channel/resolver_registry.c
index 5110a7c..f8e8bc9 100644
--- a/src/core/ext/client_channel/resolver_registry.c
+++ b/src/core/ext/client_channel/resolver_registry.c
@@ -133,7 +133,8 @@
 
 grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
                                     const grpc_channel_args *args,
-                                    grpc_pollset_set *pollset_set) {
+                                    grpc_pollset_set *pollset_set,
+                                    grpc_combiner *combiner) {
   grpc_uri *uri = NULL;
   char *canonical_target = NULL;
   grpc_resolver_factory *factory =
@@ -144,6 +145,7 @@
   resolver_args.uri = uri;
   resolver_args.args = args;
   resolver_args.pollset_set = pollset_set;
+  resolver_args.combiner = combiner;
   resolver =
       grpc_resolver_factory_create_resolver(exec_ctx, factory, &resolver_args);
   grpc_uri_destroy(uri);
diff --git a/src/core/ext/client_channel/resolver_registry.h b/src/core/ext/client_channel/resolver_registry.h
index a460646..e2c189c 100644
--- a/src/core/ext/client_channel/resolver_registry.h
+++ b/src/core/ext/client_channel/resolver_registry.h
@@ -65,7 +65,8 @@
     should not be NULL. */
 grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
                                     const grpc_channel_args *args,
-                                    grpc_pollset_set *pollset_set);
+                                    grpc_pollset_set *pollset_set,
+                                    grpc_combiner *combiner);
 
 /** Find a resolver factory given a name and return an (owned-by-the-caller)
  *  reference to it */
diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c
index 8bd2845..cb2d2c8 100644
--- a/src/core/ext/client_channel/subchannel.c
+++ b/src/core/ext/client_channel/subchannel.c
@@ -43,6 +43,7 @@
 #include "src/core/ext/client_channel/client_channel.h"
 #include "src/core/ext/client_channel/initial_connect_string.h"
 #include "src/core/ext/client_channel/parse_address.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/client_channel/subchannel_index.h"
 #include "src/core/ext/client_channel/uri_parser.h"
 #include "src/core/lib/channel/channel_args.h"
@@ -216,7 +217,7 @@
   grpc_slice_unref_internal(exec_ctx, c->initial_connect_string);
   grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
   grpc_connector_unref(exec_ctx, c->connector);
-  grpc_pollset_set_destroy(c->pollset_set);
+  grpc_pollset_set_destroy(exec_ctx, c->pollset_set);
   grpc_subchannel_key_destroy(exec_ctx, c->key);
   gpr_free(c);
 }
@@ -272,7 +273,8 @@
   gpr_mu_lock(&c->mu);
   GPR_ASSERT(!c->disconnected);
   c->disconnected = true;
-  grpc_connector_shutdown(exec_ctx, c->connector);
+  grpc_connector_shutdown(exec_ctx, c->connector,
+                          GRPC_ERROR_CREATE("Subchannel disconnected"));
   con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
   if (con != NULL) {
     GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection");
@@ -314,8 +316,7 @@
     return c;
   }
 
-  c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
+  c = gpr_zalloc(sizeof(*c));
   c->key = key;
   gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
   c->connector = connector;
@@ -332,13 +333,24 @@
   grpc_resolved_address *addr = gpr_malloc(sizeof(*addr));
   grpc_get_subchannel_address_arg(args->args, addr);
   grpc_set_initial_connect_string(&addr, &c->initial_connect_string);
-  static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
-  grpc_arg new_arg = grpc_create_subchannel_address_arg(addr);
+  grpc_resolved_address *new_address = NULL;
+  grpc_channel_args *new_args = NULL;
+  if (grpc_proxy_mappers_map_address(exec_ctx, addr, args->args, &new_address,
+                                     &new_args)) {
+    GPR_ASSERT(new_address != NULL);
+    gpr_free(addr);
+    addr = new_address;
+    if (new_args != NULL) c->args = new_args;
+  }
+  if (c->args == NULL) {
+    static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
+    grpc_arg new_arg = grpc_create_subchannel_address_arg(addr);
+    c->args = grpc_channel_args_copy_and_add_and_remove(
+        args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg,
+        1);
+    gpr_free(new_arg.value.string);
+  }
   gpr_free(addr);
-  c->args = grpc_channel_args_copy_and_add_and_remove(
-      args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1);
-  gpr_free(new_arg.value.string);
-
   c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
       &c->root_external_state_watcher;
   grpc_closure_init(&c->connected, subchannel_connected, c,
@@ -406,7 +418,7 @@
                                                            grpc_error **error) {
   grpc_connectivity_state state;
   gpr_mu_lock(&c->mu);
-  state = grpc_connectivity_state_check(&c->state_tracker, error);
+  state = grpc_connectivity_state_get(&c->state_tracker, error);
   gpr_mu_unlock(&c->mu);
   return state;
 }
@@ -425,7 +437,7 @@
   gpr_mu_unlock(&w->subchannel->mu);
   GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
   gpr_free(w);
-  follow_up->cb(exec_ctx, follow_up->cb_arg, error);
+  grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
 }
 
 static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
@@ -625,9 +637,8 @@
   grpc_error *error = grpc_channel_stack_builder_finish(
       exec_ctx, builder, 0, 1, connection_destroy, NULL, (void **)&con);
   if (error != GRPC_ERROR_NONE) {
-    const char *msg = grpc_error_string(error);
-    gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", msg);
-    grpc_error_free_string(msg);
+    gpr_log(GPR_ERROR, "error initializing subchannel stack: %s",
+            grpc_error_string(error));
     GRPC_ERROR_UNREF(error);
     abort(); /* TODO(ctiller): what to do here? */
   }
@@ -692,7 +703,6 @@
 
     const char *errmsg = grpc_error_string(error);
     gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
-    grpc_error_free_string(errmsg);
 
     maybe_start_connecting_locked(exec_ctx, c);
     GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
@@ -751,10 +761,10 @@
 
 grpc_error *grpc_connected_subchannel_create_call(
     grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
-    grpc_polling_entity *pollent, grpc_mdstr *path, gpr_timespec start_time,
+    grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time,
     gpr_timespec deadline, grpc_subchannel_call **call) {
   grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
-  *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
+  *call = gpr_zalloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
   grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
   (*call)->connection = con;  // Ref is added below.
   grpc_error *error =
@@ -763,7 +773,7 @@
   if (error != GRPC_ERROR_NONE) {
     const char *error_string = grpc_error_string(error);
     gpr_log(GPR_ERROR, "error: %s", error_string);
-    grpc_error_free_string(error_string);
+
     gpr_free(*call);
     return error;
   }
@@ -777,7 +787,8 @@
   return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
 }
 
-static void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) {
+static void grpc_uri_to_sockaddr(const char *uri_str,
+                                 grpc_resolved_address *addr) {
   grpc_uri *uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */);
   GPR_ASSERT(uri != NULL);
   if (strcmp(uri->scheme, "ipv4") == 0) {
@@ -792,14 +803,19 @@
 
 void grpc_get_subchannel_address_arg(const grpc_channel_args *args,
                                      grpc_resolved_address *addr) {
+  const char *addr_uri_str = grpc_get_subchannel_address_uri_arg(args);
+  memset(addr, 0, sizeof(*addr));
+  if (*addr_uri_str != '\0') {
+    grpc_uri_to_sockaddr(addr_uri_str, addr);
+  }
+}
+
+const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args) {
   const grpc_arg *addr_arg =
       grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS);
   GPR_ASSERT(addr_arg != NULL);  // Should have been set by LB policy.
   GPR_ASSERT(addr_arg->type == GRPC_ARG_STRING);
-  memset(addr, 0, sizeof(*addr));
-  if (*addr_arg->value.string != '\0') {
-    grpc_uri_to_sockaddr(addr_arg->value.string, addr);
-  }
+  return addr_arg->value.string;
 }
 
 grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr) {
diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h
index 684675e..26ce954 100644
--- a/src/core/ext/client_channel/subchannel.h
+++ b/src/core/ext/client_channel/subchannel.h
@@ -114,7 +114,7 @@
 /** construct a subchannel call */
 grpc_error *grpc_connected_subchannel_create_call(
     grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
-    grpc_polling_entity *pollent, grpc_mdstr *path, gpr_timespec start_time,
+    grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time,
     gpr_timespec deadline, grpc_subchannel_call **subchannel_call);
 
 /** process a transport level op */
@@ -178,6 +178,9 @@
 void grpc_get_subchannel_address_arg(const grpc_channel_args *args,
                                      grpc_resolved_address *addr);
 
+/// Returns the URI string for the address to connect to.
+const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args);
+
 /// Returns a new channel arg encoding the subchannel address as a string.
 /// Caller is responsible for freeing the string.
 grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr);
diff --git a/src/core/ext/client_channel/uri_parser.c b/src/core/ext/client_channel/uri_parser.c
index f8c946b..7dd7b75 100644
--- a/src/core/ext/client_channel/uri_parser.c
+++ b/src/core/ext/client_channel/uri_parser.c
@@ -262,8 +262,7 @@
     fragment_end = i;
   }
 
-  uri = gpr_malloc(sizeof(*uri));
-  memset(uri, 0, sizeof(*uri));
+  uri = gpr_zalloc(sizeof(*uri));
   uri->scheme = copy_component(uri_text, scheme_begin, scheme_end);
   uri->authority = copy_component(uri_text, authority_begin, authority_end);
   uri->path = copy_component(uri_text, path_begin, path_end);
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index 567e65a..aea0fcc 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -112,11 +112,14 @@
 #include "src/core/ext/client_channel/lb_policy_registry.h"
 #include "src/core/ext/client_channel/parse_address.h"
 #include "src/core/ext/lb_policy/grpclb/grpclb.h"
+#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
 #include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/sockaddr.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/slice/slice_hash_table.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/backoff.h"
@@ -135,13 +138,13 @@
 
 /* add lb_token of selected subchannel (address) to the call's initial
  * metadata */
-static void initial_metadata_add_lb_token(
-    grpc_metadata_batch *initial_metadata,
-    grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem *lb_token) {
+static grpc_error *initial_metadata_add_lb_token(
+    grpc_exec_ctx *exec_ctx, grpc_metadata_batch *initial_metadata,
+    grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem lb_token) {
   GPR_ASSERT(lb_token_mdelem_storage != NULL);
-  GPR_ASSERT(lb_token != NULL);
-  grpc_metadata_batch_add_tail(initial_metadata, lb_token_mdelem_storage,
-                               lb_token);
+  GPR_ASSERT(!GRPC_MDISNULL(lb_token));
+  return grpc_metadata_batch_add_tail(exec_ctx, initial_metadata,
+                                      lb_token_mdelem_storage, lb_token);
 }
 
 typedef struct wrapped_rr_closure_arg {
@@ -161,7 +164,7 @@
   grpc_connected_subchannel **target;
 
   /* the LB token associated with the pick */
-  grpc_mdelem *lb_token;
+  grpc_mdelem lb_token;
 
   /* storage for the lb token initial metadata mdelem */
   grpc_linked_mdelem *lb_token_mdelem_storage;
@@ -188,8 +191,8 @@
      * addresses failed to connect). There won't be any user_data/token
      * available */
     if (*wc_arg->target != NULL) {
-      if (wc_arg->lb_token != NULL) {
-        initial_metadata_add_lb_token(wc_arg->initial_metadata,
+      if (!GRPC_MDISNULL(wc_arg->lb_token)) {
+        initial_metadata_add_lb_token(exec_ctx, wc_arg->initial_metadata,
                                       wc_arg->lb_token_mdelem_storage,
                                       GRPC_MDELEM_REF(wc_arg->lb_token));
       } else {
@@ -235,9 +238,7 @@
                              const grpc_lb_policy_pick_args *pick_args,
                              grpc_connected_subchannel **target,
                              grpc_closure *on_complete) {
-  pending_pick *pp = gpr_malloc(sizeof(*pp));
-  memset(pp, 0, sizeof(pending_pick));
-  memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg));
+  pending_pick *pp = gpr_zalloc(sizeof(*pp));
   pp->next = *root;
   pp->pick_args = *pick_args;
   pp->target = target;
@@ -262,9 +263,7 @@
 } pending_ping;
 
 static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
-  pending_ping *pping = gpr_malloc(sizeof(*pping));
-  memset(pping, 0, sizeof(pending_ping));
-  memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg));
+  pending_ping *pping = gpr_zalloc(sizeof(*pping));
   pping->wrapped_notify_arg.wrapped_closure = notify;
   pping->wrapped_notify_arg.free_when_done = pping;
   pping->next = *root;
@@ -283,9 +282,6 @@
   /** base policy: must be first */
   grpc_lb_policy base;
 
-  /** mutex protecting remaining members */
-  gpr_mu mu;
-
   /** who the client is trying to communicate with */
   const char *server_name;
   grpc_client_channel_factory *cc_factory;
@@ -345,8 +341,7 @@
 
   /* call status code and details, set in lb_on_server_status_received() */
   grpc_status_code lb_call_status;
-  char *lb_call_status_details;
-  size_t lb_call_status_details_capacity;
+  grpc_slice lb_call_status_details;
 
   /** LB call retry backoff state */
   gpr_backoff lb_call_backoff_state;
@@ -388,10 +383,14 @@
 
 /* vtable for LB tokens in grpc_lb_addresses. */
 static void *lb_token_copy(void *token) {
-  return token == NULL ? NULL : GRPC_MDELEM_REF(token);
+  return token == NULL
+             ? NULL
+             : (void *)GRPC_MDELEM_REF((grpc_mdelem){(uintptr_t)token}).payload;
 }
 static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) {
-  if (token != NULL) GRPC_MDELEM_UNREF(exec_ctx, token);
+  if (token != NULL) {
+    GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){(uintptr_t)token});
+  }
 }
 static int lb_token_cmp(void *token1, void *token2) {
   if (token1 > token2) return 1;
@@ -459,10 +458,11 @@
           GPR_ARRAY_SIZE(server->load_balance_token);
       const size_t lb_token_length =
           strnlen(server->load_balance_token, lb_token_max_length);
-      grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer(
-          (uint8_t *)server->load_balance_token, lb_token_length);
-      user_data = grpc_mdelem_from_metadata_strings(
-          exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr);
+      grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
+          server->load_balance_token, lb_token_length);
+      user_data = (void *)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
+                                                  lb_token_mdstr)
+                      .payload;
     } else {
       char *uri = grpc_sockaddr_to_uri(&addr);
       gpr_log(GPR_INFO,
@@ -470,7 +470,7 @@
               "be used instead",
               uri);
       gpr_free(uri);
-      user_data = GRPC_MDELEM_LB_TOKEN_EMPTY;
+      user_data = (void *)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
     }
 
     grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
@@ -486,9 +486,8 @@
 static bool update_lb_connectivity_status_locked(
     grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
     grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) {
-  grpc_error *curr_state_error;
-  const grpc_connectivity_state curr_glb_state = grpc_connectivity_state_check(
-      &glb_policy->state_tracker, &curr_state_error);
+  const grpc_connectivity_state curr_glb_state =
+      grpc_connectivity_state_check(&glb_policy->state_tracker);
 
   /* The new connectivity status is a function of the previous one and the new
    * input coming from the status of the RR policy.
@@ -552,9 +551,9 @@
     const grpc_lb_policy_pick_args *pick_args,
     grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
   GPR_ASSERT(rr_policy != NULL);
-  const bool pick_done =
-      grpc_lb_policy_pick(exec_ctx, rr_policy, pick_args, target,
-                          (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure);
+  const bool pick_done = grpc_lb_policy_pick_locked(
+      exec_ctx, rr_policy, pick_args, target, (void **)&wc_arg->lb_token,
+      &wc_arg->wrapper_closure);
   if (pick_done) {
     /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
     if (grpc_lb_glb_trace) {
@@ -564,7 +563,7 @@
     GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
 
     /* add the load reporting initial metadata */
-    initial_metadata_add_lb_token(pick_args->initial_metadata,
+    initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
                                   pick_args->lb_token_mdelem_storage,
                                   GRPC_MDELEM_REF(wc_arg->lb_token));
 
@@ -585,6 +584,7 @@
   grpc_lb_policy_args args;
   memset(&args, 0, sizeof(args));
   args.client_channel_factory = glb_policy->cc_factory;
+  args.combiner = glb_policy->base.combiner;
   grpc_lb_addresses *addresses =
       process_serverlist_locked(exec_ctx, serverlist);
 
@@ -603,8 +603,8 @@
   return rr;
 }
 
-static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                        grpc_error *error);
+static void glb_rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx,
+                                               void *arg, grpc_error *error);
 /* glb_policy->rr_policy may be NULL (initial handover) */
 static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
                                glb_lb_policy *glb_policy) {
@@ -628,8 +628,8 @@
 
   grpc_error *new_rr_state_error = NULL;
   const grpc_connectivity_state new_rr_state =
-      grpc_lb_policy_check_connectivity(exec_ctx, new_rr_policy,
-                                        &new_rr_state_error);
+      grpc_lb_policy_check_connectivity_locked(exec_ctx, new_rr_policy,
+                                               &new_rr_state_error);
   /* Connectivity state is a function of the new RR policy just created */
   const bool replace_old_rr = update_lb_connectivity_status_locked(
       exec_ctx, glb_policy, new_rr_state, new_rr_state_error);
@@ -670,19 +670,19 @@
   /* Allocate the data for the tracking of the new RR policy's connectivity.
    * It'll be deallocated in glb_rr_connectivity_changed() */
   rr_connectivity_data *rr_connectivity =
-      gpr_malloc(sizeof(rr_connectivity_data));
-  memset(rr_connectivity, 0, sizeof(rr_connectivity_data));
-  grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed,
-                    rr_connectivity, grpc_schedule_on_exec_ctx);
+      gpr_zalloc(sizeof(rr_connectivity_data));
+  grpc_closure_init(&rr_connectivity->on_change,
+                    glb_rr_connectivity_changed_locked, rr_connectivity,
+                    grpc_combiner_scheduler(glb_policy->base.combiner, false));
   rr_connectivity->glb_policy = glb_policy;
   rr_connectivity->state = new_rr_state;
 
   /* Subscribe to changes to the connectivity of the new RR */
   GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb");
-  grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
-                                        &rr_connectivity->state,
-                                        &rr_connectivity->on_change);
-  grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
+  grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
+                                               &rr_connectivity->state,
+                                               &rr_connectivity->on_change);
+  grpc_lb_policy_exit_idle_locked(exec_ctx, glb_policy->rr_policy);
 
   /* Update picks and pings in wait */
   pending_pick *pp;
@@ -708,17 +708,16 @@
       gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
               (intptr_t)glb_policy->rr_policy);
     }
-    grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy,
-                            &pping->wrapped_notify_arg.wrapper_closure);
+    grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy,
+                                   &pping->wrapped_notify_arg.wrapper_closure);
   }
 }
 
-static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                        grpc_error *error) {
+static void glb_rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx,
+                                               void *arg, grpc_error *error) {
   rr_connectivity_data *rr_connectivity = arg;
   glb_lb_policy *glb_policy = rr_connectivity->glb_policy;
 
-  gpr_mu_lock(&glb_policy->mu);
   const bool shutting_down = glb_policy->shutting_down;
   bool unref_needed = false;
   GRPC_ERROR_REF(error);
@@ -735,11 +734,10 @@
     update_lb_connectivity_status_locked(exec_ctx, glb_policy,
                                          rr_connectivity->state, error);
     /* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */
-    grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
-                                          &rr_connectivity->state,
-                                          &rr_connectivity->on_change);
+    grpc_lb_policy_notify_on_state_change_locked(
+        exec_ctx, glb_policy->rr_policy, &rr_connectivity->state,
+        &rr_connectivity->on_change);
   }
-  gpr_mu_unlock(&glb_policy->mu);
   if (unref_needed) {
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
                               "rr_connectivity_cb");
@@ -747,6 +745,96 @@
   GRPC_ERROR_UNREF(error);
 }
 
+static void destroy_balancer_name(grpc_exec_ctx *exec_ctx,
+                                  void *balancer_name) {
+  gpr_free(balancer_name);
+}
+
+static void *copy_balancer_name(void *balancer_name) {
+  return gpr_strdup(balancer_name);
+}
+
+static grpc_slice_hash_table_entry targets_info_entry_create(
+    const char *address, const char *balancer_name) {
+  static const grpc_slice_hash_table_vtable vtable = {destroy_balancer_name,
+                                                      copy_balancer_name};
+  grpc_slice_hash_table_entry entry;
+  entry.key = grpc_slice_from_copied_string(address);
+  entry.value = (void *)balancer_name;
+  entry.vtable = &vtable;
+  return entry;
+}
+
+/* Returns the target URI for the LB service whose addresses are in \a
+ * addresses.  Using this URI, a bidirectional streaming channel will be created
+ * for the reception of load balancing updates.
+ *
+ * The output argument \a targets_info will be updated to contain a mapping of
+ * "LB server address" to "balancer name", as reported by the naming system.
+ * This mapping will be propagated via the channel arguments of the
+ * aforementioned LB streaming channel, to be used by the security connector for
+ * secure naming checks. The user is responsible for freeing \a targets_info. */
+static char *get_lb_uri_target_addresses(grpc_exec_ctx *exec_ctx,
+                                         const grpc_lb_addresses *addresses,
+                                         grpc_slice_hash_table **targets_info) {
+  size_t num_grpclb_addrs = 0;
+  for (size_t i = 0; i < addresses->num_addresses; ++i) {
+    if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
+  }
+  /* All input addresses come from a resolver that claims they are LB services.
+   * It's the resolver's responsibility to make sure this policy is only
+   * instantiated and used in that case. Otherwise, something has gone wrong. */
+  GPR_ASSERT(num_grpclb_addrs > 0);
+
+  grpc_slice_hash_table_entry *targets_info_entries =
+      gpr_malloc(sizeof(*targets_info_entries) * num_grpclb_addrs);
+
+  /* construct a target ipvX://ip1:port1,ip2:port2,... from the addresses in \a
+   * addresses */
+  /* TODO(dgq): support mixed ip version */
+  char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
+  size_t addr_index = 0;
+
+  for (size_t i = 0; i < addresses->num_addresses; i++) {
+    if (addresses->addresses[i].user_data != NULL) {
+      gpr_log(GPR_ERROR,
+              "This LB policy doesn't support user data. It will be ignored");
+    }
+    if (addresses->addresses[i].is_balancer) {
+      char *addr_str;
+      GPR_ASSERT(grpc_sockaddr_to_string(
+                     &addr_str, &addresses->addresses[i].address, true) > 0);
+      targets_info_entries[addr_index] = targets_info_entry_create(
+          addr_str, addresses->addresses[i].balancer_name);
+      addr_strs[addr_index++] = addr_str;
+    }
+  }
+  GPR_ASSERT(addr_index == num_grpclb_addrs);
+
+  size_t uri_path_len;
+  char *uri_path = gpr_strjoin_sep((const char **)addr_strs, num_grpclb_addrs,
+                                   ",", &uri_path_len);
+  for (size_t i = 0; i < num_grpclb_addrs; i++) gpr_free(addr_strs[i]);
+  gpr_free(addr_strs);
+
+  char *target_uri_str = NULL;
+  /* TODO(dgq): Don't assume all addresses will share the scheme of the first
+   * one */
+  gpr_asprintf(&target_uri_str, "%s:%s",
+               grpc_sockaddr_get_uri_scheme(&addresses->addresses[0].address),
+               uri_path);
+  gpr_free(uri_path);
+
+  *targets_info =
+      grpc_slice_hash_table_create(num_grpclb_addrs, targets_info_entries);
+  for (size_t i = 0; i < num_grpclb_addrs; i++) {
+    grpc_slice_unref_internal(exec_ctx, targets_info_entries[i].key);
+  }
+  gpr_free(targets_info_entries);
+
+  return target_uri_str;
+}
+
 static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
                                   grpc_lb_policy_factory *factory,
                                   grpc_lb_policy_args *args) {
@@ -767,8 +855,7 @@
   }
   if (num_grpclb_addrs == 0) return NULL;
 
-  glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
-  memset(glb_policy, 0, sizeof(*glb_policy));
+  glb_lb_policy *glb_policy = gpr_zalloc(sizeof(*glb_policy));
 
   /* Get server name. */
   arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
@@ -784,85 +871,29 @@
   }
   grpc_uri_destroy(uri);
 
-  /* All input addresses in addresses come from a resolver that claims
-   * they are LB services. It's the resolver's responsibility to make sure
-   * this policy is only instantiated and used in that case.
-   *
-   * Create a client channel over them to communicate with a LB service */
   glb_policy->cc_factory = args->client_channel_factory;
   glb_policy->args = grpc_channel_args_copy(args->args);
   GPR_ASSERT(glb_policy->cc_factory != NULL);
 
-  /* construct a target from the addresses in args, given in the form
-   * ipvX://ip1:port1,ip2:port2,...
-   * TODO(dgq): support mixed ip version */
-  char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
-  size_t addr_index = 0;
-  for (size_t i = 0; i < addresses->num_addresses; i++) {
-    if (addresses->addresses[i].user_data != NULL) {
-      gpr_log(GPR_ERROR,
-              "This LB policy doesn't support user data. It will be ignored");
-    }
-    if (addresses->addresses[i].is_balancer) {
-      if (addr_index == 0) {
-        addr_strs[addr_index++] =
-            grpc_sockaddr_to_uri(&addresses->addresses[i].address);
-      } else {
-        GPR_ASSERT(grpc_sockaddr_to_string(&addr_strs[addr_index++],
-                                           &addresses->addresses[i].address,
-                                           true) > 0);
-      }
-    }
-  }
-  size_t uri_path_len;
-  char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
-                                         num_grpclb_addrs, ",", &uri_path_len);
-
-  /* Create a channel to talk to the LBs.
-   *
-   * We strip out the channel arg for the LB policy name, since we want
-   * to use the default (pick_first) in this case.
-   *
-   * We also strip out the channel arg for the resolved addresses, since
-   * that will be generated by the name resolver used in the LB channel.
-   * Note that the LB channel will use the sockaddr resolver, so this
-   * won't actually generate a query to DNS (or some other name service).
-   * However, the addresses returned by the sockaddr resolver will have
-   * is_balancer=false, whereas our own addresses have is_balancer=true.
-   * We need the LB channel to return addresses with is_balancer=false
-   * so that it does not wind up recursively using the grpclb LB policy,
-   * as per the special case logic in client_channel.c.
-   *
-   * Finally, we also strip out the channel arg for the server URI,
-   * since that will be different for the LB channel than for the parent
-   * channel.  (The client channel factory will re-add this arg with
-   * the right value.)
-   */
-  static const char *keys_to_remove[] = {
-      GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI};
-  grpc_channel_args *new_args = grpc_channel_args_copy_and_remove(
-      args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove));
-  glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
-      exec_ctx, glb_policy->cc_factory, target_uri_str,
-      GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
-  grpc_channel_args_destroy(exec_ctx, new_args);
-
-  gpr_free(target_uri_str);
-  for (size_t i = 0; i < num_grpclb_addrs; i++) {
-    gpr_free(addr_strs[i]);
-  }
-  gpr_free(addr_strs);
-
+  grpc_slice_hash_table *targets_info = NULL;
+  /* Create a client channel over them to communicate with a LB service */
+  char *lb_service_target_addresses =
+      get_lb_uri_target_addresses(exec_ctx, addresses, &targets_info);
+  grpc_channel_args *lb_channel_args =
+      get_lb_channel_args(exec_ctx, targets_info, args->args);
+  glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel(
+      exec_ctx, lb_service_target_addresses, args->client_channel_factory,
+      lb_channel_args);
+  grpc_slice_hash_table_unref(exec_ctx, targets_info);
+  grpc_channel_args_destroy(exec_ctx, lb_channel_args);
+  gpr_free(lb_service_target_addresses);
   if (glb_policy->lb_channel == NULL) {
     gpr_free(glb_policy);
     return NULL;
   }
-
-  grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable);
-  gpr_mu_init(&glb_policy->mu);
+  grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable, args->combiner);
   grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
                                "grpclb");
-
   return &glb_policy->base;
 }
 
@@ -878,13 +909,11 @@
   if (glb_policy->serverlist != NULL) {
     grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
   }
-  gpr_mu_destroy(&glb_policy->mu);
   gpr_free(glb_policy);
 }
 
-static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void glb_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
-  gpr_mu_lock(&glb_policy->mu);
   glb_policy->shutting_down = true;
 
   pending_pick *pp = glb_policy->pending_picks;
@@ -901,7 +930,6 @@
    * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
    * the cancel, needs to acquire that same lock */
   grpc_call *lb_call = glb_policy->lb_call;
-  gpr_mu_unlock(&glb_policy->mu);
 
   /* glb_policy->lb_call and this local lb_call must be consistent at this point
    * because glb_policy->lb_call is only assigned in lb_call_init_locked as part
@@ -927,11 +955,10 @@
   }
 }
 
-static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                            grpc_connected_subchannel **target,
-                            grpc_error *error) {
+static void glb_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                                   grpc_connected_subchannel **target,
+                                   grpc_error *error) {
   glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
-  gpr_mu_lock(&glb_policy->mu);
   pending_pick *pp = glb_policy->pending_picks;
   glb_policy->pending_picks = NULL;
   while (pp != NULL) {
@@ -947,16 +974,15 @@
     }
     pp = next;
   }
-  gpr_mu_unlock(&glb_policy->mu);
   GRPC_ERROR_UNREF(error);
 }
 
-static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                             uint32_t initial_metadata_flags_mask,
-                             uint32_t initial_metadata_flags_eq,
-                             grpc_error *error) {
+static void glb_cancel_picks_locked(grpc_exec_ctx *exec_ctx,
+                                    grpc_lb_policy *pol,
+                                    uint32_t initial_metadata_flags_mask,
+                                    uint32_t initial_metadata_flags_eq,
+                                    grpc_error *error) {
   glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
-  gpr_mu_lock(&glb_policy->mu);
   pending_pick *pp = glb_policy->pending_picks;
   glb_policy->pending_picks = NULL;
   while (pp != NULL) {
@@ -972,7 +998,6 @@
     }
     pp = next;
   }
-  gpr_mu_unlock(&glb_policy->mu);
   GRPC_ERROR_UNREF(error);
 }
 
@@ -985,19 +1010,17 @@
   query_for_backends_locked(exec_ctx, glb_policy);
 }
 
-static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void glb_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
-  gpr_mu_lock(&glb_policy->mu);
   if (!glb_policy->started_picking) {
     start_picking_locked(exec_ctx, glb_policy);
   }
-  gpr_mu_unlock(&glb_policy->mu);
 }
 
-static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                    const grpc_lb_policy_pick_args *pick_args,
-                    grpc_connected_subchannel **target, void **user_data,
-                    grpc_closure *on_complete) {
+static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                           const grpc_lb_policy_pick_args *pick_args,
+                           grpc_connected_subchannel **target, void **user_data,
+                           grpc_closure *on_complete) {
   if (pick_args->lb_token_mdelem_storage == NULL) {
     *target = NULL;
     grpc_closure_sched(
@@ -1008,7 +1031,6 @@
   }
 
   glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
-  gpr_mu_lock(&glb_policy->mu);
   glb_policy->deadline = pick_args->deadline;
   bool pick_done;
 
@@ -1019,8 +1041,7 @@
     }
     GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
 
-    wrapped_rr_closure_arg *wc_arg = gpr_malloc(sizeof(wrapped_rr_closure_arg));
-    memset(wc_arg, 0, sizeof(wrapped_rr_closure_arg));
+    wrapped_rr_closure_arg *wc_arg = gpr_zalloc(sizeof(wrapped_rr_closure_arg));
 
     grpc_closure_init(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg,
                       grpc_schedule_on_exec_ctx);
@@ -1047,53 +1068,43 @@
     }
     pick_done = false;
   }
-  gpr_mu_unlock(&glb_policy->mu);
   return pick_done;
 }
 
-static grpc_connectivity_state glb_check_connectivity(
+static grpc_connectivity_state glb_check_connectivity_locked(
     grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
     grpc_error **connectivity_error) {
   glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
-  grpc_connectivity_state st;
-  gpr_mu_lock(&glb_policy->mu);
-  st = grpc_connectivity_state_check(&glb_policy->state_tracker,
+  return grpc_connectivity_state_get(&glb_policy->state_tracker,
                                      connectivity_error);
-  gpr_mu_unlock(&glb_policy->mu);
-  return st;
 }
 
-static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                         grpc_closure *closure) {
+static void glb_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                                grpc_closure *closure) {
   glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
-  gpr_mu_lock(&glb_policy->mu);
   if (glb_policy->rr_policy) {
-    grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure);
+    grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy, closure);
   } else {
     add_pending_ping(&glb_policy->pending_pings, closure);
     if (!glb_policy->started_picking) {
       start_picking_locked(exec_ctx, glb_policy);
     }
   }
-  gpr_mu_unlock(&glb_policy->mu);
 }
 
-static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx,
-                                       grpc_lb_policy *pol,
-                                       grpc_connectivity_state *current,
-                                       grpc_closure *notify) {
+static void glb_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
+                                              grpc_lb_policy *pol,
+                                              grpc_connectivity_state *current,
+                                              grpc_closure *notify) {
   glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
-  gpr_mu_lock(&glb_policy->mu);
   grpc_connectivity_state_notify_on_state_change(
       exec_ctx, &glb_policy->state_tracker, current, notify);
-
-  gpr_mu_unlock(&glb_policy->mu);
 }
 
-static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
-                                         grpc_error *error);
-static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
-                                    grpc_error *error);
+static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx,
+                                                void *arg, grpc_error *error);
+static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                           grpc_error *error);
 static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
                                 glb_lb_policy *glb_policy) {
   GPR_ASSERT(glb_policy->server_name != NULL);
@@ -1103,11 +1114,12 @@
   /* Note the following LB call progresses every time there's activity in \a
    * glb_policy->base.interested_parties, which is comprised of the polling
    * entities from \a client_channel. */
+  grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name);
   glb_policy->lb_call = grpc_channel_create_pollset_set_call(
       exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
       glb_policy->base.interested_parties,
-      "/grpc.lb.v1.LoadBalancer/BalanceLoad", glb_policy->server_name,
-      glb_policy->deadline, NULL);
+      GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
+      &host, glb_policy->deadline, NULL);
 
   grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv);
   grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv);
@@ -1120,15 +1132,12 @@
   grpc_slice_unref_internal(exec_ctx, request_payload_slice);
   grpc_grpclb_request_destroy(request);
 
-  glb_policy->lb_call_status_details = NULL;
-  glb_policy->lb_call_status_details_capacity = 0;
-
   grpc_closure_init(&glb_policy->lb_on_server_status_received,
-                    lb_on_server_status_received, glb_policy,
-                    grpc_schedule_on_exec_ctx);
+                    lb_on_server_status_received_locked, glb_policy,
+                    grpc_combiner_scheduler(glb_policy->base.combiner, false));
   grpc_closure_init(&glb_policy->lb_on_response_received,
-                    lb_on_response_received, glb_policy,
-                    grpc_schedule_on_exec_ctx);
+                    lb_on_response_received_locked, glb_policy,
+                    grpc_combiner_scheduler(glb_policy->base.combiner, false));
 
   gpr_backoff_init(&glb_policy->lb_call_backoff_state,
                    GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS,
@@ -1138,7 +1147,8 @@
                    GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
 }
 
-static void lb_call_destroy_locked(glb_lb_policy *glb_policy) {
+static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx,
+                                   glb_lb_policy *glb_policy) {
   GPR_ASSERT(glb_policy->lb_call != NULL);
   grpc_call_destroy(glb_policy->lb_call);
   glb_policy->lb_call = NULL;
@@ -1147,7 +1157,7 @@
   grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv);
 
   grpc_byte_buffer_destroy(glb_policy->lb_request_payload);
-  gpr_free(glb_policy->lb_call_status_details);
+  grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details);
 }
 
 /*
@@ -1197,8 +1207,6 @@
   op->data.recv_status_on_client.status = &glb_policy->lb_call_status;
   op->data.recv_status_on_client.status_details =
       &glb_policy->lb_call_status_details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &glb_policy->lb_call_status_details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -1224,14 +1232,13 @@
   GPR_ASSERT(GRPC_CALL_OK == call_error);
 }
 
-static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
-                                    grpc_error *error) {
+static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                           grpc_error *error) {
   glb_lb_policy *glb_policy = arg;
 
   grpc_op ops[2];
   memset(ops, 0, sizeof(ops));
   grpc_op *op = ops;
-  gpr_mu_lock(&glb_policy->mu);
   if (glb_policy->lb_response_payload != NULL) {
     gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
     /* Received data from the LB server. Look inside
@@ -1305,20 +1312,17 @@
           &glb_policy->lb_on_response_received); /* loop */
       GPR_ASSERT(GRPC_CALL_OK == call_error);
     }
-    gpr_mu_unlock(&glb_policy->mu);
   } else { /* empty payload: call cancelled. */
            /* dispose of the "lb_on_response_received" weak ref taken in
             * query_for_backends_locked() and reused in every reception loop */
-    gpr_mu_unlock(&glb_policy->mu);
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
                               "lb_on_response_received_empty_payload");
   }
 }
 
-static void lb_call_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
-                                   grpc_error *error) {
+static void lb_call_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                          grpc_error *error) {
   glb_lb_policy *glb_policy = arg;
-  gpr_mu_lock(&glb_policy->mu);
 
   if (!glb_policy->shutting_down) {
     if (grpc_lb_glb_trace) {
@@ -1328,28 +1332,29 @@
     GPR_ASSERT(glb_policy->lb_call == NULL);
     query_for_backends_locked(exec_ctx, glb_policy);
   }
-  gpr_mu_unlock(&glb_policy->mu);
   GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
                             "grpclb_on_retry_timer");
 }
 
-static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
-                                         grpc_error *error) {
+static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx,
+                                                void *arg, grpc_error *error) {
   glb_lb_policy *glb_policy = arg;
-  gpr_mu_lock(&glb_policy->mu);
 
   GPR_ASSERT(glb_policy->lb_call != NULL);
 
   if (grpc_lb_glb_trace) {
+    char *status_details =
+        grpc_slice_to_c_string(glb_policy->lb_call_status_details);
     gpr_log(GPR_DEBUG,
             "Status from LB server received. Status = %d, Details = '%s', "
             "(call: %p)",
-            glb_policy->lb_call_status, glb_policy->lb_call_status_details,
+            glb_policy->lb_call_status, status_details,
             (void *)glb_policy->lb_call);
+    gpr_free(status_details);
   }
 
-  /* We need to performe cleanups no matter what. */
-  lb_call_destroy_locked(glb_policy);
+  /* We need to perform cleanups no matter what. */
+  lb_call_destroy_locked(exec_ctx, glb_policy);
 
   if (!glb_policy->shutting_down) {
     /* if we aren't shutting down, restart the LB client call after some time */
@@ -1368,21 +1373,27 @@
       }
     }
     GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer");
-    grpc_closure_init(&glb_policy->lb_on_call_retry, lb_call_on_retry_timer,
-                      glb_policy, grpc_schedule_on_exec_ctx);
+    grpc_closure_init(
+        &glb_policy->lb_on_call_retry, lb_call_on_retry_timer_locked,
+        glb_policy, grpc_combiner_scheduler(glb_policy->base.combiner, false));
     grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try,
                     &glb_policy->lb_on_call_retry, now);
   }
-  gpr_mu_unlock(&glb_policy->mu);
   GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
                             "lb_on_server_status_received");
 }
 
 /* Code wiring the policy with the rest of the core */
 static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
-    glb_destroy,     glb_shutdown,           glb_pick,
-    glb_cancel_pick, glb_cancel_picks,       glb_ping_one,
-    glb_exit_idle,   glb_check_connectivity, glb_notify_on_state_change};
+    glb_destroy,
+    glb_shutdown_locked,
+    glb_pick_locked,
+    glb_cancel_pick_locked,
+    glb_cancel_picks_locked,
+    glb_ping_one_locked,
+    glb_exit_idle_locked,
+    glb_check_connectivity_locked,
+    glb_notify_on_state_change_locked};
 
 static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
 
diff --git a/src/core/ext/lb_policy/grpclb/grpclb_channel.c b/src/core/ext/lb_policy/grpclb/grpclb_channel.c
new file mode 100644
index 0000000..1b8bbab
--- /dev/null
+++ b/src/core/ext/lb_policy/grpclb/grpclb_channel.c
@@ -0,0 +1,77 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/client_channel/client_channel.h"
+#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/support/string.h"
+
+grpc_channel *grpc_lb_policy_grpclb_create_lb_channel(
+    grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses,
+    grpc_client_channel_factory *client_channel_factory,
+    grpc_channel_args *args) {
+  grpc_channel *lb_channel = grpc_client_channel_factory_create_channel(
+      exec_ctx, client_channel_factory, lb_service_target_addresses,
+      GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, args);
+  return lb_channel;
+}
+
+grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx,
+                                       grpc_slice_hash_table *targets_info,
+                                       const grpc_channel_args *args) {
+  /* We strip out the channel arg for the LB policy name, since we want
+   * to use the default (pick_first) in this case.
+   *
+   * We also strip out the channel arg for the resolved addresses, since
+   * that will be generated by the name resolver used in the LB channel.
+   * Note that the LB channel will use the sockaddr resolver, so this
+   * won't actually generate a query to DNS (or some other name service).
+   * However, the addresses returned by the sockaddr resolver will have
+   * is_balancer=false, whereas our own addresses have is_balancer=true.
+   * We need the LB channel to return addresses with is_balancer=false
+   * so that it does not wind up recursively using the grpclb LB policy,
+   * as per the special case logic in client_channel.c.
+   *
+   * Lastly, we also strip out the channel arg for the server URI,
+   * since that will be different for the LB channel than for the parent
+   * channel (the client channel factory will re-add this arg with
+   * the right value). */
+  static const char *keys_to_remove[] = {
+      GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI};
+  return grpc_channel_args_copy_and_remove(args, keys_to_remove,
+                                           GPR_ARRAY_SIZE(keys_to_remove));
+}
diff --git a/src/core/ext/lb_policy/grpclb/grpclb_channel.h b/src/core/ext/lb_policy/grpclb/grpclb_channel.h
new file mode 100644
index 0000000..f66082d
--- /dev/null
+++ b/src/core/ext/lb_policy/grpclb/grpclb_channel.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H
+#define GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H
+
+#include "src/core/ext/client_channel/lb_policy_factory.h"
+#include "src/core/lib/slice/slice_hash_table.h"
+
+/** Create the channel used for communicating with an LB service.
+ * Note that an LB *service* may be comprised of several LB *servers*.
+ *
+ * \a lb_service_target_addresses is the target URI containing the addresses
+ * from resolving the LB service's name (eg, ipv4:10.0.0.1:1234,10.2.3.4:9876).
+ * \a client_channel_factory will be used for the creation of the LB channel,
+ * alongside the channel args passed in \a args. */
+grpc_channel *grpc_lb_policy_grpclb_create_lb_channel(
+    grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses,
+    grpc_client_channel_factory *client_channel_factory,
+    grpc_channel_args *args);
+
+grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx,
+                                       grpc_slice_hash_table *targets_info,
+                                       const grpc_channel_args *args);
+
+#endif /* GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H */
diff --git a/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c b/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c
new file mode 100644
index 0000000..2fee5f1
--- /dev/null
+++ b/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c
@@ -0,0 +1,107 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/client_channel/client_channel.h"
+#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/transport/lb_targets_info.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/support/string.h"
+
+grpc_channel *grpc_lb_policy_grpclb_create_lb_channel(
+    grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses,
+    grpc_client_channel_factory *client_channel_factory,
+    grpc_channel_args *args) {
+  grpc_channel_args *new_args = args;
+  grpc_channel_credentials *channel_credentials =
+      grpc_channel_credentials_find_in_args(args);
+  if (channel_credentials != NULL) {
+    /* Substitute the channel credentials with a version without call
+     * credentials: the load balancer is not necessarily trusted to handle
+     * bearer token credentials */
+    static const char *keys_to_remove[] = {GRPC_ARG_CHANNEL_CREDENTIALS};
+    grpc_channel_credentials *creds_sans_call_creds =
+        grpc_channel_credentials_duplicate_without_call_credentials(
+            channel_credentials);
+    GPR_ASSERT(creds_sans_call_creds != NULL);
+    grpc_arg args_to_add[] = {
+        grpc_channel_credentials_to_arg(creds_sans_call_creds)};
+    /* Create the new set of channel args */
+    new_args = grpc_channel_args_copy_and_add_and_remove(
+        args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
+        GPR_ARRAY_SIZE(args_to_add));
+    grpc_channel_credentials_unref(exec_ctx, creds_sans_call_creds);
+  }
+  grpc_channel *lb_channel = grpc_client_channel_factory_create_channel(
+      exec_ctx, client_channel_factory, lb_service_target_addresses,
+      GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
+  if (channel_credentials != NULL) {
+    grpc_channel_args_destroy(exec_ctx, new_args);
+  }
+  return lb_channel;
+}
+
+grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx,
+                                       grpc_slice_hash_table *targets_info,
+                                       const grpc_channel_args *args) {
+  const grpc_arg targets_info_arg =
+      grpc_lb_targets_info_create_channel_arg(targets_info);
+  /* We strip out the channel arg for the LB policy name, since we want
+   * to use the default (pick_first) in this case.
+   *
+   * We also strip out the channel arg for the resolved addresses, since
+   * that will be generated by the name resolver used in the LB channel.
+   * Note that the LB channel will use the sockaddr resolver, so this
+   * won't actually generate a query to DNS (or some other name service).
+   * However, the addresses returned by the sockaddr resolver will have
+   * is_balancer=false, whereas our own addresses have is_balancer=true.
+   * We need the LB channel to return addresses with is_balancer=false
+   * so that it does not wind up recursively using the grpclb LB policy,
+   * as per the special case logic in client_channel.c.
+   *
+   * Lastly, we also strip out the channel arg for the server URI,
+   * since that will be different for the LB channel than for the parent
+   * channel (the client channel factory will re-add this arg with
+   * the right value). */
+  static const char *keys_to_remove[] = {
+      GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI};
+  /* Add the targets info table to be used for secure naming */
+  return grpc_channel_args_copy_and_add_and_remove(
+      args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &targets_info_arg,
+      1);
+}
diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/lb_policy/grpclb/load_balancer_api.c
index 837e9c1..3c4604c 100644
--- a/src/core/ext/lb_policy/grpclb/load_balancer_api.c
+++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.c
@@ -62,8 +62,7 @@
     }
     dec_arg->num_servers++;
   } else { /* second pass. Actually decode. */
-    grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server));
-    memset(server, 0, sizeof(grpc_grpclb_server));
+    grpc_grpclb_server *server = gpr_zalloc(sizeof(grpc_grpclb_server));
     GPR_ASSERT(dec_arg->num_servers > 0);
     if (dec_arg->decoding_idx == 0) { /* first iteration of second pass */
       dec_arg->servers =
@@ -160,8 +159,7 @@
     return NULL;
   }
 
-  grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist));
-  memset(sl, 0, sizeof(*sl));
+  grpc_grpclb_serverlist *sl = gpr_zalloc(sizeof(grpc_grpclb_serverlist));
   sl->num_servers = arg.num_servers;
   sl->servers = arg.servers;
   if (res.server_list.has_expiration_interval) {
@@ -183,8 +181,7 @@
 
 grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy(
     const grpc_grpclb_serverlist *sl) {
-  grpc_grpclb_serverlist *copy = gpr_malloc(sizeof(grpc_grpclb_serverlist));
-  memset(copy, 0, sizeof(grpc_grpclb_serverlist));
+  grpc_grpclb_serverlist *copy = gpr_zalloc(sizeof(grpc_grpclb_serverlist));
   copy->num_servers = sl->num_servers;
   memcpy(&copy->expiration_interval, &sl->expiration_interval,
          sizeof(grpc_grpclb_duration));
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
index 9f2aa46..e2a66d1 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -38,6 +38,7 @@
 #include "src/core/ext/client_channel/lb_policy_registry.h"
 #include "src/core/ext/client_channel/subchannel.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/transport/connectivity_state.h"
 
@@ -57,11 +58,11 @@
 
   grpc_closure connectivity_changed;
 
-  /** the selected channel (a grpc_connected_subchannel) */
-  gpr_atm selected;
+  /** remaining members are protected by the combiner */
 
-  /** mutex protecting remaining members */
-  gpr_mu mu;
+  /** the selected channel */
+  grpc_connected_subchannel *selected;
+
   /** have we started picking? */
   int started_picking;
   /** are we shut down? */
@@ -77,32 +78,24 @@
   grpc_connectivity_state_tracker state_tracker;
 } pick_first_lb_policy;
 
-#define GET_SELECTED(p) \
-  ((grpc_connected_subchannel *)gpr_atm_acq_load(&(p)->selected))
-
 static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  grpc_connected_subchannel *selected = GET_SELECTED(p);
   size_t i;
   GPR_ASSERT(p->pending_picks == NULL);
   for (i = 0; i < p->num_subchannels; i++) {
     GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
   }
-  if (selected != NULL) {
-    GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, selected, "picked_first");
+  if (p->selected != NULL) {
+    GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected, "picked_first");
   }
   grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
   gpr_free(p->subchannels);
-  gpr_mu_destroy(&p->mu);
   gpr_free(p);
 }
 
-static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void pf_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
   pending_pick *pp;
-  grpc_connected_subchannel *selected;
-  gpr_mu_lock(&p->mu);
-  selected = GET_SELECTED(p);
   p->shutdown = 1;
   pp = p->pending_picks;
   p->pending_picks = NULL;
@@ -110,15 +103,14 @@
       exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
       GRPC_ERROR_CREATE("Channel shutdown"), "shutdown");
   /* cancel subscription */
-  if (selected != NULL) {
+  if (p->selected != NULL) {
     grpc_connected_subchannel_notify_on_state_change(
-        exec_ctx, selected, NULL, NULL, &p->connectivity_changed);
+        exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed);
   } else if (p->num_subchannels > 0) {
     grpc_subchannel_notify_on_state_change(
         exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
         &p->connectivity_changed);
   }
-  gpr_mu_unlock(&p->mu);
   while (pp != NULL) {
     pending_pick *next = pp->next;
     *pp->target = NULL;
@@ -128,12 +120,11 @@
   }
 }
 
-static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                           grpc_connected_subchannel **target,
-                           grpc_error *error) {
+static void pf_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                                  grpc_connected_subchannel **target,
+                                  grpc_error *error) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
   pending_pick *pp;
-  gpr_mu_lock(&p->mu);
   pp = p->pending_picks;
   p->pending_picks = NULL;
   while (pp != NULL) {
@@ -150,17 +141,15 @@
     }
     pp = next;
   }
-  gpr_mu_unlock(&p->mu);
   GRPC_ERROR_UNREF(error);
 }
 
-static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                            uint32_t initial_metadata_flags_mask,
-                            uint32_t initial_metadata_flags_eq,
-                            grpc_error *error) {
+static void pf_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                                   uint32_t initial_metadata_flags_mask,
+                                   uint32_t initial_metadata_flags_eq,
+                                   grpc_error *error) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
   pending_pick *pp;
-  gpr_mu_lock(&p->mu);
   pp = p->pending_picks;
   p->pending_picks = NULL;
   while (pp != NULL) {
@@ -177,7 +166,6 @@
     }
     pp = next;
   }
-  gpr_mu_unlock(&p->mu);
   GRPC_ERROR_UNREF(error);
 }
 
@@ -192,63 +180,48 @@
       &p->connectivity_changed);
 }
 
-static void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void pf_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  gpr_mu_lock(&p->mu);
   if (!p->started_picking) {
     start_picking(exec_ctx, p);
   }
-  gpr_mu_unlock(&p->mu);
 }
 
-static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                   const grpc_lb_policy_pick_args *pick_args,
-                   grpc_connected_subchannel **target, void **user_data,
-                   grpc_closure *on_complete) {
+static int pf_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                          const grpc_lb_policy_pick_args *pick_args,
+                          grpc_connected_subchannel **target, void **user_data,
+                          grpc_closure *on_complete) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
   pending_pick *pp;
 
   /* Check atomically for a selected channel */
-  grpc_connected_subchannel *selected = GET_SELECTED(p);
-  if (selected != NULL) {
-    *target = GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked");
+  if (p->selected != NULL) {
+    *target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked");
     return 1;
   }
 
-  /* No subchannel selected yet, so acquire lock and then attempt again */
-  gpr_mu_lock(&p->mu);
-  selected = GET_SELECTED(p);
-  if (selected) {
-    gpr_mu_unlock(&p->mu);
-    *target = GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked");
-    return 1;
-  } else {
-    if (!p->started_picking) {
-      start_picking(exec_ctx, p);
-    }
-    pp = gpr_malloc(sizeof(*pp));
-    pp->next = p->pending_picks;
-    pp->target = target;
-    pp->initial_metadata_flags = pick_args->initial_metadata_flags;
-    pp->on_complete = on_complete;
-    p->pending_picks = pp;
-    gpr_mu_unlock(&p->mu);
-    return 0;
+  /* No subchannel selected yet, so try again */
+  if (!p->started_picking) {
+    start_picking(exec_ctx, p);
   }
+  pp = gpr_malloc(sizeof(*pp));
+  pp->next = p->pending_picks;
+  pp->target = target;
+  pp->initial_metadata_flags = pick_args->initial_metadata_flags;
+  pp->on_complete = on_complete;
+  p->pending_picks = pp;
+  return 0;
 }
 
-static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
-                                grpc_error *error) {
-  pick_first_lb_policy *p = arg;
+static void destroy_subchannels_locked(grpc_exec_ctx *exec_ctx,
+                                       pick_first_lb_policy *p) {
   size_t i;
   size_t num_subchannels = p->num_subchannels;
   grpc_subchannel **subchannels;
 
-  gpr_mu_lock(&p->mu);
   subchannels = p->subchannels;
   p->num_subchannels = 0;
   p->subchannels = NULL;
-  gpr_mu_unlock(&p->mu);
   GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
 
   for (i = 0; i < num_subchannels; i++) {
@@ -258,25 +231,19 @@
   gpr_free(subchannels);
 }
 
-static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                    grpc_error *error) {
+static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                           grpc_error *error) {
   pick_first_lb_policy *p = arg;
   grpc_subchannel *selected_subchannel;
   pending_pick *pp;
-  grpc_connected_subchannel *selected;
 
   GRPC_ERROR_REF(error);
 
-  gpr_mu_lock(&p->mu);
-
-  selected = GET_SELECTED(p);
-
   if (p->shutdown) {
-    gpr_mu_unlock(&p->mu);
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
     GRPC_ERROR_UNREF(error);
     return;
-  } else if (selected != NULL) {
+  } else if (p->selected != NULL) {
     if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
       /* if the selected channel goes bad, we're done */
       p->checking_connectivity = GRPC_CHANNEL_SHUTDOWN;
@@ -286,7 +253,7 @@
                                 "selected_changed");
     if (p->checking_connectivity != GRPC_CHANNEL_SHUTDOWN) {
       grpc_connected_subchannel_notify_on_state_change(
-          exec_ctx, selected, p->base.interested_parties,
+          exec_ctx, p->selected, p->base.interested_parties,
           &p->checking_connectivity, &p->connectivity_changed);
     } else {
       GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
@@ -301,26 +268,21 @@
                                     GRPC_CHANNEL_READY, GRPC_ERROR_NONE,
                                     "connecting_ready");
         selected_subchannel = p->subchannels[p->checking_subchannel];
-        selected =
-            grpc_subchannel_get_connected_subchannel(selected_subchannel);
-        GPR_ASSERT(selected != NULL);
-        GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked_first");
+        p->selected = GRPC_CONNECTED_SUBCHANNEL_REF(
+            grpc_subchannel_get_connected_subchannel(selected_subchannel),
+            "picked_first");
         /* drop the pick list: we are connected now */
         GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
-        gpr_atm_rel_store(&p->selected, (gpr_atm)selected);
-        grpc_closure_sched(exec_ctx,
-                           grpc_closure_create(destroy_subchannels, p,
-                                               grpc_schedule_on_exec_ctx),
-                           GRPC_ERROR_NONE);
+        destroy_subchannels_locked(exec_ctx, p);
         /* update any calls that were waiting for a pick */
         while ((pp = p->pending_picks)) {
           p->pending_picks = pp->next;
-          *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked");
+          *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked");
           grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
           gpr_free(pp);
         }
         grpc_connected_subchannel_notify_on_state_change(
-            exec_ctx, selected, p->base.interested_parties,
+            exec_ctx, p->selected, p->base.interested_parties,
             &p->checking_connectivity, &p->connectivity_changed);
         break;
       case GRPC_CHANNEL_TRANSIENT_FAILURE:
@@ -387,48 +349,44 @@
     }
   }
 
-  gpr_mu_unlock(&p->mu);
-
   GRPC_ERROR_UNREF(error);
 }
 
-static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
-                                                     grpc_lb_policy *pol,
-                                                     grpc_error **error) {
+static grpc_connectivity_state pf_check_connectivity_locked(
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **error) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  grpc_connectivity_state st;
-  gpr_mu_lock(&p->mu);
-  st = grpc_connectivity_state_check(&p->state_tracker, error);
-  gpr_mu_unlock(&p->mu);
-  return st;
+  return grpc_connectivity_state_get(&p->state_tracker, error);
 }
 
-static void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx,
-                                      grpc_lb_policy *pol,
-                                      grpc_connectivity_state *current,
-                                      grpc_closure *notify) {
+static void pf_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
+                                             grpc_lb_policy *pol,
+                                             grpc_connectivity_state *current,
+                                             grpc_closure *notify) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  gpr_mu_lock(&p->mu);
   grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
                                                  current, notify);
-  gpr_mu_unlock(&p->mu);
 }
 
-static void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                        grpc_closure *closure) {
+static void pf_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                               grpc_closure *closure) {
   pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
-  grpc_connected_subchannel *selected = GET_SELECTED(p);
-  if (selected) {
-    grpc_connected_subchannel_ping(exec_ctx, selected, closure);
+  if (p->selected) {
+    grpc_connected_subchannel_ping(exec_ctx, p->selected, closure);
   } else {
     grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE("Not connected"));
   }
 }
 
 static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
-    pf_destroy,     pf_shutdown,           pf_pick,
-    pf_cancel_pick, pf_cancel_picks,       pf_ping_one,
-    pf_exit_idle,   pf_check_connectivity, pf_notify_on_state_change};
+    pf_destroy,
+    pf_shutdown_locked,
+    pf_pick_locked,
+    pf_cancel_pick_locked,
+    pf_cancel_picks_locked,
+    pf_ping_one_locked,
+    pf_exit_idle_locked,
+    pf_check_connectivity_locked,
+    pf_notify_on_state_change_locked};
 
 static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
 
@@ -451,11 +409,9 @@
   }
   if (num_addrs == 0) return NULL;
 
-  pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
-  memset(p, 0, sizeof(*p));
+  pick_first_lb_policy *p = gpr_zalloc(sizeof(*p));
 
-  p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * num_addrs);
-  memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
+  p->subchannels = gpr_zalloc(sizeof(grpc_subchannel *) * num_addrs);
   grpc_subchannel_args sc_args;
   size_t subchannel_idx = 0;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
@@ -489,10 +445,9 @@
   }
   p->num_subchannels = subchannel_idx;
 
-  grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
-  grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed, p,
-                    grpc_schedule_on_exec_ctx);
-  gpr_mu_init(&p->mu);
+  grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner);
+  grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed_locked, p,
+                    grpc_combiner_scheduler(args->combiner, false));
   return &p->base;
 }
 
diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c
index d17d8fa..f2d1d46 100644
--- a/src/core/ext/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -67,6 +67,7 @@
 #include "src/core/ext/client_channel/subchannel.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/debug/trace.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/transport/connectivity_state.h"
 #include "src/core/lib/transport/static_metadata.h"
@@ -134,7 +135,6 @@
 struct round_robin_lb_policy {
   /** base policy: must be first */
   grpc_lb_policy base;
-  gpr_mu mu;
 
   /** total number of addresses received at creation time */
   size_t num_addresses;
@@ -213,8 +213,7 @@
  * csc to the list of ready subchannels. */
 static ready_list *add_connected_sc_locked(round_robin_lb_policy *p,
                                            subchannel_data *sd) {
-  ready_list *new_elem = gpr_malloc(sizeof(ready_list));
-  memset(new_elem, 0, sizeof(ready_list));
+  ready_list *new_elem = gpr_zalloc(sizeof(ready_list));
   new_elem->subchannel = sd->subchannel;
   new_elem->user_data = sd->user_data;
   if (p->ready_list.prev == NULL) {
@@ -293,7 +292,6 @@
 
   grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
   gpr_free(p->subchannels);
-  gpr_mu_destroy(&p->mu);
 
   elem = p->ready_list.next;
   while (elem != NULL && elem != &p->ready_list) {
@@ -309,12 +307,11 @@
   gpr_free(p);
 }
 
-static void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   pending_pick *pp;
   size_t i;
 
-  gpr_mu_lock(&p->mu);
   if (grpc_lb_round_robin_trace) {
     gpr_log(GPR_DEBUG, "Shutting down Round Robin policy at %p", (void *)pol);
   }
@@ -335,15 +332,13 @@
     grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL, NULL,
                                            &sd->connectivity_changed_closure);
   }
-  gpr_mu_unlock(&p->mu);
 }
 
-static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                           grpc_connected_subchannel **target,
-                           grpc_error *error) {
+static void rr_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                                  grpc_connected_subchannel **target,
+                                  grpc_error *error) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   pending_pick *pp;
-  gpr_mu_lock(&p->mu);
   pp = p->pending_picks;
   p->pending_picks = NULL;
   while (pp != NULL) {
@@ -360,17 +355,15 @@
     }
     pp = next;
   }
-  gpr_mu_unlock(&p->mu);
   GRPC_ERROR_UNREF(error);
 }
 
-static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                            uint32_t initial_metadata_flags_mask,
-                            uint32_t initial_metadata_flags_eq,
-                            grpc_error *error) {
+static void rr_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                                   uint32_t initial_metadata_flags_mask,
+                                   uint32_t initial_metadata_flags_eq,
+                                   grpc_error *error) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   pending_pick *pp;
-  gpr_mu_lock(&p->mu);
   pp = p->pending_picks;
   p->pending_picks = NULL;
   while (pp != NULL) {
@@ -388,11 +381,11 @@
     }
     pp = next;
   }
-  gpr_mu_unlock(&p->mu);
   GRPC_ERROR_UNREF(error);
 }
 
-static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
+static void start_picking_locked(grpc_exec_ctx *exec_ctx,
+                                 round_robin_lb_policy *p) {
   size_t i;
   p->started_picking = 1;
 
@@ -411,23 +404,20 @@
   }
 }
 
-static void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void rr_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  gpr_mu_lock(&p->mu);
   if (!p->started_picking) {
-    start_picking(exec_ctx, p);
+    start_picking_locked(exec_ctx, p);
   }
-  gpr_mu_unlock(&p->mu);
 }
 
-static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                   const grpc_lb_policy_pick_args *pick_args,
-                   grpc_connected_subchannel **target, void **user_data,
-                   grpc_closure *on_complete) {
+static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                          const grpc_lb_policy_pick_args *pick_args,
+                          grpc_connected_subchannel **target, void **user_data,
+                          grpc_closure *on_complete) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   pending_pick *pp;
   ready_list *selected;
-  gpr_mu_lock(&p->mu);
 
   if (grpc_lb_round_robin_trace) {
     gpr_log(GPR_INFO, "Round Robin %p trying to pick", (void *)pol);
@@ -449,12 +439,11 @@
     }
     /* only advance the last picked pointer if the selection was used */
     advance_last_picked_locked(p);
-    gpr_mu_unlock(&p->mu);
     return 1;
   } else {
     /* no pick currently available. Save for later in list of pending picks */
     if (!p->started_picking) {
-      start_picking(exec_ctx, p);
+      start_picking_locked(exec_ctx, p);
     }
     pp = gpr_malloc(sizeof(*pp));
     pp->next = p->pending_picks;
@@ -463,7 +452,6 @@
     pp->initial_metadata_flags = pick_args->initial_metadata_flags;
     pp->user_data = user_data;
     p->pending_picks = pp;
-    gpr_mu_unlock(&p->mu);
     return 0;
   }
 }
@@ -538,17 +526,15 @@
   return sd->curr_connectivity_state;
 }
 
-static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
-                                    grpc_error *error) {
+static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                           grpc_error *error) {
   subchannel_data *sd = arg;
   round_robin_lb_policy *p = sd->policy;
   pending_pick *pp;
 
   GRPC_ERROR_REF(error);
-  gpr_mu_lock(&p->mu);
 
   if (p->shutdown) {
-    gpr_mu_unlock(&p->mu);
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
     GRPC_ERROR_UNREF(error);
     return;
@@ -645,56 +631,51 @@
       GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
       break;
   }
-  gpr_mu_unlock(&p->mu);
   GRPC_ERROR_UNREF(error);
 }
 
-static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
-                                                     grpc_lb_policy *pol,
-                                                     grpc_error **error) {
+static grpc_connectivity_state rr_check_connectivity_locked(
+    grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **error) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  grpc_connectivity_state st;
-  gpr_mu_lock(&p->mu);
-  st = grpc_connectivity_state_check(&p->state_tracker, error);
-  gpr_mu_unlock(&p->mu);
-  return st;
+  return grpc_connectivity_state_get(&p->state_tracker, error);
 }
 
-static void rr_notify_on_state_change(grpc_exec_ctx *exec_ctx,
-                                      grpc_lb_policy *pol,
-                                      grpc_connectivity_state *current,
-                                      grpc_closure *notify) {
+static void rr_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
+                                             grpc_lb_policy *pol,
+                                             grpc_connectivity_state *current,
+                                             grpc_closure *notify) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
-  gpr_mu_lock(&p->mu);
   grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
                                                  current, notify);
-  gpr_mu_unlock(&p->mu);
 }
 
-static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                        grpc_closure *closure) {
+static void rr_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                               grpc_closure *closure) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   ready_list *selected;
   grpc_connected_subchannel *target;
-  gpr_mu_lock(&p->mu);
   if ((selected = peek_next_connected_locked(p))) {
-    gpr_mu_unlock(&p->mu);
     target = GRPC_CONNECTED_SUBCHANNEL_REF(
         grpc_subchannel_get_connected_subchannel(selected->subchannel),
         "rr_picked");
     grpc_connected_subchannel_ping(exec_ctx, target, closure);
     GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, target, "rr_picked");
   } else {
-    gpr_mu_unlock(&p->mu);
     grpc_closure_sched(exec_ctx, closure,
                        GRPC_ERROR_CREATE("Round Robin not connected"));
   }
 }
 
 static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = {
-    rr_destroy,     rr_shutdown,           rr_pick,
-    rr_cancel_pick, rr_cancel_picks,       rr_ping_one,
-    rr_exit_idle,   rr_check_connectivity, rr_notify_on_state_change};
+    rr_destroy,
+    rr_shutdown_locked,
+    rr_pick_locked,
+    rr_cancel_pick_locked,
+    rr_cancel_picks_locked,
+    rr_ping_one_locked,
+    rr_exit_idle_locked,
+    rr_check_connectivity_locked,
+    rr_notify_on_state_change_locked};
 
 static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {}
 
@@ -717,12 +698,10 @@
   }
   if (num_addrs == 0) return NULL;
 
-  round_robin_lb_policy *p = gpr_malloc(sizeof(*p));
-  memset(p, 0, sizeof(*p));
+  round_robin_lb_policy *p = gpr_zalloc(sizeof(*p));
 
   p->num_addresses = num_addrs;
-  p->subchannels = gpr_malloc(sizeof(*p->subchannels) * num_addrs);
-  memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
+  p->subchannels = gpr_zalloc(sizeof(*p->subchannels) * num_addrs);
 
   grpc_subchannel_args sc_args;
   size_t subchannel_idx = 0;
@@ -739,11 +718,17 @@
     sc_args.args = new_args;
     grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
         exec_ctx, args->client_channel_factory, &sc_args);
+    if (grpc_lb_round_robin_trace) {
+      char *address_uri =
+          grpc_sockaddr_to_uri(&addresses->addresses[i].address);
+      gpr_log(GPR_DEBUG, "Created subchannel %p for address uri %s",
+              (void *)subchannel, address_uri);
+      gpr_free(address_uri);
+    }
     grpc_channel_args_destroy(exec_ctx, new_args);
 
     if (subchannel != NULL) {
-      subchannel_data *sd = gpr_malloc(sizeof(*sd));
-      memset(sd, 0, sizeof(*sd));
+      subchannel_data *sd = gpr_zalloc(sizeof(*sd));
       p->subchannels[subchannel_idx] = sd;
       sd->policy = p;
       sd->index = subchannel_idx;
@@ -755,7 +740,8 @@
       }
       ++subchannel_idx;
       grpc_closure_init(&sd->connectivity_changed_closure,
-                        rr_connectivity_changed, sd, grpc_schedule_on_exec_ctx);
+                        rr_connectivity_changed_locked, sd,
+                        grpc_combiner_scheduler(args->combiner, false));
     }
   }
   if (subchannel_idx == 0) {
@@ -772,7 +758,7 @@
   p->ready_list.next = NULL;
   p->ready_list_last_pick = &p->ready_list;
 
-  grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable);
+  grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable, args->combiner);
   grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
                                "round_robin");
 
@@ -780,7 +766,6 @@
     gpr_log(GPR_DEBUG, "Created RR policy at %p with %lu subchannels",
             (void *)p, (unsigned long)p->num_subchannels);
   }
-  gpr_mu_init(&p->mu);
   return &p->base;
 }
 
diff --git a/src/core/ext/load_reporting/load_reporting.c b/src/core/ext/load_reporting/load_reporting.c
index 37b06a7..942aea4 100644
--- a/src/core/ext/load_reporting/load_reporting.c
+++ b/src/core/ext/load_reporting/load_reporting.c
@@ -34,14 +34,34 @@
 #include <limits.h>
 #include <string.h>
 
+#include <grpc/load_reporting.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/sync.h>
 
 #include "src/core/ext/load_reporting/load_reporting.h"
 #include "src/core/ext/load_reporting/load_reporting_filter.h"
 #include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/channel_init.h"
 
+static void destroy_lr_cost_context(void *c) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_load_reporting_cost_context *cost_ctx = c;
+  for (size_t i = 0; i < cost_ctx->values_count; ++i) {
+    grpc_slice_unref_internal(&exec_ctx, cost_ctx->values[i]);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  gpr_free(cost_ctx->values);
+  gpr_free(cost_ctx);
+}
+
+void grpc_call_set_load_reporting_cost_context(
+    grpc_call *call, grpc_load_reporting_cost_context *ctx) {
+  grpc_call_context_set(call, GRPC_CONTEXT_LR_COST, ctx,
+                        destroy_lr_cost_context);
+}
+
 static bool is_load_reporting_enabled(const grpc_channel_args *a) {
   if (a == NULL) return false;
   for (size_t i = 0; i < a->num_args; i++) {
diff --git a/src/core/ext/load_reporting/load_reporting.h b/src/core/ext/load_reporting/load_reporting.h
index a157844..22859a5 100644
--- a/src/core/ext/load_reporting/load_reporting.h
+++ b/src/core/ext/load_reporting/load_reporting.h
@@ -35,24 +35,9 @@
 #define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H
 
 #include <grpc/impl/codegen/grpc_types.h>
+
 #include "src/core/lib/channel/channel_stack.h"
 
-/** Metadata key for the gRPC LB load balancer token.
- *
- * The value corresponding to this key is an opaque token that is given to the
- * frontend as part of each pick; the frontend sends this token to the backend
- * in each request it sends when using that pick. The token is used by the
- * backend to verify the request and to allow the backend to report load to the
- * gRPC LB system. */
-#define GRPC_LB_TOKEN_MD_KEY "lb-token"
-
-/** Metadata key for gRPC LB cost reporting.
- *
- * The value corresponding to this key is an opaque binary blob reported by the
- * backend as part of its trailing metadata containing cost information for the
- * call. */
-#define GRPC_LB_COST_MD_KEY "lb-cost-bin"
-
 /** Identifiers for the invocation point of the users LR callback */
 typedef enum grpc_load_reporting_source {
   GRPC_LR_POINT_UNKNOWN = 0,
diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c
index 07ef10e..c275063 100644
--- a/src/core/ext/load_reporting/load_reporting_filter.c
+++ b/src/core/ext/load_reporting/load_reporting_filter.c
@@ -31,23 +31,27 @@
  *
  */
 
+#include <string.h>
+
+#include <grpc/load_reporting.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
-#include <string.h>
 
 #include "src/core/ext/load_reporting/load_reporting.h"
 #include "src/core/ext/load_reporting/load_reporting_filter.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/static_metadata.h"
 
 typedef struct call_data {
   intptr_t id; /**< an id unique to the call */
-  char *trailing_md_string;
-  char *initial_md_string;
-  const char *service_method;
+  bool have_initial_md_string;
+  grpc_slice initial_md_string;
+  bool have_service_method;
+  grpc_slice service_method;
 
   /* stores the recv_initial_metadata op's ready closure, which we wrap with our
    * own (on_initial_md_ready) in order to capture the incoming initial metadata
@@ -63,42 +67,28 @@
   intptr_t id; /**< an id unique to the channel */
 } channel_data;
 
-typedef struct {
-  grpc_call_element *elem;
-  grpc_exec_ctx *exec_ctx;
-} recv_md_filter_args;
-
-static grpc_mdelem *recv_md_filter(grpc_exec_ctx *exec_ctx, void *user_data,
-                                   grpc_mdelem *md) {
-  recv_md_filter_args *a = user_data;
-  grpc_call_element *elem = a->elem;
-  call_data *calld = elem->call_data;
-
-  if (md->key == GRPC_MDSTR_PATH) {
-    calld->service_method = grpc_mdstr_as_c_string(md->value);
-  } else if (md->key == GRPC_MDSTR_LB_TOKEN) {
-    calld->initial_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value));
-    return NULL;
-  }
-
-  return md;
-}
-
 static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data,
                                 grpc_error *err) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
 
   if (err == GRPC_ERROR_NONE) {
-    recv_md_filter_args a;
-    a.elem = elem;
-    a.exec_ctx = exec_ctx;
-    grpc_metadata_batch_filter(exec_ctx, calld->recv_initial_metadata,
-                               recv_md_filter, &a);
-    if (calld->service_method == NULL) {
+    if (calld->recv_initial_metadata->idx.named.path != NULL) {
+      calld->service_method = grpc_slice_ref_internal(
+          GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md));
+      calld->have_service_method = true;
+    } else {
       err =
           grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header"));
     }
+    if (calld->recv_initial_metadata->idx.named.lb_token != NULL) {
+      calld->initial_md_string = grpc_slice_ref_internal(
+          GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.lb_token->md));
+      calld->have_initial_md_string = true;
+      grpc_metadata_batch_remove(
+          exec_ctx, calld->recv_initial_metadata,
+          calld->recv_initial_metadata->idx.named.lb_token);
+    }
   } else {
     GRPC_ERROR_REF(err);
   }
@@ -110,10 +100,8 @@
 /* Constructor for call_data */
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
-  memset(calld, 0, sizeof(call_data));
-
   calld->id = (intptr_t)args->call_stack;
   grpc_closure_init(&calld->on_initial_md_ready, on_initial_md_ready, elem,
                     grpc_schedule_on_exec_ctx);
@@ -149,8 +137,12 @@
                                                 calld->service_method};
   */
 
-  gpr_free(calld->initial_md_string);
-  gpr_free(calld->trailing_md_string);
+  if (calld->have_initial_md_string) {
+    grpc_slice_unref_internal(exec_ctx, calld->initial_md_string);
+  }
+  if (calld->have_service_method) {
+    grpc_slice_unref_internal(exec_ctx, calld->service_method);
+  }
 }
 
 /* Constructor for channel_data */
@@ -160,8 +152,6 @@
   GPR_ASSERT(!args->is_last);
 
   channel_data *chand = elem->channel_data;
-  memset(chand, 0, sizeof(channel_data));
-
   chand->id = (intptr_t)args->channel_stack;
 
   /* TODO(dgq): do something with the data
@@ -193,19 +183,6 @@
   */
 }
 
-static grpc_mdelem *lr_trailing_md_filter(grpc_exec_ctx *exec_ctx,
-                                          void *user_data, grpc_mdelem *md) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-
-  if (md->key == GRPC_MDSTR_LB_COST_BIN) {
-    calld->trailing_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value));
-    return NULL;
-  }
-
-  return md;
-}
-
 static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
                                          grpc_call_element *elem,
                                          grpc_transport_stream_op *op) {
@@ -217,9 +194,6 @@
     /* substitute our callback for the higher callback */
     calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready;
     op->recv_initial_metadata_ready = &calld->on_initial_md_ready;
-  } else if (op->send_trailing_metadata) {
-    grpc_metadata_batch_filter(exec_ctx, op->send_trailing_metadata,
-                               lr_trailing_md_filter, elem);
   }
   grpc_call_next_op(exec_ctx, elem, op);
 
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index 655d9dc..d227c19 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -37,10 +37,10 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/ext/client_channel/http_connect_handshaker.h"
 #include "src/core/ext/client_channel/lb_policy_registry.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/support/backoff.h"
@@ -64,8 +64,6 @@
   /** pollset_set to drive the name resolution process */
   grpc_pollset_set *interested_parties;
 
-  /** mutex guarding the rest of the state */
-  gpr_mu mu;
   /** are we currently resolving? */
   bool resolving;
   /** which version of the result have we published? */
@@ -96,18 +94,20 @@
 static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
                                          dns_resolver *r);
 
-static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
-                     grpc_channel_args **target_result,
-                     grpc_closure *on_complete);
+static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+                                         grpc_resolver *r);
+static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+                            grpc_channel_args **target_result,
+                            grpc_closure *on_complete);
 
 static const grpc_resolver_vtable dns_resolver_vtable = {
-    dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
+    dns_destroy, dns_shutdown_locked, dns_channel_saw_error_locked,
+    dns_next_locked};
 
-static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
+static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx,
+                                grpc_resolver *resolver) {
   dns_resolver *r = (dns_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
   if (r->have_retry_timer) {
     grpc_timer_cancel(exec_ctx, &r->retry_timer);
   }
@@ -117,25 +117,21 @@
                        GRPC_ERROR_CREATE("Resolver Shutdown"));
     r->next_completion = NULL;
   }
-  gpr_mu_unlock(&r->mu);
 }
 
-static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                  grpc_resolver *resolver) {
+static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+                                         grpc_resolver *resolver) {
   dns_resolver *r = (dns_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
   if (!r->resolving) {
     gpr_backoff_reset(&r->backoff_state);
     dns_start_resolving_locked(exec_ctx, r);
   }
-  gpr_mu_unlock(&r->mu);
 }
 
-static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                     grpc_channel_args **target_result,
-                     grpc_closure *on_complete) {
+static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+                            grpc_channel_args **target_result,
+                            grpc_closure *on_complete) {
   dns_resolver *r = (dns_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
   GPR_ASSERT(!r->next_completion);
   r->next_completion = on_complete;
   r->target_result = target_result;
@@ -145,30 +141,26 @@
   } else {
     dns_maybe_finish_next_locked(exec_ctx, r);
   }
-  gpr_mu_unlock(&r->mu);
 }
 
-static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
-                               grpc_error *error) {
+static void dns_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                      grpc_error *error) {
   dns_resolver *r = arg;
 
-  gpr_mu_lock(&r->mu);
   r->have_retry_timer = false;
   if (error == GRPC_ERROR_NONE) {
     if (!r->resolving) {
       dns_start_resolving_locked(exec_ctx, r);
     }
   }
-  gpr_mu_unlock(&r->mu);
 
   GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
 }
 
-static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
-                            grpc_error *error) {
+static void dns_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                   grpc_error *error) {
   dns_resolver *r = arg;
   grpc_channel_args *result = NULL;
-  gpr_mu_lock(&r->mu);
   GPR_ASSERT(r->resolving);
   r->resolving = false;
   if (r->addresses != NULL) {
@@ -188,9 +180,8 @@
     gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
     gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
     gpr_timespec timeout = gpr_time_sub(next_try, now);
-    const char *msg = grpc_error_string(error);
-    gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", msg);
-    grpc_error_free_string(msg);
+    gpr_log(GPR_INFO, "dns resolution failed (will retry): %s",
+            grpc_error_string(error));
     GPR_ASSERT(!r->have_retry_timer);
     r->have_retry_timer = true;
     GRPC_RESOLVER_REF(&r->base, "retry-timer");
@@ -200,8 +191,8 @@
     } else {
       gpr_log(GPR_DEBUG, "retrying immediately");
     }
-    grpc_closure_init(&r->on_retry, dns_on_retry_timer, r,
-                      grpc_schedule_on_exec_ctx);
+    grpc_closure_init(&r->on_retry, dns_on_retry_timer_locked, r,
+                      grpc_combiner_scheduler(r->base.combiner, false));
     grpc_timer_init(exec_ctx, &r->retry_timer, next_try, &r->on_retry, now);
   }
   if (r->resolved_result != NULL) {
@@ -210,7 +201,6 @@
   r->resolved_result = result;
   r->resolved_version++;
   dns_maybe_finish_next_locked(exec_ctx, r);
-  gpr_mu_unlock(&r->mu);
 
   GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
 }
@@ -223,7 +213,8 @@
   r->addresses = NULL;
   grpc_resolve_address(
       exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties,
-      grpc_closure_create(dns_on_resolved, r, grpc_schedule_on_exec_ctx),
+      grpc_closure_create(dns_on_resolved_locked, r,
+                          grpc_combiner_scheduler(r->base.combiner, false)),
       &r->addresses);
 }
 
@@ -242,11 +233,10 @@
 
 static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
   dns_resolver *r = (dns_resolver *)gr;
-  gpr_mu_destroy(&r->mu);
   if (r->resolved_result != NULL) {
     grpc_channel_args_destroy(exec_ctx, r->resolved_result);
   }
-  grpc_pollset_set_destroy(r->interested_parties);
+  grpc_pollset_set_destroy(exec_ctx, r->interested_parties);
   gpr_free(r->name_to_resolve);
   gpr_free(r->default_port);
   grpc_channel_args_destroy(exec_ctx, r->channel_args);
@@ -261,16 +251,12 @@
     return NULL;
   }
   // Get name from args.
-  const char *path = args->uri->path;
+  char *path = args->uri->path;
   if (path[0] == '/') ++path;
-  // Get proxy name, if any.
-  char *proxy_name = grpc_get_http_proxy_server();
   // Create resolver.
-  dns_resolver *r = gpr_malloc(sizeof(dns_resolver));
-  memset(r, 0, sizeof(*r));
-  gpr_mu_init(&r->mu);
-  grpc_resolver_init(&r->base, &dns_resolver_vtable);
-  r->name_to_resolve = proxy_name == NULL ? gpr_strdup(path) : proxy_name;
+  dns_resolver *r = gpr_zalloc(sizeof(dns_resolver));
+  grpc_resolver_init(&r->base, &dns_resolver_vtable, args->combiner);
+  r->name_to_resolve = gpr_strdup(path);
   r->default_port = gpr_strdup(default_port);
   r->channel_args = grpc_channel_args_copy(args->args);
   r->interested_parties = grpc_pollset_set_create();
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index c146a62..da5923d 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -45,6 +45,7 @@
 #include "src/core/ext/client_channel/parse_address.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/unix_sockets_posix.h"
 #include "src/core/lib/slice/slice_internal.h"
@@ -58,8 +59,6 @@
   grpc_lb_addresses *addresses;
   /** channel args */
   grpc_channel_args *channel_args;
-  /** mutex guarding the rest of the state */
-  gpr_mu mu;
   /** have we published? */
   bool published;
   /** pending next completion, or NULL */
@@ -73,48 +72,43 @@
 static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
                                               sockaddr_resolver *r);
 
-static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                       grpc_resolver *r);
-static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
-                          grpc_channel_args **target_result,
-                          grpc_closure *on_complete);
+static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+                                              grpc_resolver *r);
+static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+                                 grpc_channel_args **target_result,
+                                 grpc_closure *on_complete);
 
 static const grpc_resolver_vtable sockaddr_resolver_vtable = {
-    sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
-    sockaddr_next};
+    sockaddr_destroy, sockaddr_shutdown_locked,
+    sockaddr_channel_saw_error_locked, sockaddr_next_locked};
 
-static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
-                              grpc_resolver *resolver) {
+static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx,
+                                     grpc_resolver *resolver) {
   sockaddr_resolver *r = (sockaddr_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
   if (r->next_completion != NULL) {
     *r->target_result = NULL;
     grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
     r->next_completion = NULL;
   }
-  gpr_mu_unlock(&r->mu);
 }
 
-static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                       grpc_resolver *resolver) {
+static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+                                              grpc_resolver *resolver) {
   sockaddr_resolver *r = (sockaddr_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
   r->published = false;
   sockaddr_maybe_finish_next_locked(exec_ctx, r);
-  gpr_mu_unlock(&r->mu);
 }
 
-static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                          grpc_channel_args **target_result,
-                          grpc_closure *on_complete) {
+static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx,
+                                 grpc_resolver *resolver,
+                                 grpc_channel_args **target_result,
+                                 grpc_closure *on_complete) {
   sockaddr_resolver *r = (sockaddr_resolver *)resolver;
-  gpr_mu_lock(&r->mu);
   GPR_ASSERT(!r->next_completion);
   r->next_completion = on_complete;
   r->target_result = target_result;
   sockaddr_maybe_finish_next_locked(exec_ctx, r);
-  gpr_mu_unlock(&r->mu);
 }
 
 static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@@ -131,7 +125,6 @@
 
 static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
   sockaddr_resolver *r = (sockaddr_resolver *)gr;
-  gpr_mu_destroy(&r->mu);
   grpc_lb_addresses_destroy(exec_ctx, r->addresses);
   grpc_channel_args_destroy(exec_ctx, r->channel_args);
   gpr_free(r);
@@ -182,7 +175,7 @@
   bool errors_found = false;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     grpc_uri ith_uri = *args->uri;
-    char *part_str = grpc_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
+    char *part_str = grpc_slice_to_c_string(path_parts.slices[i]);
     ith_uri.path = part_str;
     if (!parse(&ith_uri, &addresses->addresses[i].address)) {
       errors_found = true; /* GPR_TRUE */
@@ -197,12 +190,10 @@
     return NULL;
   }
   /* Instantiate resolver. */
-  sockaddr_resolver *r = gpr_malloc(sizeof(sockaddr_resolver));
-  memset(r, 0, sizeof(*r));
+  sockaddr_resolver *r = gpr_zalloc(sizeof(sockaddr_resolver));
   r->addresses = addresses;
   r->channel_args = grpc_channel_args_copy(args->args);
-  gpr_mu_init(&r->mu);
-  grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
+  grpc_resolver_init(&r->base, &sockaddr_resolver_vtable, args->combiner);
   return &r->base;
 }
 
diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.c b/src/core/ext/transport/chttp2/client/chttp2_connector.c
index 013c96d..fc5e17d 100644
--- a/src/core/ext/transport/chttp2/client/chttp2_connector.c
+++ b/src/core/ext/transport/chttp2/client/chttp2_connector.c
@@ -92,19 +92,21 @@
 }
 
 static void chttp2_connector_shutdown(grpc_exec_ctx *exec_ctx,
-                                      grpc_connector *con) {
+                                      grpc_connector *con, grpc_error *why) {
   chttp2_connector *c = (chttp2_connector *)con;
   gpr_mu_lock(&c->mu);
   c->shutdown = true;
   if (c->handshake_mgr != NULL) {
-    grpc_handshake_manager_shutdown(exec_ctx, c->handshake_mgr);
+    grpc_handshake_manager_shutdown(exec_ctx, c->handshake_mgr,
+                                    GRPC_ERROR_REF(why));
   }
   // If handshaking is not yet in progress, shutdown the endpoint.
   // Otherwise, the handshaker will do this for us.
   if (!c->connecting && c->endpoint != NULL) {
-    grpc_endpoint_shutdown(exec_ctx, c->endpoint);
+    grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(why));
   }
   gpr_mu_unlock(&c->mu);
+  GRPC_ERROR_UNREF(why);
 }
 
 static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
@@ -121,7 +123,7 @@
       // before destroying them, even if we know that there are no
       // pending read/write callbacks.  This should be fixed, at which
       // point this can be removed.
-      grpc_endpoint_shutdown(exec_ctx, args->endpoint);
+      grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_REF(error));
       grpc_endpoint_destroy(exec_ctx, args->endpoint);
       grpc_channel_args_destroy(exec_ctx, args->args);
       grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer);
@@ -195,7 +197,9 @@
     grpc_closure *notify = c->notify;
     c->notify = NULL;
     grpc_closure_sched(exec_ctx, notify, error);
-    if (c->endpoint != NULL) grpc_endpoint_shutdown(exec_ctx, c->endpoint);
+    if (c->endpoint != NULL) {
+      grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(error));
+    }
     gpr_mu_unlock(&c->mu);
     chttp2_connector_unref(exec_ctx, arg);
   } else {
@@ -244,8 +248,7 @@
     chttp2_connector_connect};
 
 grpc_connector *grpc_chttp2_connector_create() {
-  chttp2_connector *c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
+  chttp2_connector *c = gpr_zalloc(sizeof(*c));
   c->base.vtable = &chttp2_connector_vtable;
   gpr_mu_init(&c->mu);
   gpr_ref_init(&c->refs, 1);
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
index c9f4021..286232f 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -39,6 +39,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/client_channel/client_channel.h"
+#include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/ext/transport/chttp2/client/chttp2_connector.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/api_trace.h"
@@ -63,12 +64,19 @@
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
     const char *target, grpc_client_channel_type type,
     const grpc_channel_args *args) {
+  if (target == NULL) {
+    gpr_log(GPR_ERROR, "cannot create channel with NULL target name");
+    return NULL;
+  }
   // Add channel arg containing the server URI.
   grpc_arg arg;
   arg.type = GRPC_ARG_STRING;
   arg.key = GRPC_ARG_SERVER_URI;
-  arg.value.string = (char *)target;
-  grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
+  arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(target);
+  const char *to_remove[] = {GRPC_ARG_SERVER_URI};
+  grpc_channel_args *new_args =
+      grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
+  gpr_free(arg.value.string);
   grpc_channel *channel = grpc_channel_create(exec_ctx, target, new_args,
                                               GRPC_CLIENT_CHANNEL, NULL);
   grpc_channel_args_destroy(exec_ctx, new_args);
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
index f979d9b..825db68 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
@@ -39,10 +39,16 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/client_channel/client_channel.h"
+#include "src/core/ext/client_channel/resolver_registry.h"
+#include "src/core/ext/client_channel/uri_parser.h"
 #include "src/core/ext/transport/chttp2/client/chttp2_connector.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/transport/lb_targets_info.h"
 #include "src/core/lib/security/transport/security_connector.h"
+#include "src/core/lib/slice/slice_hash_table.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/channel.h"
 
@@ -52,12 +58,114 @@
 static void client_channel_factory_unref(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {}
 
+static grpc_subchannel_args *get_secure_naming_subchannel_args(
+    grpc_exec_ctx *exec_ctx, const grpc_subchannel_args *args) {
+  grpc_channel_credentials *channel_credentials =
+      grpc_channel_credentials_find_in_args(args->args);
+  if (channel_credentials == NULL) {
+    gpr_log(GPR_ERROR,
+            "Can't create subchannel: channel credentials missing for secure "
+            "channel.");
+    return NULL;
+  }
+  // Make sure security connector does not already exist in args.
+  if (grpc_security_connector_find_in_args(args->args) != NULL) {
+    gpr_log(GPR_ERROR,
+            "Can't create subchannel: security connector already present in "
+            "channel args.");
+    return NULL;
+  }
+  // To which address are we connecting? By default, use the server URI.
+  const grpc_arg *server_uri_arg =
+      grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
+  GPR_ASSERT(server_uri_arg != NULL);
+  GPR_ASSERT(server_uri_arg->type == GRPC_ARG_STRING);
+  const char *server_uri_str = server_uri_arg->value.string;
+  GPR_ASSERT(server_uri_str != NULL);
+  grpc_uri *server_uri =
+      grpc_uri_parse(server_uri_str, true /* supress errors */);
+  GPR_ASSERT(server_uri != NULL);
+  const char *server_uri_path;
+  server_uri_path =
+      server_uri->path[0] == '/' ? server_uri->path + 1 : server_uri->path;
+  const grpc_slice_hash_table *targets_info =
+      grpc_lb_targets_info_find_in_args(args->args);
+  char *target_name_to_check = NULL;
+  if (targets_info != NULL) {  // LB channel
+    // Find the balancer name for the target.
+    const char *target_uri_str =
+        grpc_get_subchannel_address_uri_arg(args->args);
+    grpc_uri *target_uri =
+        grpc_uri_parse(target_uri_str, false /* suppress errors */);
+    GPR_ASSERT(target_uri != NULL);
+    if (target_uri->path[0] != '\0') {  // "path" may be empty
+      const grpc_slice key = grpc_slice_from_static_string(
+          target_uri->path[0] == '/' ? target_uri->path + 1 : target_uri->path);
+      const char *value = grpc_slice_hash_table_get(targets_info, key);
+      if (value != NULL) target_name_to_check = gpr_strdup(value);
+      grpc_slice_unref_internal(exec_ctx, key);
+    }
+    if (target_name_to_check == NULL) {
+      // If the target name to check hasn't already been set, fall back to using
+      // SERVER_URI
+      target_name_to_check = gpr_strdup(server_uri_path);
+    }
+    grpc_uri_destroy(target_uri);
+  } else {  // regular channel: the secure name is the original server URI.
+    target_name_to_check = gpr_strdup(server_uri_path);
+  }
+  grpc_uri_destroy(server_uri);
+  GPR_ASSERT(target_name_to_check != NULL);
+  grpc_channel_security_connector *subchannel_security_connector = NULL;
+  // Create the security connector using the credentials and target name.
+  grpc_channel_args *new_args_from_connector = NULL;
+  const grpc_security_status security_status =
+      grpc_channel_credentials_create_security_connector(
+          exec_ctx, channel_credentials, target_name_to_check, args->args,
+          &subchannel_security_connector, &new_args_from_connector);
+  if (security_status != GRPC_SECURITY_OK) {
+    gpr_log(GPR_ERROR,
+            "Failed to create secure subchannel for secure name '%s'",
+            target_name_to_check);
+    gpr_free(target_name_to_check);
+    return NULL;
+  }
+  gpr_free(target_name_to_check);
+  grpc_arg new_security_connector_arg =
+      grpc_security_connector_to_arg(&subchannel_security_connector->base);
+
+  grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
+      new_args_from_connector != NULL ? new_args_from_connector : args->args,
+      &new_security_connector_arg, 1);
+  GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &subchannel_security_connector->base,
+                                "lb_channel_create");
+  if (new_args_from_connector != NULL) {
+    grpc_channel_args_destroy(exec_ctx, new_args_from_connector);
+  }
+  grpc_subchannel_args *final_sc_args = gpr_malloc(sizeof(*final_sc_args));
+  memcpy(final_sc_args, args, sizeof(*args));
+  final_sc_args->args = new_args;
+  return final_sc_args;
+}
+
 static grpc_subchannel *client_channel_factory_create_subchannel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
     const grpc_subchannel_args *args) {
+  grpc_subchannel_args *subchannel_args =
+      get_secure_naming_subchannel_args(exec_ctx, args);
+  if (subchannel_args == NULL) {
+    gpr_log(
+        GPR_ERROR,
+        "Failed to create subchannel arguments during subchannel creation.");
+    return NULL;
+  }
   grpc_connector *connector = grpc_chttp2_connector_create();
-  grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, args);
+  grpc_subchannel *s =
+      grpc_subchannel_create(exec_ctx, connector, subchannel_args);
   grpc_connector_unref(exec_ctx, connector);
+  grpc_channel_args_destroy(exec_ctx,
+                            (grpc_channel_args *)subchannel_args->args);
+  gpr_free(subchannel_args);
   return s;
 }
 
@@ -65,12 +173,19 @@
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
     const char *target, grpc_client_channel_type type,
     const grpc_channel_args *args) {
+  if (target == NULL) {
+    gpr_log(GPR_ERROR, "cannot create channel with NULL target name");
+    return NULL;
+  }
   // Add channel arg containing the server URI.
   grpc_arg arg;
   arg.type = GRPC_ARG_STRING;
   arg.key = GRPC_ARG_SERVER_URI;
-  arg.value.string = (char *)target;
-  grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
+  arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(target);
+  const char *to_remove[] = {GRPC_ARG_SERVER_URI};
+  grpc_channel_args *new_args =
+      grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
+  gpr_free(arg.value.string);
   grpc_channel *channel = grpc_channel_create(exec_ctx, target, new_args,
                                               GRPC_CLIENT_CHANNEL, NULL);
   grpc_channel_args_destroy(exec_ctx, new_args);
@@ -85,10 +200,10 @@
 static grpc_client_channel_factory client_channel_factory = {
     &client_channel_factory_vtable};
 
-/* Create a secure client channel:
-   Asynchronously: - resolve target
-                   - connect to it (trying alternatives as presented)
-                   - perform handshakes */
+// Create a secure client channel:
+//   Asynchronously: - resolve target
+//                   - connect to it (trying alternatives as presented)
+//                   - perform handshakes
 grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
                                          const char *target,
                                          const grpc_channel_args *args,
@@ -97,46 +212,27 @@
   GRPC_API_TRACE(
       "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
       "reserved=%p)",
-      4, (creds, target, args, reserved));
+      4, ((void *)creds, target, (void *)args, (void *)reserved));
   GPR_ASSERT(reserved == NULL);
-  // Make sure security connector does not already exist in args.
-  if (grpc_find_security_connector_in_args(args) != NULL) {
-    gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
+  grpc_channel *channel = NULL;
+  if (creds != NULL) {
+    // Add channel args containing the client channel factory and channel
+    // credentials.
+    grpc_arg args_to_add[] = {
+        grpc_client_channel_factory_create_channel_arg(&client_channel_factory),
+        grpc_channel_credentials_to_arg(creds)};
+    grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
+        args, args_to_add, GPR_ARRAY_SIZE(args_to_add));
+    // Create channel.
+    channel = client_channel_factory_create_channel(
+        &exec_ctx, &client_channel_factory, target,
+        GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
+    // Clean up.
+    grpc_channel_args_destroy(&exec_ctx, new_args);
     grpc_exec_ctx_finish(&exec_ctx);
-    return grpc_lame_client_channel_create(
-        target, GRPC_STATUS_INTERNAL,
-        "Security connector exists in channel args.");
   }
-  // Create security connector and construct new channel args.
-  grpc_channel_security_connector *security_connector;
-  grpc_channel_args *new_args_from_connector;
-  if (grpc_channel_credentials_create_security_connector(
-          &exec_ctx, creds, target, args, &security_connector,
-          &new_args_from_connector) != GRPC_SECURITY_OK) {
-    grpc_exec_ctx_finish(&exec_ctx);
-    return grpc_lame_client_channel_create(
-        target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
-  }
-  // Add channel args containing the client channel factory and security
-  // connector.
-  grpc_arg args_to_add[2];
-  args_to_add[0] =
-      grpc_client_channel_factory_create_channel_arg(&client_channel_factory);
-  args_to_add[1] = grpc_security_connector_to_arg(&security_connector->base);
-  grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
-      new_args_from_connector != NULL ? new_args_from_connector : args,
-      args_to_add, GPR_ARRAY_SIZE(args_to_add));
-  if (new_args_from_connector != NULL) {
-    grpc_channel_args_destroy(&exec_ctx, new_args_from_connector);
-  }
-  // Create channel.
-  grpc_channel *channel = client_channel_factory_create_channel(
-      &exec_ctx, &client_channel_factory, target,
-      GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
-  // Clean up.
-  GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &security_connector->base,
-                                "secure_client_channel_factory_create_channel");
-  grpc_channel_args_destroy(&exec_ctx, new_args);
-  grpc_exec_ctx_finish(&exec_ctx);
-  return channel; /* may be NULL */
+  return channel != NULL ? channel
+                         : grpc_lame_client_channel_create(
+                               target, GRPC_STATUS_INTERNAL,
+                               "Failed to create secure client channel");
 }
diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.c b/src/core/ext/transport/chttp2/server/chttp2_server.c
index 574d1a7..837b9fd 100644
--- a/src/core/ext/transport/chttp2/server/chttp2_server.c
+++ b/src/core/ext/transport/chttp2/server/chttp2_server.c
@@ -55,11 +55,6 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/server.h"
 
-typedef struct pending_handshake_manager_node {
-  grpc_handshake_manager *handshake_mgr;
-  struct pending_handshake_manager_node *next;
-} pending_handshake_manager_node;
-
 typedef struct {
   grpc_server *server;
   grpc_tcp_server *tcp_server;
@@ -68,7 +63,7 @@
   bool shutdown;
   grpc_closure tcp_server_shutdown_complete;
   grpc_closure *server_destroy_listener_done;
-  pending_handshake_manager_node *pending_handshake_mgrs;
+  grpc_handshake_manager *pending_handshake_mgrs;
 } server_state;
 
 typedef struct {
@@ -78,41 +73,6 @@
   grpc_handshake_manager *handshake_mgr;
 } server_connection_state;
 
-static void pending_handshake_manager_add_locked(
-    server_state *state, grpc_handshake_manager *handshake_mgr) {
-  pending_handshake_manager_node *node = gpr_malloc(sizeof(*node));
-  node->handshake_mgr = handshake_mgr;
-  node->next = state->pending_handshake_mgrs;
-  state->pending_handshake_mgrs = node;
-}
-
-static void pending_handshake_manager_remove_locked(
-    server_state *state, grpc_handshake_manager *handshake_mgr) {
-  pending_handshake_manager_node **prev_node = &state->pending_handshake_mgrs;
-  for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
-       node != NULL; node = node->next) {
-    if (node->handshake_mgr == handshake_mgr) {
-      *prev_node = node->next;
-      gpr_free(node);
-      break;
-    }
-    prev_node = &node->next;
-  }
-}
-
-static void pending_handshake_manager_shutdown_locked(grpc_exec_ctx *exec_ctx,
-                                                      server_state *state) {
-  pending_handshake_manager_node *prev_node = NULL;
-  for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
-       node != NULL; node = node->next) {
-    grpc_handshake_manager_shutdown(exec_ctx, node->handshake_mgr);
-    gpr_free(prev_node);
-    prev_node = node;
-  }
-  gpr_free(prev_node);
-  state->pending_handshake_mgrs = NULL;
-}
-
 static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
                               grpc_error *error) {
   grpc_handshaker_args *args = arg;
@@ -121,7 +81,7 @@
   if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) {
     const char *error_str = grpc_error_string(error);
     gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
-    grpc_error_free_string(error_str);
+
     if (error == GRPC_ERROR_NONE && args->endpoint != NULL) {
       // We were shut down after handshaking completed successfully, so
       // destroy the endpoint here.
@@ -129,7 +89,7 @@
       // before destroying them, even if we know that there are no
       // pending read/write callbacks.  This should be fixed, at which
       // point this can be removed.
-      grpc_endpoint_shutdown(exec_ctx, args->endpoint);
+      grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE);
       grpc_endpoint_destroy(exec_ctx, args->endpoint);
       grpc_channel_args_destroy(exec_ctx, args->args);
       grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer);
@@ -150,8 +110,9 @@
       grpc_channel_args_destroy(exec_ctx, args->args);
     }
   }
-  pending_handshake_manager_remove_locked(connection_state->server_state,
-                                          connection_state->handshake_mgr);
+  grpc_handshake_manager_pending_list_remove(
+      &connection_state->server_state->pending_handshake_mgrs,
+      connection_state->handshake_mgr);
   gpr_mu_unlock(&connection_state->server_state->mu);
   grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
   grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server);
@@ -171,7 +132,8 @@
     return;
   }
   grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create();
-  pending_handshake_manager_add_locked(state, handshake_mgr);
+  grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs,
+                                          handshake_mgr);
   gpr_mu_unlock(&state->mu);
   grpc_tcp_server_ref(state->tcp_server);
   server_connection_state *connection_state =
@@ -210,7 +172,8 @@
   gpr_mu_lock(&state->mu);
   grpc_closure *destroy_done = state->server_destroy_listener_done;
   GPR_ASSERT(state->shutdown);
-  pending_handshake_manager_shutdown_locked(exec_ctx, state);
+  grpc_handshake_manager_pending_list_shutdown_all(
+      exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error));
   gpr_mu_unlock(&state->mu);
   // Flush queued work before destroying handshaker factory, since that
   // may do a synchronous unref.
@@ -259,8 +222,7 @@
   if (err != GRPC_ERROR_NONE) {
     goto error;
   }
-  state = gpr_malloc(sizeof(*state));
-  memset(state, 0, sizeof(*state));
+  state = gpr_zalloc(sizeof(*state));
   grpc_closure_init(&state->tcp_server_shutdown_complete,
                     tcp_server_shutdown_complete, state,
                     grpc_schedule_on_exec_ctx);
@@ -307,7 +269,7 @@
 
     const char *warning_message = grpc_error_string(err);
     gpr_log(GPR_INFO, "WARNING: %s", warning_message);
-    grpc_error_free_string(warning_message);
+
     /* we managed to bind some addresses: continue */
   }
   grpc_resolved_addresses_destroy(resolved);
diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
index bf5026b..c219a7d 100644
--- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
@@ -51,7 +51,7 @@
   if (err != GRPC_ERROR_NONE) {
     const char *msg = grpc_error_string(err);
     gpr_log(GPR_ERROR, "%s", msg);
-    grpc_error_free_string(msg);
+
     GRPC_ERROR_UNREF(err);
   }
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
index 395c79a..cb2b3f5 100644
--- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
+++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
@@ -94,7 +94,7 @@
   if (err != GRPC_ERROR_NONE) {
     const char *msg = grpc_error_string(err);
     gpr_log(GPR_ERROR, "%s", msg);
-    grpc_error_free_string(msg);
+
     GRPC_ERROR_UNREF(err);
   }
   return port_num;
diff --git a/src/core/ext/transport/chttp2/transport/bin_decoder.c b/src/core/ext/transport/chttp2/transport/bin_decoder.c
index 8db36e4..8c87de1 100644
--- a/src/core/ext/transport/chttp2/transport/bin_decoder.c
+++ b/src/core/ext/transport/chttp2/transport/bin_decoder.c
@@ -157,7 +157,7 @@
             "grpc_chttp2_base64_decode has a length of %d, which is not a "
             "multiple of 4.\n",
             (int)input_length);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
 
   if (input_length > 0) {
@@ -178,11 +178,11 @@
   ctx.contains_tail = false;
 
   if (!grpc_base64_decode_partial(&ctx)) {
-    char *s = grpc_dump_slice(input, GPR_DUMP_ASCII);
+    char *s = grpc_slice_to_c_string(input);
     gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
     gpr_free(s);
     grpc_slice_unref_internal(exec_ctx, output);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
   GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
   GPR_ASSERT(ctx.input_cur == GRPC_SLICE_END_PTR(input));
@@ -204,7 +204,7 @@
             "has a tail of 1 byte.\n",
             (int)input_length);
     grpc_slice_unref_internal(exec_ctx, output);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
 
   if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) {
@@ -214,7 +214,7 @@
             (int)output_length,
             (int)(input_length / 4 * 3 + tail_xtra[input_length % 4]));
     grpc_slice_unref_internal(exec_ctx, output);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
 
   ctx.input_cur = GRPC_SLICE_START_PTR(input);
@@ -224,11 +224,11 @@
   ctx.contains_tail = true;
 
   if (!grpc_base64_decode_partial(&ctx)) {
-    char *s = grpc_dump_slice(input, GPR_DUMP_ASCII);
+    char *s = grpc_slice_to_c_string(input);
     gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
     gpr_free(s);
     grpc_slice_unref_internal(exec_ctx, output);
-    return gpr_empty_slice();
+    return grpc_empty_slice();
   }
   GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
   GPR_ASSERT(ctx.input_cur <= GRPC_SLICE_END_PTR(input));
diff --git a/src/core/ext/transport/chttp2/transport/bin_encoder.c b/src/core/ext/transport/chttp2/transport/bin_encoder.c
index af25a43..e301c07 100644
--- a/src/core/ext/transport/chttp2/transport/bin_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/bin_encoder.c
@@ -177,8 +177,7 @@
   enc_flush_some(out);
 }
 
-grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(
-    grpc_slice input) {
+grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input) {
   size_t input_length = GRPC_SLICE_LENGTH(input);
   size_t input_triplets = input_length / 3;
   size_t tail_case = input_length % 3;
diff --git a/src/core/ext/transport/chttp2/transport/bin_encoder.h b/src/core/ext/transport/chttp2/transport/bin_encoder.h
index 477559d..0f899c8 100644
--- a/src/core/ext/transport/chttp2/transport/bin_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/bin_encoder.h
@@ -49,7 +49,6 @@
    grpc_slice y = grpc_chttp2_huffman_compress(x);
    grpc_slice_unref_internal(exec_ctx, x);
    return y; */
-grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(
-    grpc_slice input);
+grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input);
 
 #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
index bd87253..59b21e3 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_plugin.c
@@ -31,14 +31,11 @@
  *
  */
 
-#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/transport/metadata.h"
 
 void grpc_chttp2_plugin_init(void) {
-  grpc_chttp2_base64_encode_and_huffman_compress =
-      grpc_chttp2_base64_encode_and_huffman_compress_impl;
   grpc_register_tracer("http", &grpc_http_trace);
   grpc_register_tracer("flowctl", &grpc_flowctl_trace);
 }
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 68a6a21..da4c7dc 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -44,19 +44,23 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
 #include "src/core/ext/transport/chttp2/transport/internal.h"
-#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
 #include "src/core/ext/transport/chttp2/transport/varint.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/iomgr/workqueue.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
+#include "src/core/lib/support/env.h"
 #include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/error_utils.h"
+#include "src/core/lib/transport/http2_errors.h"
 #include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/status_conversion.h"
 #include "src/core/lib/transport/timeout_encoding.h"
+#include "src/core/lib/transport/transport.h"
 #include "src/core/lib/transport/transport_impl.h"
 
 #define DEFAULT_WINDOW 65535
@@ -65,6 +69,10 @@
 #define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
 #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
 
+#define DEFAULT_KEEPALIVE_TIME_SECOND INT_MAX
+#define DEFAULT_KEEPALIVE_TIMEOUT_SECOND 20
+#define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false
+
 #define MAX_CLIENT_STREAM_ID 0x7fffffffu
 int grpc_http_trace = 0;
 int grpc_flowctl_trace = 0;
@@ -123,6 +131,31 @@
 static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
                               grpc_error *error);
 
+static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
+                                  grpc_error *error);
+static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
+                                   grpc_error *error);
+
+static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                         grpc_error *error);
+static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                             grpc_chttp2_ping_type ping_type,
+                             grpc_closure *on_initiate,
+                             grpc_closure *on_complete);
+
+#define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0
+#define DEFAULT_MAX_PINGS_BETWEEN_DATA 3
+
+/** keepalive-relevant functions */
+static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                       grpc_error *error);
+static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                        grpc_error *error);
+static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                         grpc_error *error);
+static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                            grpc_error *error);
+
 /*******************************************************************************
  * CONSTRUCTION/DESTRUCTION/REFCOUNTING
  */
@@ -152,18 +185,9 @@
   grpc_chttp2_stream_map_destroy(&t->stream_map);
   grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
 
-  grpc_combiner_destroy(exec_ctx, t->combiner);
+  GRPC_COMBINER_UNREF(exec_ctx, t->combiner, "chttp2_transport");
 
-  /* callback remaining pings: they're not allowed to call into the transpot,
-     and maybe they hold resources that need to be freed */
-  while (t->pings.next != &t->pings) {
-    grpc_chttp2_outstanding_ping *ping = t->pings.next;
-    grpc_closure_sched(exec_ctx, ping->on_recv,
-                       GRPC_ERROR_CREATE("Transport closed"));
-    ping->next->prev = ping->prev;
-    ping->prev->next = ping->next;
-    gpr_free(ping);
-  }
+  cancel_pings(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
 
   while (t->write_cb_pool) {
     grpc_chttp2_write_cb *next = t->write_cb_pool->next;
@@ -171,6 +195,7 @@
     t->write_cb_pool = next;
   }
 
+  gpr_free(t->ping_acks);
   gpr_free(t->peer_string);
   gpr_free(t);
 }
@@ -210,8 +235,6 @@
   GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
              GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
 
-  memset(t, 0, sizeof(*t));
-
   t->base.vtable = &vtable;
   t->ep = ep;
   /* one ref is for destroy */
@@ -223,10 +246,6 @@
   t->is_client = is_client;
   t->outgoing_window = DEFAULT_WINDOW;
   t->incoming_window = DEFAULT_WINDOW;
-  t->stream_lookahead = DEFAULT_WINDOW;
-  t->connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
-  t->ping_counter = 1;
-  t->pings.next = t->pings.prev = &t->pings;
   t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
   t->is_first_frame = true;
   grpc_connectivity_state_init(
@@ -247,6 +266,33 @@
   grpc_closure_init(&t->destructive_reclaimer_locked,
                     destructive_reclaimer_locked, t,
                     grpc_combiner_scheduler(t->combiner, false));
+  grpc_closure_init(&t->start_bdp_ping_locked, start_bdp_ping_locked, t,
+                    grpc_combiner_scheduler(t->combiner, false));
+  grpc_closure_init(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t,
+                    grpc_combiner_scheduler(t->combiner, false));
+  grpc_closure_init(&t->init_keepalive_ping_locked, init_keepalive_ping_locked,
+                    t, grpc_combiner_scheduler(t->combiner, false));
+  grpc_closure_init(&t->start_keepalive_ping_locked,
+                    start_keepalive_ping_locked, t,
+                    grpc_combiner_scheduler(t->combiner, false));
+  grpc_closure_init(&t->finish_keepalive_ping_locked,
+                    finish_keepalive_ping_locked, t,
+                    grpc_combiner_scheduler(t->combiner, false));
+  grpc_closure_init(&t->keepalive_watchdog_fired_locked,
+                    keepalive_watchdog_fired_locked, t,
+                    grpc_combiner_scheduler(t->combiner, false));
+
+  grpc_bdp_estimator_init(&t->bdp_estimator, t->peer_string);
+  t->last_pid_update = gpr_now(GPR_CLOCK_MONOTONIC);
+  grpc_pid_controller_init(
+      &t->pid_controller,
+      (grpc_pid_controller_args){.gain_p = 4,
+                                 .gain_i = 8,
+                                 .gain_d = 0,
+                                 .initial_control_value = log2(DEFAULT_WINDOW),
+                                 .min_control_value = -1,
+                                 .max_control_value = 25,
+                                 .integral_range = 10});
 
   grpc_chttp2_goaway_parser_init(&t->goaway_parser);
   grpc_chttp2_hpack_parser_init(exec_ctx, &t->hpack_parser);
@@ -272,6 +318,7 @@
   t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
   t->sent_local_settings = 0;
   t->write_buffer_size = DEFAULT_WINDOW;
+  t->enable_bdp_probe = true;
 
   if (is_client) {
     grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string(
@@ -289,6 +336,24 @@
   push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
                DEFAULT_MAX_HEADER_LIST_SIZE);
 
+  t->ping_policy = (grpc_chttp2_repeated_ping_policy){
+      .max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA,
+      .min_time_between_pings =
+          gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN),
+  };
+
+  /* client-side keepalive setting */
+  t->keepalive_time =
+      DEFAULT_KEEPALIVE_TIME_SECOND == INT_MAX
+          ? gpr_inf_future(GPR_TIMESPAN)
+          : gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIME_SECOND, GPR_TIMESPAN);
+  t->keepalive_timeout =
+      DEFAULT_KEEPALIVE_TIMEOUT_SECOND == INT_MAX
+          ? gpr_inf_future(GPR_TIMESPAN)
+          : gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIMEOUT_SECOND,
+                                  GPR_TIMESPAN);
+  t->keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
+
   if (channel_args) {
     for (i = 0; i < channel_args->num_args; i++) {
       if (0 == strcmp(channel_args->args[i].key,
@@ -306,14 +371,6 @@
           }
         }
       } else if (0 == strcmp(channel_args->args[i].key,
-                             GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) {
-        const grpc_integer_options options = {-1, 5, INT_MAX};
-        const int value =
-            grpc_channel_arg_get_integer(&channel_args->args[i], options);
-        if (value >= 0) {
-          t->stream_lookahead = (uint32_t)value;
-        }
-      } else if (0 == strcmp(channel_args->args[i].key,
                              GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
         const grpc_integer_options options = {-1, 0, INT_MAX};
         const int value =
@@ -323,34 +380,75 @@
                                                            (uint32_t)value);
         }
       } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
+        t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer(
+            &channel_args->args[i],
+            (grpc_integer_options){DEFAULT_MAX_PINGS_BETWEEN_DATA, 0, INT_MAX});
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS)) {
+        t->ping_policy.min_time_between_pings = gpr_time_from_millis(
+            grpc_channel_arg_get_integer(
+                &channel_args->args[i],
+                (grpc_integer_options){DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, 0,
+                                       INT_MAX}),
+            GPR_TIMESPAN);
+      } else if (0 == strcmp(channel_args->args[i].key,
                              GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) {
         t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer(
             &channel_args->args[i],
             (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE});
+      } else if (0 ==
+                 strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) {
+        t->enable_bdp_probe = grpc_channel_arg_get_integer(
+            &channel_args->args[i], (grpc_integer_options){1, 0, 1});
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_KEEPALIVE_TIME)) {
+        const int value = grpc_channel_arg_get_integer(
+            &channel_args->args[i],
+            (grpc_integer_options){DEFAULT_KEEPALIVE_TIME_SECOND, 1, INT_MAX});
+        t->keepalive_time = value == INT_MAX
+                                ? gpr_inf_future(GPR_TIMESPAN)
+                                : gpr_time_from_seconds(value, GPR_TIMESPAN);
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT)) {
+        const int value = grpc_channel_arg_get_integer(
+            &channel_args->args[i],
+            (grpc_integer_options){DEFAULT_KEEPALIVE_TIMEOUT_SECOND, 0,
+                                   INT_MAX});
+        t->keepalive_timeout = value == INT_MAX
+                                   ? gpr_inf_future(GPR_TIMESPAN)
+                                   : gpr_time_from_seconds(value, GPR_TIMESPAN);
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS)) {
+        t->keepalive_permit_without_calls =
+            (uint32_t)grpc_channel_arg_get_integer(
+                &channel_args->args[i], (grpc_integer_options){0, 0, 1});
       } else {
         static const struct {
           const char *channel_arg_name;
           grpc_chttp2_setting_id setting_id;
           grpc_integer_options integer_options;
           bool availability[2] /* server, client */;
-        } settings_map[] = {
-            {GRPC_ARG_MAX_CONCURRENT_STREAMS,
-             GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
-             {-1, 0, INT_MAX},
-             {true, false}},
-            {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
-             GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
-             {-1, 0, INT_MAX},
-             {true, true}},
-            {GRPC_ARG_MAX_METADATA_SIZE,
-             GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
-             {-1, 0, INT_MAX},
-             {true, true}},
-            {GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
-             GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
-             {-1, 16384, 16777215},
-             {true, true}},
-        };
+        } settings_map[] = {{GRPC_ARG_MAX_CONCURRENT_STREAMS,
+                             GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
+                             {-1, 0, INT32_MAX},
+                             {true, false}},
+                            {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
+                             GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
+                             {-1, 0, INT32_MAX},
+                             {true, true}},
+                            {GRPC_ARG_MAX_METADATA_SIZE,
+                             GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
+                             {-1, 0, INT32_MAX},
+                             {true, true}},
+                            {GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
+                             GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
+                             {-1, 16384, 16777215},
+                             {true, true}},
+                            {GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES,
+                             GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
+                             {-1, 5, INT32_MAX},
+                             {true, true}}};
         for (j = 0; j < (int)GPR_ARRAY_SIZE(settings_map); j++) {
           if (0 == strcmp(channel_args->args[i].key,
                           settings_map[j].channel_arg_name)) {
@@ -373,6 +471,19 @@
     }
   }
 
+  t->ping_state.pings_before_data_required =
+      t->ping_policy.max_pings_without_data;
+
+  /** Start client-side keepalive pings */
+  if (t->is_client) {
+    t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
+    GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
+    grpc_timer_init(
+        exec_ctx, &t->keepalive_ping_timer,
+        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
+        &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
+  }
+
   grpc_chttp2_initiate_write(exec_ctx, t, false, "init");
   post_benign_reclaimer(exec_ctx, t);
 }
@@ -409,14 +520,30 @@
           grpc_error_add_child(t->close_transport_on_writes_finished, error);
       return;
     }
-    if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) {
+    if (!grpc_error_has_clear_grpc_status(error)) {
       error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
                                  GRPC_STATUS_UNAVAILABLE);
     }
     t->closed = 1;
     connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
                            GRPC_ERROR_REF(error), "close_transport");
-    grpc_endpoint_shutdown(exec_ctx, t->ep);
+    grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
+    if (t->is_client) {
+      switch (t->keepalive_state) {
+        case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING: {
+          grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
+          break;
+        }
+        case GRPC_CHTTP2_KEEPALIVE_STATE_PINGING: {
+          grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
+          grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer);
+          break;
+        }
+        case GRPC_CHTTP2_KEEPALIVE_STATE_DYING: {
+          break;
+        }
+      }
+    }
 
     /* flush writable stream list to avoid dangling references */
     grpc_chttp2_stream *s;
@@ -424,6 +551,7 @@
       GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:close");
     }
     end_all_the_calls(exec_ctx, t, GRPC_ERROR_REF(error));
+    cancel_pings(exec_ctx, t, GRPC_ERROR_REF(error));
   }
   GRPC_ERROR_UNREF(error);
 }
@@ -452,8 +580,6 @@
   grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
   grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
 
-  memset(s, 0, sizeof(*s));
-
   s->t = t;
   s->refcount = refcount;
   /* We reserve one 'active stream' that's dropped when the stream is
@@ -474,11 +600,6 @@
 
   if (server_data) {
     s->id = (uint32_t)(uintptr_t)server_data;
-    s->outgoing_window = t->settings[GRPC_PEER_SETTINGS]
-                                    [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-    s->incoming_window = s->max_recv_bytes =
-        t->settings[GRPC_SENT_SETTINGS]
-                   [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
     *t->accepting_stream = s;
     grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
     post_destructive_reclaimer(exec_ctx, t);
@@ -507,6 +628,7 @@
   }
 
   grpc_chttp2_list_remove_stalled_by_transport(t, s);
+  grpc_chttp2_list_remove_stalled_by_stream(t, s);
 
   for (int i = 0; i < STREAM_LIST_COUNT; i++) {
     if (s->included[i]) {
@@ -531,6 +653,14 @@
   GRPC_ERROR_UNREF(s->read_closed_error);
   GRPC_ERROR_UNREF(s->write_closed_error);
 
+  if (s->incoming_window_delta > 0) {
+    GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA(
+        "destroy", t, s, s->incoming_window_delta);
+  } else if (s->incoming_window_delta < 0) {
+    GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA(
+        "destroy", t, s, -s->incoming_window_delta);
+  }
+
   GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream");
 
   GPR_TIMER_END("destroy_stream", 0);
@@ -646,13 +776,21 @@
   GPR_TIMER_END("grpc_chttp2_initiate_write", 0);
 }
 
-void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
-                                 grpc_chttp2_transport *t,
-                                 grpc_chttp2_stream *s, bool covered_by_poller,
-                                 const char *reason) {
+void grpc_chttp2_become_writable(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
+    grpc_chttp2_stream_write_type stream_write_type, const char *reason) {
   if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
     GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become");
-    grpc_chttp2_initiate_write(exec_ctx, t, covered_by_poller, reason);
+  }
+  switch (stream_write_type) {
+    case GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK:
+      break;
+    case GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED:
+      grpc_chttp2_initiate_write(exec_ctx, t, true, reason);
+      break;
+    case GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED:
+      grpc_chttp2_initiate_write(exec_ctx, t, false, reason);
+      break;
   }
 }
 
@@ -780,7 +918,6 @@
 static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
                                      grpc_chttp2_transport *t) {
   grpc_chttp2_stream *s;
-  uint32_t stream_incoming_window;
   /* start streams where we have free grpc_chttp2_stream ids and free
    * concurrency */
   while (t->next_stream_id <= MAX_CLIENT_STREAM_ID &&
@@ -803,15 +940,11 @@
                              "no_more_stream_ids");
     }
 
-    s->outgoing_window = t->settings[GRPC_PEER_SETTINGS]
-                                    [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-    s->incoming_window = stream_incoming_window =
-        t->settings[GRPC_SENT_SETTINGS]
-                   [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-    s->max_recv_bytes = GPR_MAX(stream_incoming_window, s->max_recv_bytes);
     grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
     post_destructive_reclaimer(exec_ctx, t);
-    grpc_chttp2_become_writable(exec_ctx, t, s, true, "new_stream");
+    grpc_chttp2_become_writable(exec_ctx, t, s,
+                                GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
+                                "new_stream");
   }
   /* cancel out streams that will never be started */
   while (t->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@@ -866,7 +999,6 @@
             (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT),
             (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT),
             desc, errstr);
-    grpc_error_free_string(errstr);
   }
   if (error != GRPC_ERROR_NONE) {
     if (closure->error_data.error == GRPC_ERROR_NONE) {
@@ -895,12 +1027,9 @@
 }
 
 static bool contains_non_ok_status(grpc_metadata_batch *batch) {
-  grpc_linked_mdelem *l;
-  for (l = batch->list.head; l; l = l->next) {
-    if (l->md->key == GRPC_MDSTR_GRPC_STATUS &&
-        l->md != GRPC_MDELEM_GRPC_STATUS_0) {
-      return true;
-    }
+  if (batch->idx.named.grpc_status != NULL) {
+    return !grpc_mdelem_eq(batch->idx.named.grpc_status->md,
+                           GRPC_MDELEM_GRPC_STATUS_0);
   }
   return false;
 }
@@ -910,7 +1039,9 @@
                                                   grpc_chttp2_stream *s) {
   if (s->id != 0 && (!s->write_buffering ||
                      s->flow_controlled_buffer.length > t->write_buffer_size)) {
-    grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message");
+    grpc_chttp2_become_writable(exec_ctx, t, s,
+                                GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
+                                "op.send_message");
   }
 }
 
@@ -980,9 +1111,12 @@
                          bool is_client, bool is_initial) {
   for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail;
        md = md->next) {
+    char *key = grpc_slice_to_c_string(GRPC_MDKEY(md->md));
+    char *value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md));
     gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL",
-            is_client ? "CLI" : "SVR", grpc_mdstr_as_c_string(md->md->key),
-            grpc_mdstr_as_c_string(md->md->value));
+            is_client ? "CLI" : "SVR", key, value);
+    gpr_free(key);
+    gpr_free(value);
   }
 }
 
@@ -991,8 +1125,8 @@
   GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
 
   grpc_transport_stream_op *op = stream_op;
-  grpc_chttp2_transport *t = op->transport_private.args[0];
-  grpc_chttp2_stream *s = op->transport_private.args[1];
+  grpc_chttp2_transport *t = op->handler_private.args[0];
+  grpc_chttp2_stream *s = op->handler_private.args[1];
 
   if (grpc_http_trace) {
     char *str = grpc_transport_stream_op_string(op);
@@ -1025,11 +1159,7 @@
   }
 
   if (op->cancel_error != GRPC_ERROR_NONE) {
-    grpc_chttp2_cancel_stream(exec_ctx, t, s, GRPC_ERROR_REF(op->cancel_error));
-  }
-
-  if (op->close_error != GRPC_ERROR_NONE) {
-    close_from_api(exec_ctx, t, s, GRPC_ERROR_REF(op->close_error));
+    grpc_chttp2_cancel_stream(exec_ctx, t, s, op->cancel_error);
   }
 
   if (op->send_initial_metadata != NULL) {
@@ -1068,20 +1198,25 @@
             grpc_chttp2_list_add_waiting_for_concurrency(t, s);
             maybe_start_some_streams(exec_ctx, t);
           } else {
-            grpc_chttp2_cancel_stream(exec_ctx, t, s,
-                                      GRPC_ERROR_CREATE("Transport closed"));
+            grpc_chttp2_cancel_stream(
+                exec_ctx, t, s,
+                grpc_error_set_int(GRPC_ERROR_CREATE("Transport closed"),
+                                   GRPC_ERROR_INT_GRPC_STATUS,
+                                   GRPC_STATUS_UNAVAILABLE));
           }
         } else {
           GPR_ASSERT(s->id != 0);
-          grpc_chttp2_become_writable(exec_ctx, t, s, true,
+          grpc_chttp2_become_writable(exec_ctx, t, s,
+                                      GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
                                       "op.send_initial_metadata");
         }
       } else {
         s->send_initial_metadata = NULL;
         grpc_chttp2_complete_closure_step(
             exec_ctx, t, s, &s->send_initial_metadata_finished,
-            GRPC_ERROR_CREATE(
-                "Attempt to send initial metadata after stream was closed"),
+            GRPC_ERROR_CREATE_REFERENCING(
+                "Attempt to send initial metadata after stream was closed",
+                &s->write_closed_error, 1),
             "send_initial_metadata_finished");
       }
     }
@@ -1093,7 +1228,9 @@
     if (s->write_closed) {
       grpc_chttp2_complete_closure_step(
           exec_ctx, t, s, &s->fetching_send_message_finished,
-          GRPC_ERROR_CREATE("Attempt to send message after stream was closed"),
+          GRPC_ERROR_CREATE_REFERENCING(
+              "Attempt to send message after stream was closed",
+              &s->write_closed_error, 1),
           "fetching_send_message_finished");
     } else {
       GPR_ASSERT(s->fetching_send_message == NULL);
@@ -1161,7 +1298,8 @@
       } else if (s->id != 0) {
         /* TODO(ctiller): check if there's flow control for any outstanding
            bytes before going writable */
-        grpc_chttp2_become_writable(exec_ctx, t, s, true,
+        grpc_chttp2_become_writable(exec_ctx, t, s,
+                                    GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
                                     "op.send_trailing_metadata");
       }
     }
@@ -1180,8 +1318,7 @@
     s->recv_message = op->recv_message;
     if (s->id != 0 &&
         (s->incoming_frames.head == NULL || s->incoming_frames.head->is_tail)) {
-      incoming_byte_stream_update_flow_control(exec_ctx, t, s,
-                                               t->stream_lookahead, 0);
+      incoming_byte_stream_update_flow_control(exec_ctx, t, s, 5, 0);
     }
     grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
   }
@@ -1213,63 +1350,71 @@
     gpr_free(str);
   }
 
-  op->transport_private.args[0] = gt;
-  op->transport_private.args[1] = gs;
+  op->handler_private.args[0] = gt;
+  op->handler_private.args[1] = gs;
   GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
   grpc_closure_sched(
       exec_ctx,
       grpc_closure_init(
-          &op->transport_private.closure, perform_stream_op_locked, op,
+          &op->handler_private.closure, perform_stream_op_locked, op,
           grpc_combiner_scheduler(t->combiner, op->covered_by_poller)),
       GRPC_ERROR_NONE);
   GPR_TIMER_END("perform_stream_op", 0);
 }
 
+static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                         grpc_error *error) {
+  /* callback remaining pings: they're not allowed to call into the transpot,
+     and maybe they hold resources that need to be freed */
+  for (size_t i = 0; i < GRPC_CHTTP2_PING_TYPE_COUNT; i++) {
+    grpc_chttp2_ping_queue *pq = &t->ping_queues[i];
+    for (size_t j = 0; j < GRPC_CHTTP2_PCL_COUNT; j++) {
+      grpc_closure_list_fail_all(&pq->lists[j], GRPC_ERROR_REF(error));
+      grpc_closure_list_sched(exec_ctx, &pq->lists[j]);
+    }
+  }
+  GRPC_ERROR_UNREF(error);
+}
+
 static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                             grpc_closure *on_recv) {
-  grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p));
-  p->next = &t->pings;
-  p->prev = p->next->prev;
-  p->prev->next = p->next->prev = p;
-  p->id[0] = (uint8_t)((t->ping_counter >> 56) & 0xff);
-  p->id[1] = (uint8_t)((t->ping_counter >> 48) & 0xff);
-  p->id[2] = (uint8_t)((t->ping_counter >> 40) & 0xff);
-  p->id[3] = (uint8_t)((t->ping_counter >> 32) & 0xff);
-  p->id[4] = (uint8_t)((t->ping_counter >> 24) & 0xff);
-  p->id[5] = (uint8_t)((t->ping_counter >> 16) & 0xff);
-  p->id[6] = (uint8_t)((t->ping_counter >> 8) & 0xff);
-  p->id[7] = (uint8_t)(t->ping_counter & 0xff);
-  t->ping_counter++;
-  p->on_recv = on_recv;
-  grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_ping_create(0, p->id));
-  grpc_chttp2_initiate_write(exec_ctx, t, true, "send_ping");
+                             grpc_chttp2_ping_type ping_type,
+                             grpc_closure *on_initiate, grpc_closure *on_ack) {
+  grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type];
+  grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate,
+                           GRPC_ERROR_NONE);
+  if (grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack,
+                               GRPC_ERROR_NONE)) {
+    grpc_chttp2_initiate_write(exec_ctx, t, false, "send_ping");
+  }
 }
 
 void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                          const uint8_t *opaque_8bytes) {
-  grpc_chttp2_outstanding_ping *ping;
-  for (ping = t->pings.next; ping != &t->pings; ping = ping->next) {
-    if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
-      grpc_closure_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE);
-      ping->next->prev = ping->prev;
-      ping->prev->next = ping->next;
-      gpr_free(ping);
-      return;
-    }
+                          uint64_t id) {
+  grpc_chttp2_ping_queue *pq =
+      &t->ping_queues[id % GRPC_CHTTP2_PING_TYPE_COUNT];
+  if (pq->inflight_id != id) {
+    char *from = grpc_endpoint_get_peer(t->ep);
+    gpr_log(GPR_DEBUG, "Unknown ping response from %s: %" PRIx64, from, id);
+    gpr_free(from);
+    return;
   }
-  char *msg = gpr_dump((const char *)opaque_8bytes, 8, GPR_DUMP_HEX);
-  char *from = grpc_endpoint_get_peer(t->ep);
-  gpr_log(GPR_DEBUG, "Unknown ping response from %s: %s", from, msg);
-  gpr_free(from);
-  gpr_free(msg);
+  grpc_closure_list_sched(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
+  if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
+    grpc_chttp2_initiate_write(exec_ctx, t, false, "continue_pings");
+  }
 }
 
 static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                        grpc_chttp2_error_code error, grpc_slice data) {
+                        grpc_error *error) {
   t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED;
-  grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)error, data,
-                            &t->qbuf);
+  grpc_http2_error_code http_error;
+  const char *msg;
+  grpc_error_get_status(error, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL, &msg,
+                        &http_error);
+  grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error,
+                            grpc_slice_from_copied_string(msg), &t->qbuf);
   grpc_chttp2_initiate_write(exec_ctx, t, false, "goaway_sent");
+  GRPC_ERROR_UNREF(error);
 }
 
 static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
@@ -1285,10 +1430,8 @@
         op->on_connectivity_state_change);
   }
 
-  if (op->send_goaway) {
-    send_goaway(exec_ctx, t,
-                grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
-                grpc_slice_ref_internal(*op->goaway_message));
+  if (op->goaway_error) {
+    send_goaway(exec_ctx, t, op->goaway_error);
   }
 
   if (op->set_accept_stream) {
@@ -1306,7 +1449,8 @@
   }
 
   if (op->send_ping) {
-    send_ping_locked(exec_ctx, t, op->send_ping);
+    send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, NULL,
+                     op->send_ping);
   }
 
   if (close_transport != GRPC_ERROR_NONE) {
@@ -1348,8 +1492,8 @@
         incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE);
       }
     }
-    grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[0],
-                                                 s->recv_initial_metadata);
+    grpc_chttp2_incoming_metadata_buffer_publish(
+        exec_ctx, &s->metadata_buffer[0], s->recv_initial_metadata);
     null_then_run_closure(exec_ctx, &s->recv_initial_metadata_ready,
                           GRPC_ERROR_NONE);
   }
@@ -1392,8 +1536,8 @@
     }
     if (s->all_incoming_byte_streams_finished &&
         s->recv_trailing_metadata_finished != NULL) {
-      grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1],
-                                                   s->recv_trailing_metadata);
+      grpc_chttp2_incoming_metadata_buffer_publish(
+          exec_ctx, &s->metadata_buffer[1], s->recv_trailing_metadata);
       grpc_chttp2_complete_closure_step(
           exec_ctx, t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE,
           "recv_trailing_metadata_finished");
@@ -1441,70 +1585,37 @@
   maybe_start_some_streams(exec_ctx, t);
 }
 
-static void status_codes_from_error(grpc_error *error, gpr_timespec deadline,
-                                    grpc_chttp2_error_code *http2_error,
-                                    grpc_status_code *grpc_status) {
-  intptr_t ip_http;
-  intptr_t ip_grpc;
-  bool have_http =
-      grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &ip_http);
-  bool have_grpc =
-      grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &ip_grpc);
-  if (have_http) {
-    *http2_error = (grpc_chttp2_error_code)ip_http;
-  } else if (have_grpc) {
-    *http2_error =
-        grpc_chttp2_grpc_status_to_http2_error((grpc_status_code)ip_grpc);
-  } else {
-    *http2_error = GRPC_CHTTP2_INTERNAL_ERROR;
-  }
-  if (have_grpc) {
-    *grpc_status = (grpc_status_code)ip_grpc;
-  } else if (have_http) {
-    *grpc_status = grpc_chttp2_http2_error_to_grpc_status(
-        (grpc_chttp2_error_code)ip_http, deadline);
-  } else {
-    *grpc_status = GRPC_STATUS_INTERNAL;
-  }
-}
-
 void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
                                grpc_chttp2_transport *t, grpc_chttp2_stream *s,
                                grpc_error *due_to_error) {
-  if (!s->read_closed || !s->write_closed) {
-    grpc_status_code grpc_status;
-    grpc_chttp2_error_code http_error;
-    status_codes_from_error(due_to_error, s->deadline, &http_error,
-                            &grpc_status);
+  if (!t->is_client && !s->sent_trailing_metadata &&
+      grpc_error_has_clear_grpc_status(due_to_error)) {
+    close_from_api(exec_ctx, t, s, due_to_error);
+    return;
+  }
 
+  if (!s->read_closed || !s->write_closed) {
     if (s->id != 0) {
+      grpc_http2_error_code http_error;
+      grpc_error_get_status(due_to_error, s->deadline, NULL, NULL, &http_error);
       grpc_slice_buffer_add(
           &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
                                                   &s->stats.outgoing));
       grpc_chttp2_initiate_write(exec_ctx, t, false, "rst_stream");
     }
-
-    const char *msg =
-        grpc_error_get_str(due_to_error, GRPC_ERROR_STR_GRPC_MESSAGE);
-    bool free_msg = false;
-    if (msg == NULL) {
-      free_msg = true;
-      msg = grpc_error_string(due_to_error);
-    }
-    grpc_slice msg_slice = grpc_slice_from_copied_string(msg);
-    grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice);
-    if (free_msg) grpc_error_free_string(msg);
   }
   if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) {
     s->seen_error = true;
-    grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
   }
   grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, due_to_error);
 }
 
 void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                             grpc_chttp2_stream *s, grpc_status_code status,
-                             grpc_slice *slice) {
+                             grpc_chttp2_stream *s, grpc_error *error) {
+  grpc_status_code status;
+  const char *msg;
+  grpc_error_get_status(error, s->deadline, &status, &msg, NULL);
+
   if (status != GRPC_STATUS_OK) {
     s->seen_error = true;
   }
@@ -1518,24 +1629,21 @@
       s->recv_trailing_metadata_finished != NULL) {
     char status_string[GPR_LTOA_MIN_BUFSIZE];
     gpr_ltoa(status, status_string);
-    grpc_chttp2_incoming_metadata_buffer_add(
-        &s->metadata_buffer[1], grpc_mdelem_from_metadata_strings(
-                                    exec_ctx, GRPC_MDSTR_GRPC_STATUS,
-                                    grpc_mdstr_from_string(status_string)));
-    if (slice) {
-      grpc_chttp2_incoming_metadata_buffer_add(
-          &s->metadata_buffer[1],
-          grpc_mdelem_from_metadata_strings(
-              exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
-              grpc_mdstr_from_slice(exec_ctx,
-                                    grpc_slice_ref_internal(*slice))));
+    grpc_chttp2_incoming_metadata_buffer_replace_or_add(
+        exec_ctx, &s->metadata_buffer[1],
+        grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
+                                grpc_slice_from_copied_string(status_string)));
+    if (msg != NULL) {
+      grpc_chttp2_incoming_metadata_buffer_replace_or_add(
+          exec_ctx, &s->metadata_buffer[1],
+          grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
+                                  grpc_slice_from_copied_string(msg)));
     }
     s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE;
     grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
   }
-  if (slice) {
-    grpc_slice_unref_internal(exec_ctx, *slice);
-  }
+
+  GRPC_ERROR_UNREF(error);
 }
 
 static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) {
@@ -1601,12 +1709,37 @@
                                     int close_writes, grpc_error *error) {
   if (s->read_closed && s->write_closed) {
     /* already closed */
+    grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
     GRPC_ERROR_UNREF(error);
     return;
   }
+  bool closed_read = false;
+  bool became_closed = false;
   if (close_reads && !s->read_closed) {
     s->read_closed_error = GRPC_ERROR_REF(error);
     s->read_closed = true;
+    closed_read = true;
+  }
+  if (close_writes && !s->write_closed) {
+    s->write_closed_error = GRPC_ERROR_REF(error);
+    s->write_closed = true;
+    grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error));
+  }
+  if (s->read_closed && s->write_closed) {
+    became_closed = true;
+    grpc_error *overall_error =
+        removal_error(GRPC_ERROR_REF(error), s, "Stream removed");
+    if (s->id != 0) {
+      remove_stream(exec_ctx, t, s->id, GRPC_ERROR_REF(overall_error));
+    } else {
+      /* Purge streams waiting on concurrency still waiting for id assignment */
+      grpc_chttp2_list_remove_waiting_for_concurrency(t, s);
+    }
+    if (overall_error != GRPC_ERROR_NONE) {
+      grpc_chttp2_fake_status(exec_ctx, t, s, overall_error);
+    }
+  }
+  if (closed_read) {
     for (int i = 0; i < 2; i++) {
       if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) {
         s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE;
@@ -1615,22 +1748,9 @@
     decrement_active_streams_locked(exec_ctx, t, s);
     grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
     grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
-    grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
   }
-  if (close_writes && !s->write_closed) {
-    s->write_closed_error = GRPC_ERROR_REF(error);
-    s->write_closed = true;
-    grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error));
+  if (became_closed) {
     grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
-  }
-  if (s->read_closed && s->write_closed) {
-    if (s->id != 0) {
-      remove_stream(exec_ctx, t, s->id,
-                    removal_error(GRPC_ERROR_REF(error), s, "Stream removed"));
-    } else {
-      /* Purge streams waiting on concurrency still waiting for id assignment */
-      grpc_chttp2_list_remove_waiting_for_concurrency(t, s);
-    }
     GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2");
   }
   GRPC_ERROR_UNREF(error);
@@ -1644,112 +1764,92 @@
   uint8_t *p;
   uint32_t len = 0;
   grpc_status_code grpc_status;
-  grpc_chttp2_error_code http_error;
-  status_codes_from_error(error, s->deadline, &http_error, &grpc_status);
+  const char *msg;
+  grpc_error_get_status(error, s->deadline, &grpc_status, &msg, NULL);
 
   GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
 
-  if (s->id != 0 && !t->is_client) {
-    /* Hand roll a header block.
-       This is unnecessarily ugly - at some point we should find a more
-       elegant
-       solution.
-       It's complicated by the fact that our send machinery would be dead by
-       the
-       time we got around to sending this, so instead we ignore HPACK
-       compression
-       and just write the uncompressed bytes onto the wire. */
-    status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10));
-    p = GRPC_SLICE_START_PTR(status_hdr);
-    *p++ = 0x40; /* literal header */
-    *p++ = 11;   /* len(grpc-status) */
+  /* Hand roll a header block.
+     This is unnecessarily ugly - at some point we should find a more
+     elegant solution.
+     It's complicated by the fact that our send machinery would be dead by
+     the time we got around to sending this, so instead we ignore HPACK
+     compression and just write the uncompressed bytes onto the wire. */
+  status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10));
+  p = GRPC_SLICE_START_PTR(status_hdr);
+  *p++ = 0x00; /* literal header, not indexed */
+  *p++ = 11;   /* len(grpc-status) */
+  *p++ = 'g';
+  *p++ = 'r';
+  *p++ = 'p';
+  *p++ = 'c';
+  *p++ = '-';
+  *p++ = 's';
+  *p++ = 't';
+  *p++ = 'a';
+  *p++ = 't';
+  *p++ = 'u';
+  *p++ = 's';
+  if (grpc_status < 10) {
+    *p++ = 1;
+    *p++ = (uint8_t)('0' + grpc_status);
+  } else {
+    *p++ = 2;
+    *p++ = (uint8_t)('0' + (grpc_status / 10));
+    *p++ = (uint8_t)('0' + (grpc_status % 10));
+  }
+  GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
+  len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr);
+
+  if (msg != NULL) {
+    size_t msg_len = strlen(msg);
+    GPR_ASSERT(msg_len <= UINT32_MAX);
+    uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0);
+    message_pfx = grpc_slice_malloc(14 + msg_len_len);
+    p = GRPC_SLICE_START_PTR(message_pfx);
+    *p++ = 0x00; /* literal header, not indexed */
+    *p++ = 12;   /* len(grpc-message) */
     *p++ = 'g';
     *p++ = 'r';
     *p++ = 'p';
     *p++ = 'c';
     *p++ = '-';
+    *p++ = 'm';
+    *p++ = 'e';
     *p++ = 's';
-    *p++ = 't';
+    *p++ = 's';
     *p++ = 'a';
-    *p++ = 't';
-    *p++ = 'u';
-    *p++ = 's';
-    if (grpc_status < 10) {
-      *p++ = 1;
-      *p++ = (uint8_t)('0' + grpc_status);
-    } else {
-      *p++ = 2;
-      *p++ = (uint8_t)('0' + (grpc_status / 10));
-      *p++ = (uint8_t)('0' + (grpc_status % 10));
-    }
-    GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
-    len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr);
-
-    const char *optional_message =
-        grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
-
-    if (optional_message != NULL) {
-      size_t msg_len = strlen(optional_message);
-      GPR_ASSERT(msg_len <= UINT32_MAX);
-      uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0);
-      message_pfx = grpc_slice_malloc(14 + msg_len_len);
-      p = GRPC_SLICE_START_PTR(message_pfx);
-      *p++ = 0x40;
-      *p++ = 12; /* len(grpc-message) */
-      *p++ = 'g';
-      *p++ = 'r';
-      *p++ = 'p';
-      *p++ = 'c';
-      *p++ = '-';
-      *p++ = 'm';
-      *p++ = 'e';
-      *p++ = 's';
-      *p++ = 's';
-      *p++ = 'a';
-      *p++ = 'g';
-      *p++ = 'e';
-      GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p,
-                               (uint32_t)msg_len_len);
-      p += msg_len_len;
-      GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
-      len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
-      len += (uint32_t)msg_len;
-    }
-
-    hdr = grpc_slice_malloc(9);
-    p = GRPC_SLICE_START_PTR(hdr);
-    *p++ = (uint8_t)(len >> 16);
-    *p++ = (uint8_t)(len >> 8);
-    *p++ = (uint8_t)(len);
-    *p++ = GRPC_CHTTP2_FRAME_HEADER;
-    *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
-    *p++ = (uint8_t)(s->id >> 24);
-    *p++ = (uint8_t)(s->id >> 16);
-    *p++ = (uint8_t)(s->id >> 8);
-    *p++ = (uint8_t)(s->id);
-    GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
-
-    grpc_slice_buffer_add(&t->qbuf, hdr);
-    grpc_slice_buffer_add(&t->qbuf, status_hdr);
-    if (optional_message) {
-      grpc_slice_buffer_add(&t->qbuf, message_pfx);
-      grpc_slice_buffer_add(&t->qbuf,
-                            grpc_slice_from_copied_string(optional_message));
-    }
-    grpc_slice_buffer_add(
-        &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR,
-                                                &s->stats.outgoing));
+    *p++ = 'g';
+    *p++ = 'e';
+    GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p, (uint32_t)msg_len_len);
+    p += msg_len_len;
+    GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
+    len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
+    len += (uint32_t)msg_len;
   }
 
-  const char *msg = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
-  bool free_msg = false;
-  if (msg == NULL) {
-    free_msg = true;
-    msg = grpc_error_string(error);
+  hdr = grpc_slice_malloc(9);
+  p = GRPC_SLICE_START_PTR(hdr);
+  *p++ = (uint8_t)(len >> 16);
+  *p++ = (uint8_t)(len >> 8);
+  *p++ = (uint8_t)(len);
+  *p++ = GRPC_CHTTP2_FRAME_HEADER;
+  *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
+  *p++ = (uint8_t)(s->id >> 24);
+  *p++ = (uint8_t)(s->id >> 16);
+  *p++ = (uint8_t)(s->id >> 8);
+  *p++ = (uint8_t)(s->id);
+  GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
+
+  grpc_slice_buffer_add(&t->qbuf, hdr);
+  grpc_slice_buffer_add(&t->qbuf, status_hdr);
+  if (msg != NULL) {
+    grpc_slice_buffer_add(&t->qbuf, message_pfx);
+    grpc_slice_buffer_add(&t->qbuf, grpc_slice_from_copied_string(msg));
   }
-  grpc_slice msg_slice = grpc_slice_from_copied_string(msg);
-  grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice);
-  if (free_msg) grpc_error_free_string(msg);
+  grpc_slice_buffer_add(
+      &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR,
+                                              &s->stats.outgoing));
 
   grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error);
   grpc_chttp2_initiate_write(exec_ctx, t, false, "close_from_api");
@@ -1775,40 +1875,34 @@
   GRPC_ERROR_UNREF(error);
 }
 
-/** update window from a settings change */
-typedef struct {
-  grpc_chttp2_transport *t;
-  grpc_exec_ctx *exec_ctx;
-} update_global_window_args;
-
-static void update_global_window(void *args, uint32_t id, void *stream) {
-  update_global_window_args *a = args;
-  grpc_chttp2_transport *t = a->t;
-  grpc_chttp2_stream *s = stream;
-  int was_zero;
-  int is_zero;
-  int64_t initial_window_update = t->initial_window_update;
-
-  if (initial_window_update > 0) {
-    was_zero = s->outgoing_window <= 0;
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", t, s, outgoing_window,
-                                   initial_window_update);
-    is_zero = s->outgoing_window <= 0;
-
-    if (was_zero && !is_zero) {
-      grpc_chttp2_become_writable(a->exec_ctx, t, s, true,
-                                  "update_global_window");
-    }
-  } else {
-    GRPC_CHTTP2_FLOW_DEBIT_STREAM("settings", t, s, outgoing_window,
-                                  -initial_window_update);
-  }
-}
-
 /*******************************************************************************
  * INPUT PROCESSING - PARSING
  */
 
+static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                       double bdp_dbl) {
+  uint32_t bdp;
+  if (bdp_dbl <= 0) {
+    bdp = 0;
+  } else if (bdp_dbl > UINT32_MAX) {
+    bdp = UINT32_MAX;
+  } else {
+    bdp = (uint32_t)(bdp_dbl);
+  }
+  int64_t delta =
+      (int64_t)bdp -
+      (int64_t)t->settings[GRPC_LOCAL_SETTINGS]
+                          [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+  if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) {
+    return;
+  }
+  if (grpc_bdp_estimator_trace) {
+    gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string,
+            (int)bdp);
+  }
+  push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp);
+}
+
 static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
                                     grpc_chttp2_transport *t) {
   grpc_http_parser parser;
@@ -1827,8 +1921,10 @@
   if (parse_error == GRPC_ERROR_NONE &&
       (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) {
     error = grpc_error_set_int(
-        GRPC_ERROR_CREATE("Trying to connect an http1.x server"),
-        GRPC_ERROR_INT_HTTP_STATUS, response.status);
+        grpc_error_set_int(
+            GRPC_ERROR_CREATE("Trying to connect an http1.x server"),
+            GRPC_ERROR_INT_HTTP_STATUS, response.status),
+        GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
   }
   GRPC_ERROR_UNREF(parse_error);
 
@@ -1842,6 +1938,7 @@
   GPR_TIMER_BEGIN("reading_action_locked", 0);
 
   grpc_chttp2_transport *t = tp;
+  bool need_bdp_ping = false;
 
   GRPC_ERROR_REF(error);
 
@@ -1859,9 +1956,14 @@
     grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
                              GRPC_ERROR_NONE};
     for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
+      if (grpc_bdp_estimator_add_incoming_bytes(
+              &t->bdp_estimator,
+              (int64_t)GRPC_SLICE_LENGTH(t->read_buffer.slices[i]))) {
+        need_bdp_ping = true;
+      }
       errors[1] =
           grpc_chttp2_perform_read(exec_ctx, t, t->read_buffer.slices[i]);
-    };
+    }
     if (errors[1] != GRPC_ERROR_NONE) {
       errors[2] = try_http_parsing(exec_ctx, t);
       GRPC_ERROR_UNREF(error);
@@ -1875,21 +1977,16 @@
 
     GPR_TIMER_BEGIN("post_parse_locked", 0);
     if (t->initial_window_update != 0) {
-      update_global_window_args args = {t, exec_ctx};
-      grpc_chttp2_stream_map_for_each(&t->stream_map, update_global_window,
-                                      &args);
+      if (t->initial_window_update > 0) {
+        grpc_chttp2_stream *s;
+        while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) {
+          grpc_chttp2_become_writable(
+              exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
+              "unstalled");
+        }
+      }
       t->initial_window_update = 0;
     }
-    /* handle higher level things */
-    if (t->incoming_window < t->connection_window_target * 3 / 4) {
-      int64_t announce_bytes = t->connection_window_target - t->incoming_window;
-      GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", t, announce_incoming_window,
-                                        announce_bytes);
-      GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", t, incoming_window,
-                                        announce_bytes);
-      grpc_chttp2_initiate_write(exec_ctx, t, false, "global incoming window");
-    }
-
     GPR_TIMER_END("post_parse_locked", 0);
   }
 
@@ -1910,6 +2007,38 @@
   if (keep_reading) {
     grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer,
                        &t->read_action_locked);
+
+    if (t->enable_bdp_probe) {
+      if (need_bdp_ping) {
+        GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping");
+        grpc_bdp_estimator_schedule_ping(&t->bdp_estimator);
+        send_ping_locked(exec_ctx, t,
+                         GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
+                         &t->start_bdp_ping_locked, &t->finish_bdp_ping_locked);
+      }
+
+      int64_t estimate = -1;
+      if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
+        double target = 1 + log2((double)estimate);
+        double memory_pressure = grpc_resource_quota_get_memory_pressure(
+            grpc_resource_user_quota(grpc_endpoint_get_resource_user(t->ep)));
+        if (memory_pressure > 0.8) {
+          target *= 1 - GPR_MIN(1, (memory_pressure - 0.8) / 0.1);
+        }
+        double bdp_error =
+            target - grpc_pid_controller_last(&t->pid_controller);
+        gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
+        gpr_timespec dt_timespec = gpr_time_sub(now, t->last_pid_update);
+        double dt = (double)dt_timespec.tv_sec + dt_timespec.tv_nsec * 1e-9;
+        if (dt > 0.1) {
+          dt = 0.1;
+        }
+        double log2_bdp_guess =
+            grpc_pid_controller_update(&t->pid_controller, bdp_error, dt);
+        update_bdp(exec_ctx, t, pow(2, log2_bdp_guess));
+        t->last_pid_update = now;
+      }
+    }
     GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
   } else {
     GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "reading_action");
@@ -1922,6 +2051,97 @@
   GPR_TIMER_END("reading_action_locked", 0);
 }
 
+static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
+                                  grpc_error *error) {
+  grpc_chttp2_transport *t = tp;
+  if (grpc_http_trace) {
+    gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string);
+  }
+  grpc_bdp_estimator_start_ping(&t->bdp_estimator);
+}
+
+static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
+                                   grpc_error *error) {
+  grpc_chttp2_transport *t = tp;
+  if (grpc_http_trace) {
+    gpr_log(GPR_DEBUG, "%s: Complete BDP ping", t->peer_string);
+  }
+  grpc_bdp_estimator_complete_ping(&t->bdp_estimator);
+
+  GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
+}
+
+static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                       grpc_error *error) {
+  grpc_chttp2_transport *t = arg;
+  GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING);
+  if (error == GRPC_ERROR_NONE && !(t->destroying || t->closed)) {
+    if (t->keepalive_permit_without_calls || t->stream_map.count > 0) {
+      t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING;
+      GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end");
+      send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE,
+                       &t->start_keepalive_ping_locked,
+                       &t->finish_keepalive_ping_locked);
+    } else {
+      GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
+      grpc_timer_init(
+          exec_ctx, &t->keepalive_ping_timer,
+          gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
+          &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
+    }
+  }
+  GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "init keepalive ping");
+}
+
+static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                        grpc_error *error) {
+  grpc_chttp2_transport *t = arg;
+  GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
+  grpc_timer_init(
+      exec_ctx, &t->keepalive_watchdog_timer,
+      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout),
+      &t->keepalive_watchdog_fired_locked, gpr_now(GPR_CLOCK_MONOTONIC));
+}
+
+static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                         grpc_error *error) {
+  grpc_chttp2_transport *t = arg;
+  if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
+    if (error == GRPC_ERROR_NONE) {
+      t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
+      grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer);
+      GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
+      grpc_timer_init(
+          exec_ctx, &t->keepalive_ping_timer,
+          gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
+          grpc_closure_create(init_keepalive_ping_locked, t,
+                              grpc_combiner_scheduler(t->combiner, false)),
+          gpr_now(GPR_CLOCK_MONOTONIC));
+    }
+  }
+  GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end");
+}
+
+static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
+                                            grpc_error *error) {
+  grpc_chttp2_transport *t = arg;
+  if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
+    if (error == GRPC_ERROR_NONE) {
+      t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
+      close_transport_locked(exec_ctx, t,
+                             GRPC_ERROR_CREATE("keepalive watchdog timeout"));
+    }
+  } else {
+    /** The watchdog timer should have been cancelled by
+        finish_keepalive_ping_locked. */
+    if (error != GRPC_ERROR_CANCELLED) {
+      gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)",
+              t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING);
+    }
+  }
+  GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive watchdog");
+}
+
 /*******************************************************************************
  * CALLBACK LOOP
  */
@@ -1972,10 +2192,12 @@
                                                      size_t max_size_hint,
                                                      size_t have_already) {
   uint32_t max_recv_bytes;
+  uint32_t initial_window_size =
+      t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 
   /* clamp max recv hint to an allowable size */
-  if (max_size_hint >= UINT32_MAX - t->stream_lookahead) {
-    max_recv_bytes = UINT32_MAX - t->stream_lookahead;
+  if (max_size_hint >= UINT32_MAX - initial_window_size) {
+    max_recv_bytes = UINT32_MAX - initial_window_size;
   } else {
     max_recv_bytes = (uint32_t)max_size_hint;
   }
@@ -1988,20 +2210,26 @@
   }
 
   /* add some small lookahead to keep pipelines flowing */
-  GPR_ASSERT(max_recv_bytes <= UINT32_MAX - t->stream_lookahead);
-  max_recv_bytes += t->stream_lookahead;
-  if (s->max_recv_bytes < max_recv_bytes) {
-    uint32_t add_max_recv_bytes = max_recv_bytes - s->max_recv_bytes;
-    bool new_window_write_is_covered_by_poller =
-        s->max_recv_bytes < have_already;
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, max_recv_bytes,
-                                   add_max_recv_bytes);
-    GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, incoming_window,
-                                   add_max_recv_bytes);
+  GPR_ASSERT(max_recv_bytes <= UINT32_MAX - initial_window_size);
+  if (s->incoming_window_delta < max_recv_bytes && !s->read_closed) {
+    uint32_t add_max_recv_bytes =
+        (uint32_t)(max_recv_bytes - s->incoming_window_delta);
+    grpc_chttp2_stream_write_type write_type =
+        GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED;
+    if (s->incoming_window_delta + initial_window_size <
+        (int64_t)have_already) {
+      write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED;
+    }
+    GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA("op", t, s,
+                                                         add_max_recv_bytes);
     GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window,
                                    add_max_recv_bytes);
-    grpc_chttp2_become_writable(exec_ctx, t, s,
-                                new_window_write_is_covered_by_poller,
+    if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size -
+            (int64_t)s->announce_window >
+        (int64_t)initial_window_size / 2) {
+      write_type = GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK;
+    }
+    grpc_chttp2_become_writable(exec_ctx, t, s, write_type,
                                 "read_incoming_stream");
   }
 }
@@ -2089,6 +2317,8 @@
   grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error));
   bs->on_next = NULL;
   GRPC_ERROR_UNREF(bs->error);
+  grpc_chttp2_cancel_stream(exec_ctx, bs->transport, bs->stream,
+                            GRPC_ERROR_REF(error));
   bs->error = error;
 }
 
@@ -2197,8 +2427,10 @@
       gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory",
               t->peer_string);
     }
-    send_goaway(exec_ctx, t, GRPC_CHTTP2_ENHANCE_YOUR_CALM,
-                grpc_slice_from_static_string("Buffers full"));
+    send_goaway(exec_ctx, t,
+                grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
+                                   GRPC_ERROR_INT_HTTP2_ERROR,
+                                   GRPC_HTTP2_ENHANCE_YOUR_CALM));
   } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) {
     gpr_log(GPR_DEBUG,
             "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR
@@ -2227,7 +2459,7 @@
     grpc_chttp2_cancel_stream(
         exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
                                            GRPC_ERROR_INT_HTTP2_ERROR,
-                                           GRPC_CHTTP2_ENHANCE_YOUR_CALM));
+                                           GRPC_HTTP2_ENHANCE_YOUR_CALM));
     if (n > 1) {
       /* Since we cancel one stream per destructive reclamation, if
          there are more streams left, we can immediately post a new
@@ -2351,7 +2583,7 @@
 grpc_transport *grpc_create_chttp2_transport(
     grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
     grpc_endpoint *ep, int is_client) {
-  grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport));
+  grpc_chttp2_transport *t = gpr_zalloc(sizeof(grpc_chttp2_transport));
   init_transport(exec_ctx, t, channel_args, ep, is_client != 0);
   return &t->base;
 }
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.c b/src/core/ext/transport/chttp2/transport/frame_ping.c
index 7de5f63..f487533 100644
--- a/src/core/ext/transport/chttp2/transport/frame_ping.c
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -40,7 +40,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
+grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes) {
   grpc_slice slice = grpc_slice_malloc(9 + 8);
   uint8_t *p = GRPC_SLICE_START_PTR(slice);
 
@@ -53,7 +53,14 @@
   *p++ = 0;
   *p++ = 0;
   *p++ = 0;
-  memcpy(p, opaque_8bytes, 8);
+  *p++ = (uint8_t)(opaque_8bytes >> 56);
+  *p++ = (uint8_t)(opaque_8bytes >> 48);
+  *p++ = (uint8_t)(opaque_8bytes >> 40);
+  *p++ = (uint8_t)(opaque_8bytes >> 32);
+  *p++ = (uint8_t)(opaque_8bytes >> 24);
+  *p++ = (uint8_t)(opaque_8bytes >> 16);
+  *p++ = (uint8_t)(opaque_8bytes >> 8);
+  *p++ = (uint8_t)(opaque_8bytes);
 
   return slice;
 }
@@ -70,6 +77,7 @@
   }
   parser->byte = 0;
   parser->is_ack = flags;
+  parser->opaque_8bytes = 0;
   return GRPC_ERROR_NONE;
 }
 
@@ -83,7 +91,7 @@
   grpc_chttp2_ping_parser *p = parser;
 
   while (p->byte != 8 && cur != end) {
-    p->opaque_8bytes[p->byte] = *cur;
+    p->opaque_8bytes |= (((uint64_t)*cur) << (8 * p->byte));
     cur++;
     p->byte++;
   }
@@ -93,8 +101,12 @@
     if (p->is_ack) {
       grpc_chttp2_ack_ping(exec_ctx, t, p->opaque_8bytes);
     } else {
-      grpc_slice_buffer_add(&t->qbuf,
-                            grpc_chttp2_ping_create(1, p->opaque_8bytes));
+      if (t->ping_ack_count == t->ping_ack_capacity) {
+        t->ping_ack_capacity = GPR_MAX(t->ping_ack_capacity * 3 / 2, 3);
+        t->ping_acks = gpr_realloc(
+            t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks));
+      }
+      t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes;
       grpc_chttp2_initiate_write(exec_ctx, t, false, "ping response");
     }
   }
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.h b/src/core/ext/transport/chttp2/transport/frame_ping.h
index b9889e2..ef64246 100644
--- a/src/core/ext/transport/chttp2/transport/frame_ping.h
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.h
@@ -41,10 +41,10 @@
 typedef struct {
   uint8_t byte;
   uint8_t is_ack;
-  uint8_t opaque_8bytes[8];
+  uint64_t opaque_8bytes;
 } grpc_chttp2_ping_parser;
 
-grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes);
+grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes);
 
 grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
                                                 uint32_t length, uint8_t flags);
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
index 20043f5..cb017e7 100644
--- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
@@ -39,8 +39,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/transport/chttp2/transport/frame.h"
-#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
-#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
+#include "src/core/lib/transport/http2_errors.h"
 
 grpc_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code,
                                          grpc_transport_one_way_stats *stats) {
@@ -109,17 +108,14 @@
                       (((uint32_t)p->reason_bytes[2]) << 8) |
                       (((uint32_t)p->reason_bytes[3]));
     grpc_error *error = GRPC_ERROR_NONE;
-    if (reason != GRPC_CHTTP2_NO_ERROR || s->header_frames_received < 2) {
-      error = grpc_error_set_int(GRPC_ERROR_CREATE("RST_STREAM"),
-                                 GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason);
-      grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
-          (grpc_chttp2_error_code)reason, s->deadline);
-      char *status_details;
-      gpr_asprintf(&status_details, "Received RST_STREAM with error code %d",
-                   reason);
-      grpc_slice slice_details = grpc_slice_from_copied_string(status_details);
-      gpr_free(status_details);
-      grpc_chttp2_fake_status(exec_ctx, t, s, status_code, &slice_details);
+    if (reason != GRPC_HTTP2_NO_ERROR || s->header_frames_received < 2) {
+      char *message;
+      gpr_asprintf(&message, "Received RST_STREAM with error code %d", reason);
+      error = grpc_error_set_int(
+          grpc_error_set_str(GRPC_ERROR_CREATE("RST_STREAM"),
+                             GRPC_ERROR_STR_GRPC_MESSAGE, message),
+          GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason);
+      gpr_free(message);
     }
     grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, error);
   }
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.c b/src/core/ext/transport/chttp2/transport/frame_settings.c
index 98facae..82290e3 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.c
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.c
@@ -43,8 +43,8 @@
 
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/ext/transport/chttp2/transport/frame.h"
-#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
 #include "src/core/lib/debug/trace.h"
+#include "src/core/lib/transport/http2_errors.h"
 
 #define MAX_MAX_HEADER_LIST_SIZE (1024 * 1024 * 1024)
 
@@ -52,21 +52,21 @@
 const grpc_chttp2_setting_parameters
     grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {
         {NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
-         GRPC_CHTTP2_PROTOCOL_ERROR},
+         GRPC_HTTP2_PROTOCOL_ERROR},
         {"HEADER_TABLE_SIZE", 4096, 0, 0xffffffff,
-         GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
+         GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
         {"ENABLE_PUSH", 1, 0, 1, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
-         GRPC_CHTTP2_PROTOCOL_ERROR},
+         GRPC_HTTP2_PROTOCOL_ERROR},
         {"MAX_CONCURRENT_STREAMS", 0xffffffffu, 0, 0xffffffffu,
-         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
+         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
         {"INITIAL_WINDOW_SIZE", 65535, 0, 0x7fffffffu,
          GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
-         GRPC_CHTTP2_FLOW_CONTROL_ERROR},
+         GRPC_HTTP2_FLOW_CONTROL_ERROR},
         {"MAX_FRAME_SIZE", 16384, 16384, 16777215,
-         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR},
+         GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
         {"MAX_HEADER_LIST_SIZE", MAX_MAX_HEADER_LIST_SIZE, 0,
          MAX_MAX_HEADER_LIST_SIZE, GRPC_CHTTP2_CLAMP_INVALID_VALUE,
-         GRPC_CHTTP2_PROTOCOL_ERROR},
+         GRPC_HTTP2_PROTOCOL_ERROR},
 };
 
 static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) {
@@ -236,7 +236,7 @@
           }
           if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
               parser->incoming_settings[parser->id] != parser->value) {
-            t->initial_window_update =
+            t->initial_window_update +=
                 (int64_t)parser->value - parser->incoming_settings[parser->id];
             if (grpc_http_trace) {
               gpr_log(GPR_DEBUG, "adding %d for initial_window change",
@@ -245,8 +245,9 @@
           }
           parser->incoming_settings[parser->id] = parser->value;
           if (grpc_http_trace) {
-            gpr_log(GPR_DEBUG, "CHTTP2:%s: got setting %d = %d",
-                    t->is_client ? "CLI" : "SVR", parser->id, parser->value);
+            gpr_log(GPR_DEBUG, "CHTTP2:%s:%s: got setting %d = %d",
+                    t->is_client ? "CLI" : "SVR", t->peer_string, parser->id,
+                    parser->value);
           }
         } else if (grpc_http_trace) {
           gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.h b/src/core/ext/transport/chttp2/transport/frame_settings.h
index a29dc82..4413779 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.h
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.h
@@ -87,7 +87,7 @@
     grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
 
 /* Create a settings frame by diffing old & new, and updating old to be new */
-grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
+grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *newval,
                                        uint32_t force_mask, size_t count);
 /* Create an ack settings frame */
 grpc_slice grpc_chttp2_settings_ack_create(void);
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.c b/src/core/ext/transport/chttp2/transport/frame_window_update.c
index 31a31c2..8fa0bb4 100644
--- a/src/core/ext/transport/chttp2/transport/frame_window_update.c
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.c
@@ -110,13 +110,12 @@
 
     if (t->incoming_stream_id != 0) {
       if (s != NULL) {
-        bool was_zero = s->outgoing_window <= 0;
-        GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", t, s, outgoing_window,
+        GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", t, s, outgoing_window_delta,
                                        received_update);
-        bool is_zero = s->outgoing_window <= 0;
-        if (was_zero && !is_zero) {
-          grpc_chttp2_become_writable(exec_ctx, t, s, false,
-                                      "stream.read_flow_control");
+        if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) {
+          grpc_chttp2_become_writable(
+              exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
+              "stream.read_flow_control");
         }
       }
     } else {
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
index 49a8326..84586cd 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
@@ -49,6 +49,7 @@
 #include "src/core/ext/transport/chttp2/transport/hpack_table.h"
 #include "src/core/ext/transport/chttp2/transport/varint.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "src/core/lib/transport/timeout_encoding.h"
@@ -64,6 +65,10 @@
 /* don't consider adding anything bigger than this to the hpack table */
 #define MAX_DECODER_SPACE_USAGE 512
 
+static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL};
+static const grpc_slice terminal_slice = {&terminal_slice_refcount,
+                                          .data.refcounted = {0, 0}};
+
 extern int grpc_http_trace;
 
 typedef struct {
@@ -168,6 +173,7 @@
 
 static uint8_t *add_tiny_header_data(framer_state *st, size_t len) {
   ensure_space(st, len);
+  st->stats->header_bytes += len;
   return grpc_slice_buffer_tiny_add(st->output, len);
 }
 
@@ -185,9 +191,12 @@
 
 /* add an element to the decoder table */
 static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
-                     grpc_mdelem *elem) {
-  uint32_t key_hash = elem->key->hash;
-  uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
+                     grpc_mdelem elem) {
+  GPR_ASSERT(GRPC_MDELEM_IS_INTERNED(elem));
+
+  uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
+  uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
+  uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
   uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
   size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
 
@@ -212,17 +221,18 @@
   c->table_elems++;
 
   /* Store this element into {entries,indices}_elem */
-  if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem) {
+  if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem)) {
     /* already there: update with new index */
     c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
-  } else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem) {
+  } else if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)],
+                            elem)) {
     /* already there (cuckoo): update with new index */
     c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
-  } else if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == NULL) {
+  } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_2(elem_hash)])) {
     /* not there, but a free element: add */
     c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
     c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
-  } else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == NULL) {
+  } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_3(elem_hash)])) {
     /* not there (cuckoo), but a free element: add */
     c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
     c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
@@ -241,24 +251,34 @@
 
   /* do exactly the same for the key (so we can find by that again too) */
 
-  if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key) {
+  if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)],
+                    GRPC_MDKEY(elem))) {
     c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
-  } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) {
+  } else if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_3(key_hash)],
+                           GRPC_MDKEY(elem))) {
     c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
-  } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) {
-    c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
+  } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)].refcount ==
+             &terminal_slice_refcount) {
+    c->entries_keys[HASH_FRAGMENT_2(key_hash)] =
+        grpc_slice_ref_internal(GRPC_MDKEY(elem));
     c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
-  } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) {
-    c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
+  } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)].refcount ==
+             &terminal_slice_refcount) {
+    c->entries_keys[HASH_FRAGMENT_3(key_hash)] =
+        grpc_slice_ref_internal(GRPC_MDKEY(elem));
     c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
   } else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] <
              c->indices_keys[HASH_FRAGMENT_3(key_hash)]) {
-    GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
-    c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
+    grpc_slice_unref_internal(exec_ctx,
+                              c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
+    c->entries_keys[HASH_FRAGMENT_2(key_hash)] =
+        grpc_slice_ref_internal(GRPC_MDKEY(elem));
     c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
   } else {
-    GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
-    c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
+    grpc_slice_unref_internal(exec_ctx,
+                              c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
+    c->entries_keys[HASH_FRAGMENT_3(key_hash)] =
+        grpc_slice_ref_internal(GRPC_MDKEY(elem));
     c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
   }
 }
@@ -270,20 +290,18 @@
                            len);
 }
 
-static grpc_slice get_wire_value(grpc_mdelem *elem, uint8_t *huffman_prefix) {
-  if (grpc_is_binary_header(
-          (const char *)GRPC_SLICE_START_PTR(elem->key->slice),
-          GRPC_SLICE_LENGTH(elem->key->slice))) {
+static grpc_slice get_wire_value(grpc_mdelem elem, uint8_t *huffman_prefix) {
+  if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
     *huffman_prefix = 0x80;
-    return grpc_mdstr_as_base64_encoded_and_huffman_compressed(elem->value);
+    return grpc_chttp2_base64_encode_and_huffman_compress(GRPC_MDVALUE(elem));
   }
   /* TODO(ctiller): opportunistically compress non-binary headers */
   *huffman_prefix = 0x00;
-  return elem->value->slice;
+  return grpc_slice_ref_internal(GRPC_MDVALUE(elem));
 }
 
 static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
-                               uint32_t key_index, grpc_mdelem *elem,
+                               uint32_t key_index, grpc_mdelem elem,
                                framer_state *st) {
   uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2);
   uint8_t huffman_prefix;
@@ -296,11 +314,11 @@
                            add_tiny_header_data(st, len_pfx), len_pfx);
   GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
                            add_tiny_header_data(st, len_val_len), len_val_len);
-  add_header_data(st, grpc_slice_ref_internal(value_slice));
+  add_header_data(st, value_slice);
 }
 
 static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
-                              uint32_t key_index, grpc_mdelem *elem,
+                              uint32_t key_index, grpc_mdelem elem,
                               framer_state *st) {
   uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
   uint8_t huffman_prefix;
@@ -313,12 +331,12 @@
                            add_tiny_header_data(st, len_pfx), len_pfx);
   GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
                            add_tiny_header_data(st, len_val_len), len_val_len);
-  add_header_data(st, grpc_slice_ref_internal(value_slice));
+  add_header_data(st, value_slice);
 }
 
 static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
-                                 grpc_mdelem *elem, framer_state *st) {
-  uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key->slice);
+                                 grpc_mdelem elem, framer_state *st) {
+  uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
   uint8_t huffman_prefix;
   grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
   uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
@@ -329,15 +347,15 @@
   *add_tiny_header_data(st, 1) = 0x40;
   GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
                            add_tiny_header_data(st, len_key_len), len_key_len);
-  add_header_data(st, grpc_slice_ref_internal(elem->key->slice));
+  add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
   GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
                            add_tiny_header_data(st, len_val_len), len_val_len);
-  add_header_data(st, grpc_slice_ref_internal(value_slice));
+  add_header_data(st, value_slice);
 }
 
 static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
-                                grpc_mdelem *elem, framer_state *st) {
-  uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key->slice);
+                                grpc_mdelem elem, framer_state *st) {
+  uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
   uint8_t huffman_prefix;
   grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
   uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
@@ -348,10 +366,10 @@
   *add_tiny_header_data(st, 1) = 0x00;
   GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
                            add_tiny_header_data(st, len_key_len), len_key_len);
-  add_header_data(st, grpc_slice_ref_internal(elem->key->slice));
+  add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
   GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
                            add_tiny_header_data(st, len_val_len), len_val_len);
-  add_header_data(st, grpc_slice_ref_internal(value_slice));
+  add_header_data(st, value_slice);
 }
 
 static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
@@ -369,15 +387,9 @@
 
 /* encode an mdelem */
 static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
-                      grpc_mdelem *elem, framer_state *st) {
-  uint32_t key_hash = elem->key->hash;
-  uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
-  size_t decoder_space_usage;
-  uint32_t indices_key;
-  int should_add_elem;
-
-  GPR_ASSERT(GRPC_SLICE_LENGTH(elem->key->slice) > 0);
-  if (GRPC_SLICE_START_PTR(elem->key->slice)[0] != ':') { /* regular header */
+                      grpc_mdelem elem, framer_state *st) {
+  GPR_ASSERT(GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)) > 0);
+  if (GRPC_SLICE_START_PTR(GRPC_MDKEY(elem))[0] != ':') { /* regular header */
     st->seen_regular_header = 1;
   } else {
     GPR_ASSERT(
@@ -385,11 +397,39 @@
         "Reserved header (colon-prefixed) happening after regular ones.");
   }
 
+  if (grpc_http_trace && !GRPC_MDELEM_IS_INTERNED(elem)) {
+    char *k = grpc_slice_to_c_string(GRPC_MDKEY(elem));
+    char *v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
+    gpr_log(
+        GPR_DEBUG,
+        "Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
+        k, v, GRPC_MDELEM_IS_INTERNED(elem), GRPC_MDELEM_STORAGE(elem),
+        grpc_slice_is_interned(GRPC_MDKEY(elem)),
+        grpc_slice_is_interned(GRPC_MDVALUE(elem)));
+    gpr_free(k);
+    gpr_free(v);
+  }
+  if (!GRPC_MDELEM_IS_INTERNED(elem)) {
+    emit_lithdr_noidx_v(c, elem, st);
+    return;
+  }
+
+  uint32_t key_hash;
+  uint32_t value_hash;
+  uint32_t elem_hash;
+  size_t decoder_space_usage;
+  uint32_t indices_key;
+  int should_add_elem;
+
+  key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
+  value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
+  elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
+
   inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems);
 
   /* is this elem currently in the decoders table? */
 
-  if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem &&
+  if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) &&
       c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
     /* HIT: complete element (first cuckoo hash) */
     emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
@@ -397,7 +437,7 @@
     return;
   }
 
-  if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem &&
+  if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) &&
       c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
     /* HIT: complete element (second cuckoo hash) */
     emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
@@ -414,7 +454,8 @@
   /* no hits for the elem... maybe there's a key? */
 
   indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
-  if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key &&
+  if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)],
+                    GRPC_MDKEY(elem)) &&
       indices_key > c->tail_remote_index) {
     /* HIT: key (first cuckoo hash) */
     if (should_add_elem) {
@@ -429,7 +470,8 @@
   }
 
   indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
-  if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key &&
+  if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_3(key_hash)],
+                    GRPC_MDKEY(elem)) &&
       indices_key > c->tail_remote_index) {
     /* HIT: key (first cuckoo hash) */
     if (should_add_elem) {
@@ -463,11 +505,11 @@
                          grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
                          framer_state *st) {
   char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
-  grpc_mdelem *mdelem;
+  grpc_mdelem mdelem;
   grpc_http2_encode_timeout(
       gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str);
-  mdelem = grpc_mdelem_from_metadata_strings(
-      exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT, grpc_mdstr_from_string(timeout_str));
+  mdelem = grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT,
+                                   grpc_slice_from_copied_string(timeout_str));
   hpack_enc(exec_ctx, c, mdelem, st);
   GRPC_MDELEM_UNREF(exec_ctx, mdelem);
 }
@@ -484,14 +526,19 @@
       gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
   memset(c->table_elem_size, 0,
          sizeof(*c->table_elem_size) * c->cap_table_elems);
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(c->entries_keys); i++) {
+    c->entries_keys[i] = terminal_slice;
+  }
 }
 
 void grpc_chttp2_hpack_compressor_destroy(grpc_exec_ctx *exec_ctx,
                                           grpc_chttp2_hpack_compressor *c) {
   int i;
   for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
-    if (c->entries_keys[i]) GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[i]);
-    if (c->entries_elems[i]) GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]);
+    if (c->entries_keys[i].refcount != &terminal_slice_refcount) {
+      grpc_slice_unref_internal(exec_ctx, c->entries_keys[i]);
+    }
+    GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]);
   }
   gpr_free(c->table_elem_size);
 }
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
index 3a35496..83ba5b1 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
@@ -74,8 +74,8 @@
 
   /* entry tables for keys & elems: these tables track values that have been
      seen and *may* be in the decompressor table */
-  grpc_mdstr *entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
-  grpc_mdelem *entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
+  grpc_slice entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
+  grpc_mdelem entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
   uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
   uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
 
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c
index 8b91cc7..40f5120 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c
@@ -50,9 +50,13 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
-#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/support/string.h"
+#include "src/core/lib/transport/http2_errors.h"
+
+/* TODO(ctiller): remove before submission */
+#include "src/core/lib/slice/slice_string_helpers.h"
 
 extern int grpc_http_trace;
 
@@ -668,8 +672,22 @@
 
 /* emission helpers */
 static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p,
-                          grpc_mdelem *md, int add_to_table) {
+                          grpc_mdelem md, int add_to_table) {
+  if (grpc_http_trace && !GRPC_MDELEM_IS_INTERNED(md)) {
+    char *k = grpc_slice_to_c_string(GRPC_MDKEY(md));
+    char *v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+    gpr_log(
+        GPR_DEBUG,
+        "Decode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
+        k, v, GRPC_MDELEM_IS_INTERNED(md), GRPC_MDELEM_STORAGE(md),
+        grpc_slice_is_interned(GRPC_MDKEY(md)),
+        grpc_slice_is_interned(GRPC_MDVALUE(md)));
+    gpr_free(k);
+    gpr_free(v);
+  }
   if (add_to_table) {
+    GPR_ASSERT(GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_INTERNED ||
+               GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC);
     grpc_error *err = grpc_chttp2_hptbl_add(exec_ctx, &p->table, md);
     if (err != GRPC_ERROR_NONE) return err;
   }
@@ -681,10 +699,28 @@
   return GRPC_ERROR_NONE;
 }
 
-static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
-                               grpc_chttp2_hpack_parser_string *str) {
-  grpc_mdstr *s = grpc_mdstr_from_buffer((uint8_t *)str->str, str->length);
-  str->length = 0;
+static grpc_slice take_string(grpc_exec_ctx *exec_ctx,
+                              grpc_chttp2_hpack_parser *p,
+                              grpc_chttp2_hpack_parser_string *str,
+                              bool intern) {
+  grpc_slice s;
+  if (!str->copied) {
+    if (intern) {
+      s = grpc_slice_intern(str->data.referenced);
+      grpc_slice_unref_internal(exec_ctx, str->data.referenced);
+    } else {
+      s = str->data.referenced;
+    }
+    str->copied = true;
+    str->data.referenced = grpc_empty_slice();
+  } else if (intern) {
+    s = grpc_slice_intern(grpc_slice_from_static_buffer(
+        str->data.copied.str, str->data.copied.length));
+  } else {
+    s = grpc_slice_from_copied_buffer(str->data.copied.str,
+                                      str->data.copied.length);
+  }
+  str->data.copied.length = 0;
   return s;
 }
 
@@ -771,8 +807,8 @@
                                         grpc_chttp2_hpack_parser *p,
                                         const uint8_t *cur,
                                         const uint8_t *end) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  if (md == NULL) {
+  grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  if (GRPC_MDISNULL(md)) {
     return grpc_error_set_int(
         grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
                            GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
@@ -813,12 +849,13 @@
                                         grpc_chttp2_hpack_parser *p,
                                         const uint8_t *cur,
                                         const uint8_t *end) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  GPR_ASSERT(md != NULL); /* handled in string parsing */
-  grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
-                                            exec_ctx, GRPC_MDSTR_REF(md->key),
-                                            take_string(p, &p->value)),
-                           1);
+  grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
+  grpc_error *err = on_hdr(
+      exec_ctx, p,
+      grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
+                              take_string(exec_ctx, p, &p->value, true)),
+      1);
   if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
   return parse_begin(exec_ctx, p, cur, end);
 }
@@ -828,10 +865,11 @@
                                           grpc_chttp2_hpack_parser *p,
                                           const uint8_t *cur,
                                           const uint8_t *end) {
-  grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
-                                            exec_ctx, take_string(p, &p->key),
-                                            take_string(p, &p->value)),
-                           1);
+  grpc_error *err = on_hdr(
+      exec_ctx, p,
+      grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
+                              take_string(exec_ctx, p, &p->value, true)),
+      1);
   if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
   return parse_begin(exec_ctx, p, cur, end);
 }
@@ -881,12 +919,13 @@
                                         grpc_chttp2_hpack_parser *p,
                                         const uint8_t *cur,
                                         const uint8_t *end) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  GPR_ASSERT(md != NULL); /* handled in string parsing */
-  grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
-                                            exec_ctx, GRPC_MDSTR_REF(md->key),
-                                            take_string(p, &p->value)),
-                           0);
+  grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
+  grpc_error *err = on_hdr(
+      exec_ctx, p,
+      grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
+                              take_string(exec_ctx, p, &p->value, false)),
+      0);
   if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
   return parse_begin(exec_ctx, p, cur, end);
 }
@@ -896,10 +935,11 @@
                                           grpc_chttp2_hpack_parser *p,
                                           const uint8_t *cur,
                                           const uint8_t *end) {
-  grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
-                                            exec_ctx, take_string(p, &p->key),
-                                            take_string(p, &p->value)),
-                           0);
+  grpc_error *err = on_hdr(
+      exec_ctx, p,
+      grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
+                              take_string(exec_ctx, p, &p->value, false)),
+      0);
   if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
   return parse_begin(exec_ctx, p, cur, end);
 }
@@ -949,12 +989,13 @@
                                         grpc_chttp2_hpack_parser *p,
                                         const uint8_t *cur,
                                         const uint8_t *end) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  GPR_ASSERT(md != NULL); /* handled in string parsing */
-  grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
-                                            exec_ctx, GRPC_MDSTR_REF(md->key),
-                                            take_string(p, &p->value)),
-                           0);
+  grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
+  grpc_error *err = on_hdr(
+      exec_ctx, p,
+      grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
+                              take_string(exec_ctx, p, &p->value, false)),
+      0);
   if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
   return parse_begin(exec_ctx, p, cur, end);
 }
@@ -964,10 +1005,11 @@
                                           grpc_chttp2_hpack_parser *p,
                                           const uint8_t *cur,
                                           const uint8_t *end) {
-  grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings(
-                                            exec_ctx, take_string(p, &p->key),
-                                            take_string(p, &p->value)),
-                           0);
+  grpc_error *err = on_hdr(
+      exec_ctx, p,
+      grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
+                              take_string(exec_ctx, p, &p->value, false)),
+      0);
   if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
   return parse_begin(exec_ctx, p, cur, end);
 }
@@ -1261,14 +1303,15 @@
 static void append_bytes(grpc_chttp2_hpack_parser_string *str,
                          const uint8_t *data, size_t length) {
   if (length == 0) return;
-  if (length + str->length > str->capacity) {
-    GPR_ASSERT(str->length + length <= UINT32_MAX);
-    str->capacity = (uint32_t)(str->length + length);
-    str->str = gpr_realloc(str->str, str->capacity);
+  if (length + str->data.copied.length > str->data.copied.capacity) {
+    GPR_ASSERT(str->data.copied.length + length <= UINT32_MAX);
+    str->data.copied.capacity = (uint32_t)(str->data.copied.length + length);
+    str->data.copied.str =
+        gpr_realloc(str->data.copied.str, str->data.copied.capacity);
   }
-  memcpy(str->str + str->length, data, length);
-  GPR_ASSERT(length <= UINT32_MAX - str->length);
-  str->length += (uint32_t)length;
+  memcpy(str->data.copied.str + str->data.copied.length, data, length);
+  GPR_ASSERT(length <= UINT32_MAX - str->data.copied.length);
+  str->data.copied.length += (uint32_t)length;
 }
 
 static grpc_error *append_string(grpc_exec_ctx *exec_ctx,
@@ -1351,11 +1394,9 @@
       exec_ctx, p, cur, end, GRPC_ERROR_CREATE("Should never reach here")));
 }
 
-/* append a null terminator to a string */
 static grpc_error *finish_str(grpc_exec_ctx *exec_ctx,
                               grpc_chttp2_hpack_parser *p, const uint8_t *cur,
                               const uint8_t *end) {
-  uint8_t terminator = 0;
   uint8_t decoded[2];
   uint32_t bits;
   grpc_chttp2_hpack_parser_string *str = p->parsing.str;
@@ -1396,8 +1437,6 @@
       append_bytes(str, decoded, 2);
       break;
   }
-  append_bytes(str, &terminator, 1);
-  p->parsing.str->length--; /* don't actually count the null terminator */
   return GRPC_ERROR_NONE;
 }
 
@@ -1472,8 +1511,18 @@
                                       const uint8_t *cur, const uint8_t *end,
                                       uint8_t binary,
                                       grpc_chttp2_hpack_parser_string *str) {
+  if (!p->huff && binary == NOT_BINARY && (end - cur) >= (intptr_t)p->strlen &&
+      p->current_slice_refcount != NULL) {
+    str->copied = false;
+    str->data.referenced.refcount = p->current_slice_refcount;
+    str->data.referenced.data.refcounted.bytes = (uint8_t *)cur;
+    str->data.referenced.data.refcounted.length = p->strlen;
+    grpc_slice_ref_internal(str->data.referenced);
+    return parse_next(exec_ctx, p, cur + p->strlen, end);
+  }
   p->strgot = 0;
-  str->length = 0;
+  str->copied = true;
+  str->data.copied.length = 0;
   p->parsing.str = str;
   p->huff_state = 0;
   p->binary = binary;
@@ -1490,21 +1539,22 @@
 /* check if a key represents a binary header or not */
 
 static bool is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
-  return grpc_is_binary_header(p->key.str, p->key.length);
+  return grpc_is_binary_header(
+      p->key.copied ? grpc_slice_from_static_buffer(p->key.data.copied.str,
+                                                    p->key.data.copied.length)
+                    : p->key.data.referenced);
 }
 
 static grpc_error *is_binary_indexed_header(grpc_chttp2_hpack_parser *p,
                                             bool *is) {
-  grpc_mdelem *elem = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  if (!elem) {
+  grpc_mdelem elem = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  if (GRPC_MDISNULL(elem)) {
     return grpc_error_set_int(
         grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
                            GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
         GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents);
   }
-  *is = grpc_is_binary_header(
-      (const char *)GRPC_SLICE_START_PTR(elem->key->slice),
-      GRPC_SLICE_LENGTH(elem->key->slice));
+  *is = grpc_is_binary_header(GRPC_MDKEY(elem));
   return GRPC_ERROR_NONE;
 }
 
@@ -1539,12 +1589,14 @@
   p->on_header = NULL;
   p->on_header_user_data = NULL;
   p->state = parse_begin;
-  p->key.str = NULL;
-  p->key.capacity = 0;
-  p->key.length = 0;
-  p->value.str = NULL;
-  p->value.capacity = 0;
-  p->value.length = 0;
+  p->key.data.referenced = grpc_empty_slice();
+  p->key.data.copied.str = NULL;
+  p->key.data.copied.capacity = 0;
+  p->key.data.copied.length = 0;
+  p->value.data.referenced = grpc_empty_slice();
+  p->value.data.copied.str = NULL;
+  p->value.data.copied.capacity = 0;
+  p->value.data.copied.length = 0;
   p->dynamic_table_update_allowed = 2;
   p->last_error = GRPC_ERROR_NONE;
   grpc_chttp2_hptbl_init(exec_ctx, &p->table);
@@ -1559,19 +1611,24 @@
                                       grpc_chttp2_hpack_parser *p) {
   grpc_chttp2_hptbl_destroy(exec_ctx, &p->table);
   GRPC_ERROR_UNREF(p->last_error);
-  gpr_free(p->key.str);
-  gpr_free(p->value.str);
+  grpc_slice_unref_internal(exec_ctx, p->key.data.referenced);
+  grpc_slice_unref_internal(exec_ctx, p->value.data.referenced);
+  gpr_free(p->key.data.copied.str);
+  gpr_free(p->value.data.copied.str);
 }
 
 grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx,
                                            grpc_chttp2_hpack_parser *p,
-                                           const uint8_t *beg,
-                                           const uint8_t *end) {
+                                           grpc_slice slice) {
   /* TODO(ctiller): limit the distance of end from beg, and perform multiple
      steps in the event of a large chunk of data to limit
      stack space usage when no tail call optimization is
      available */
-  return p->state(exec_ctx, p, beg, end);
+  p->current_slice_refcount = slice.refcount;
+  grpc_error *error = p->state(exec_ctx, p, GRPC_SLICE_START_PTR(slice),
+                               GRPC_SLICE_END_PTR(slice));
+  p->current_slice_refcount = NULL;
+  return error;
 }
 
 typedef void (*maybe_complete_func_type)(grpc_exec_ctx *exec_ctx,
@@ -1587,7 +1644,7 @@
   grpc_chttp2_transport *t = s->t;
   if (!s->write_closed) {
     grpc_slice_buffer_add(
-        &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR,
+        &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR,
                                                 &s->stats.outgoing));
     grpc_chttp2_initiate_write(exec_ctx, t, false, "force_rst_stream");
     grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, GRPC_ERROR_NONE);
@@ -1605,8 +1662,7 @@
   if (s != NULL) {
     s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice);
   }
-  grpc_error *error = grpc_chttp2_hpack_parser_parse(
-      exec_ctx, parser, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_END_PTR(slice));
+  grpc_error *error = grpc_chttp2_hpack_parser_parse(exec_ctx, parser, slice);
   if (error != GRPC_ERROR_NONE) {
     GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
     return error;
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.h b/src/core/ext/transport/chttp2/transport/hpack_parser.h
index 52ccf1e..a817183 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.h
@@ -49,14 +49,20 @@
     const uint8_t *end);
 
 typedef struct {
-  char *str;
-  uint32_t length;
-  uint32_t capacity;
+  bool copied;
+  struct {
+    grpc_slice referenced;
+    struct {
+      char *str;
+      uint32_t length;
+      uint32_t capacity;
+    } copied;
+  } data;
 } grpc_chttp2_hpack_parser_string;
 
 struct grpc_chttp2_hpack_parser {
   /* user specified callback for each header output */
-  void (*on_header)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem *md);
+  void (*on_header)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem md);
   void *on_header_user_data;
 
   grpc_error *last_error;
@@ -67,6 +73,8 @@
   const grpc_chttp2_hpack_parser_state *next_state;
   /* what to do after skipping prioritization data */
   grpc_chttp2_hpack_parser_state after_prioritization;
+  /* the refcount of the slice that we're currently parsing */
+  grpc_slice_refcount *current_slice_refcount;
   /* the value we're currently parsing */
   union {
     uint32_t *value;
@@ -106,11 +114,9 @@
 
 void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p);
 
-/* returns 1 on success, 0 on error */
 grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx,
                                            grpc_chttp2_hpack_parser *p,
-                                           const uint8_t *beg,
-                                           const uint8_t *end);
+                                           grpc_slice slice);
 
 /* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for
    the transport */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.c b/src/core/ext/transport/chttp2/transport/hpack_table.c
index 26d4036..62dd1b8 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.c
@@ -190,8 +190,11 @@
   tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
   memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
   for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
-    tbl->static_ents[i - 1] = grpc_mdelem_from_strings(
-        exec_ctx, static_table[i].key, static_table[i].value);
+    tbl->static_ents[i - 1] = grpc_mdelem_from_slices(
+        exec_ctx,
+        grpc_slice_intern(grpc_slice_from_static_string(static_table[i].key)),
+        grpc_slice_intern(
+            grpc_slice_from_static_string(static_table[i].value)));
   }
 }
 
@@ -208,8 +211,8 @@
   gpr_free(tbl->ents);
 }
 
-grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
-                                      uint32_t tbl_index) {
+grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
+                                     uint32_t tbl_index) {
   /* Static table comes first, just return an entry from it */
   if (tbl_index <= GRPC_CHTTP2_LAST_STATIC_ENTRY) {
     return tbl->static_ents[tbl_index - 1];
@@ -222,14 +225,14 @@
     return tbl->ents[offset];
   }
   /* Invalid entry: return error */
-  return NULL;
+  return GRPC_MDNULL;
 }
 
 /* Evict one element from the table */
 static void evict1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
-  grpc_mdelem *first_ent = tbl->ents[tbl->first_ent];
-  size_t elem_bytes = GRPC_SLICE_LENGTH(first_ent->key->slice) +
-                      GRPC_SLICE_LENGTH(first_ent->value->slice) +
+  grpc_mdelem first_ent = tbl->ents[tbl->first_ent];
+  size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(first_ent)) +
+                      GRPC_SLICE_LENGTH(GRPC_MDVALUE(first_ent)) +
                       GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
   GPR_ASSERT(elem_bytes <= tbl->mem_used);
   tbl->mem_used -= (uint32_t)elem_bytes;
@@ -239,7 +242,7 @@
 }
 
 static void rebuild_ents(grpc_chttp2_hptbl *tbl, uint32_t new_cap) {
-  grpc_mdelem **ents = gpr_malloc(sizeof(*ents) * new_cap);
+  grpc_mdelem *ents = gpr_malloc(sizeof(*ents) * new_cap);
   uint32_t i;
 
   for (i = 0; i < tbl->num_ents; i++) {
@@ -301,10 +304,10 @@
 }
 
 grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx,
-                                  grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
+                                  grpc_chttp2_hptbl *tbl, grpc_mdelem md) {
   /* determine how many bytes of buffer this entry represents */
-  size_t elem_bytes = GRPC_SLICE_LENGTH(md->key->slice) +
-                      GRPC_SLICE_LENGTH(md->value->slice) +
+  size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(md)) +
+                      GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)) +
                       GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
 
   if (tbl->current_table_bytes > tbl->max_bytes) {
@@ -352,16 +355,16 @@
 }
 
 grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
-    const grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
+    const grpc_chttp2_hptbl *tbl, grpc_mdelem md) {
   grpc_chttp2_hptbl_find_result r = {0, 0};
   uint32_t i;
 
   /* See if the string is in the static table */
   for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
-    grpc_mdelem *ent = tbl->static_ents[i];
-    if (md->key != ent->key) continue;
+    grpc_mdelem ent = tbl->static_ents[i];
+    if (!grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDKEY(ent))) continue;
     r.index = i + 1u;
-    r.has_value = md->value == ent->value;
+    r.has_value = grpc_slice_eq(GRPC_MDVALUE(md), GRPC_MDVALUE(ent));
     if (r.has_value) return r;
   }
 
@@ -369,10 +372,10 @@
   for (i = 0; i < tbl->num_ents; i++) {
     uint32_t idx =
         (uint32_t)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
-    grpc_mdelem *ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
-    if (md->key != ent->key) continue;
+    grpc_mdelem ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
+    if (!grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDKEY(ent))) continue;
     r.index = idx;
-    r.has_value = md->value == ent->value;
+    r.has_value = grpc_slice_eq(GRPC_MDVALUE(md), GRPC_MDVALUE(ent));
     if (r.has_value) return r;
   }
 
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.h b/src/core/ext/transport/chttp2/transport/hpack_table.h
index 144574e..32a0380 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.h
@@ -79,8 +79,8 @@
   /* a circular buffer of headers - this is stored in the opposite order to
      what hpack specifies, in order to simplify table management a little...
      meaning lookups need to SUBTRACT from the end position */
-  grpc_mdelem **ents;
-  grpc_mdelem *static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY];
+  grpc_mdelem *ents;
+  grpc_mdelem static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY];
 } grpc_chttp2_hptbl;
 
 /* initialize a hpack table */
@@ -94,12 +94,12 @@
                                                      uint32_t bytes);
 
 /* lookup a table entry based on its hpack index */
-grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
-                                      uint32_t index);
+grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
+                                     uint32_t index);
 /* add a table entry to the index */
 grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx,
                                   grpc_chttp2_hptbl *tbl,
-                                  grpc_mdelem *md) GRPC_MUST_USE_RESULT;
+                                  grpc_mdelem md) GRPC_MUST_USE_RESULT;
 /* Find a key/value pair in the table... returns the index in the table of the
    most similar entry, or 0 if the value was not found */
 typedef struct {
@@ -107,6 +107,6 @@
   int has_value;
 } grpc_chttp2_hptbl_find_result;
 grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
-    const grpc_chttp2_hptbl *tbl, grpc_mdelem *md);
+    const grpc_chttp2_hptbl *tbl, grpc_mdelem md);
 
 #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H */
diff --git a/src/core/ext/transport/chttp2/transport/http2_errors.h b/src/core/ext/transport/chttp2/transport/http2_errors.h
deleted file mode 100644
index deab2b7..0000000
--- a/src/core/ext/transport/chttp2/transport/http2_errors.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_ERRORS_H
-#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_ERRORS_H
-
-/* error codes for RST_STREAM from http2 draft 14 section 7 */
-typedef enum {
-  GRPC_CHTTP2_NO_ERROR = 0x0,
-  GRPC_CHTTP2_PROTOCOL_ERROR = 0x1,
-  GRPC_CHTTP2_INTERNAL_ERROR = 0x2,
-  GRPC_CHTTP2_FLOW_CONTROL_ERROR = 0x3,
-  GRPC_CHTTP2_SETTINGS_TIMEOUT = 0x4,
-  GRPC_CHTTP2_STREAM_CLOSED = 0x5,
-  GRPC_CHTTP2_FRAME_SIZE_ERROR = 0x6,
-  GRPC_CHTTP2_REFUSED_STREAM = 0x7,
-  GRPC_CHTTP2_CANCEL = 0x8,
-  GRPC_CHTTP2_COMPRESSION_ERROR = 0x9,
-  GRPC_CHTTP2_CONNECT_ERROR = 0xa,
-  GRPC_CHTTP2_ENHANCE_YOUR_CALM = 0xb,
-  GRPC_CHTTP2_INADEQUATE_SECURITY = 0xc,
-  /* force use of a default clause */
-  GRPC_CHTTP2__ERROR_DO_NOT_USE = -1
-} grpc_chttp2_error_code;
-
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_ERRORS_H */
diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.c b/src/core/ext/transport/chttp2/transport/incoming_metadata.c
index 5d10949..c91b019 100644
--- a/src/core/ext/transport/chttp2/transport/incoming_metadata.c
+++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.c
@@ -57,7 +57,7 @@
 }
 
 void grpc_chttp2_incoming_metadata_buffer_add(
-    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem) {
+    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) {
   GPR_ASSERT(!buffer->published);
   if (buffer->capacity == buffer->count) {
     buffer->capacity = GPR_MAX(8, 2 * buffer->capacity);
@@ -68,6 +68,19 @@
   buffer->size += GRPC_MDELEM_LENGTH(elem);
 }
 
+void grpc_chttp2_incoming_metadata_buffer_replace_or_add(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
+    grpc_mdelem elem) {
+  for (size_t i = 0; i < buffer->count; i++) {
+    if (grpc_slice_eq(GRPC_MDKEY(buffer->elems[i].md), GRPC_MDKEY(elem))) {
+      GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md);
+      buffer->elems[i].md = elem;
+      return;
+    }
+  }
+  grpc_chttp2_incoming_metadata_buffer_add(buffer, elem);
+}
+
 void grpc_chttp2_incoming_metadata_buffer_set_deadline(
     grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) {
   GPR_ASSERT(!buffer->published);
@@ -75,21 +88,20 @@
 }
 
 void grpc_chttp2_incoming_metadata_buffer_publish(
-    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch) {
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
+    grpc_metadata_batch *batch) {
   GPR_ASSERT(!buffer->published);
   buffer->published = 1;
   if (buffer->count > 0) {
     size_t i;
-    for (i = 1; i < buffer->count; i++) {
-      buffer->elems[i].prev = &buffer->elems[i - 1];
+    for (i = 0; i < buffer->count; i++) {
+      /* TODO(ctiller): do something better here */
+      if (!GRPC_LOG_IF_ERROR("grpc_chttp2_incoming_metadata_buffer_publish",
+                             grpc_metadata_batch_link_tail(
+                                 exec_ctx, batch, &buffer->elems[i]))) {
+        GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md);
+      }
     }
-    for (i = 0; i < buffer->count - 1; i++) {
-      buffer->elems[i].next = &buffer->elems[i + 1];
-    }
-    buffer->elems[0].prev = NULL;
-    buffer->elems[buffer->count - 1].next = NULL;
-    batch->list.head = &buffer->elems[0];
-    batch->list.tail = &buffer->elems[buffer->count - 1];
   } else {
     batch->list.head = batch->list.tail = NULL;
   }
diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/src/core/ext/transport/chttp2/transport/incoming_metadata.h
index 7a0c4da..1eac6fc 100644
--- a/src/core/ext/transport/chttp2/transport/incoming_metadata.h
+++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.h
@@ -51,10 +51,14 @@
 void grpc_chttp2_incoming_metadata_buffer_destroy(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer);
 void grpc_chttp2_incoming_metadata_buffer_publish(
-    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch);
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
+    grpc_metadata_batch *batch);
 
 void grpc_chttp2_incoming_metadata_buffer_add(
-    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem);
+    grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem);
+void grpc_chttp2_incoming_metadata_buffer_replace_or_add(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
+    grpc_mdelem elem);
 void grpc_chttp2_incoming_metadata_buffer_set_deadline(
     grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline);
 
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
index ea7beb4..d26812a 100644
--- a/src/core/ext/transport/chttp2/transport/internal.h
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -50,7 +50,10 @@
 #include "src/core/ext/transport/chttp2/transport/stream_map.h"
 #include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/transport/bdp_estimator.h"
 #include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/pid_controller.h"
 #include "src/core/lib/transport/transport_impl.h"
 
 /* streams are kept in various linked lists depending on what things need to
@@ -59,6 +62,7 @@
   GRPC_CHTTP2_LIST_WRITABLE,
   GRPC_CHTTP2_LIST_WRITING,
   GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT,
+  GRPC_CHTTP2_LIST_STALLED_BY_STREAM,
   /** streams that are waiting to start because there are too many concurrent
       streams on the connection */
   GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY,
@@ -72,6 +76,34 @@
   GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER,
 } grpc_chttp2_write_state;
 
+typedef enum {
+  GRPC_CHTTP2_PING_ON_NEXT_WRITE = 0,
+  GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
+  GRPC_CHTTP2_PING_TYPE_COUNT /* must be last */
+} grpc_chttp2_ping_type;
+
+typedef enum {
+  GRPC_CHTTP2_PCL_INITIATE = 0,
+  GRPC_CHTTP2_PCL_NEXT,
+  GRPC_CHTTP2_PCL_INFLIGHT,
+  GRPC_CHTTP2_PCL_COUNT /* must be last */
+} grpc_chttp2_ping_closure_list;
+
+typedef struct {
+  grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT];
+  uint64_t inflight_id;
+} grpc_chttp2_ping_queue;
+
+typedef struct {
+  gpr_timespec min_time_between_pings;
+  int max_pings_without_data;
+} grpc_chttp2_repeated_ping_policy;
+
+typedef struct {
+  gpr_timespec last_ping_sent_time;
+  int pings_before_data_required;
+} grpc_chttp2_repeated_ping_state;
+
 /* deframer state for the overall http2 stream of bytes */
 typedef enum {
   /* prefix: one entry per http2 connection prefix byte */
@@ -144,14 +176,6 @@
   GRPC_CHTTP2_GOAWAY_SENT,
 } grpc_chttp2_sent_goaway_state;
 
-/* Outstanding ping request data */
-typedef struct grpc_chttp2_outstanding_ping {
-  uint8_t id[8];
-  grpc_closure *on_recv;
-  struct grpc_chttp2_outstanding_ping *next;
-  struct grpc_chttp2_outstanding_ping *prev;
-} grpc_chttp2_outstanding_ping;
-
 typedef struct grpc_chttp2_write_cb {
   int64_t call_at_byte;
   grpc_closure *closure;
@@ -185,6 +209,12 @@
   grpc_closure finished_action;
 };
 
+typedef enum {
+  GRPC_CHTTP2_KEEPALIVE_STATE_WAITING,
+  GRPC_CHTTP2_KEEPALIVE_STATE_PINGING,
+  GRPC_CHTTP2_KEEPALIVE_STATE_DYING,
+} grpc_chttp2_keepalive_state;
+
 struct grpc_chttp2_transport {
   grpc_transport base; /* must be first */
   gpr_refcount refs;
@@ -204,6 +234,9 @@
   /** is there a read request to the endpoint outstanding? */
   uint8_t endpoint_reading;
 
+  /** should we probe bdp? */
+  bool enable_bdp_probe;
+
   /** various lists of streams */
   grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
 
@@ -245,10 +278,6 @@
   /** data to write next write */
   grpc_slice_buffer qbuf;
 
-  /** window available to announce to peer */
-  int64_t announce_incoming_window;
-  /** how much window would we like to have for incoming_window */
-  uint32_t connection_window_target;
   /** how much data are we willing to buffer when the WRITE_BUFFER_HINT is set?
    */
   uint32_t write_buffer_size;
@@ -271,16 +300,19 @@
       copied to next_stream_id in parsing when parsing commences */
   uint32_t next_stream_id;
 
-  /** how far to lookahead in a stream? */
-  uint32_t stream_lookahead;
-
   /** last new stream id */
   uint32_t last_new_stream_id;
 
-  /** pings awaiting responses */
-  grpc_chttp2_outstanding_ping pings;
-  /** next payload for an outgoing ping */
-  uint64_t ping_counter;
+  /** ping queues for various ping insertion points */
+  grpc_chttp2_ping_queue ping_queues[GRPC_CHTTP2_PING_TYPE_COUNT];
+  grpc_chttp2_repeated_ping_policy ping_policy;
+  grpc_chttp2_repeated_ping_state ping_state;
+  uint64_t ping_ctr; /* unique id for pings */
+
+  /** ping acks */
+  size_t ping_ack_count;
+  size_t ping_ack_capacity;
+  uint64_t *ping_acks;
 
   /** parser for headers */
   grpc_chttp2_hpack_parser hpack_parser;
@@ -299,6 +331,16 @@
 
   /** window available for peer to send to us */
   int64_t incoming_window;
+  /** calculating what we should give for incoming window:
+      we track the total amount of flow control over initial window size
+      across all streams: this is data that we want to receive right now (it
+      has an outstanding read)
+      and the total amount of flow control under initial window size across all
+      streams: this is data we've read early
+      we want to adjust incoming_window such that:
+      incoming_window = total_over - max(bdp - total_under, 0) */
+  int64_t stream_total_over_incoming_window;
+  int64_t stream_total_under_incoming_window;
 
   /* deframing */
   grpc_chttp2_deframe_transport_state deframe_state;
@@ -324,6 +366,13 @@
 
   grpc_chttp2_write_cb *write_cb_pool;
 
+  /* bdp estimator */
+  grpc_bdp_estimator bdp_estimator;
+  grpc_pid_controller pid_controller;
+  grpc_closure start_bdp_ping_locked;
+  grpc_closure finish_bdp_ping_locked;
+  gpr_timespec last_pid_update;
+
   /* if non-NULL, close the transport with this error when writes are finished
    */
   grpc_error *close_transport_on_writes_finished;
@@ -340,6 +389,28 @@
   grpc_closure benign_reclaimer_locked;
   /** destructive cleanup closure */
   grpc_closure destructive_reclaimer_locked;
+
+  /* keep-alive ping support */
+  /** Closure to initialize a keepalive ping */
+  grpc_closure init_keepalive_ping_locked;
+  /** Closure to run when the keepalive ping is sent */
+  grpc_closure start_keepalive_ping_locked;
+  /** Cousure to run when the keepalive ping ack is received */
+  grpc_closure finish_keepalive_ping_locked;
+  /** Closrue to run when the keepalive ping timeouts */
+  grpc_closure keepalive_watchdog_fired_locked;
+  /** timer to initiate ping events */
+  grpc_timer keepalive_ping_timer;
+  /** watchdog to kill the transport when waiting for the keepalive ping */
+  grpc_timer keepalive_watchdog_timer;
+  /** time duration in between pings */
+  gpr_timespec keepalive_time;
+  /** grace period for a ping to complete before watchdog kicks in */
+  gpr_timespec keepalive_timeout;
+  /** if keepalive pings are allowed when there's no outstanding streams */
+  bool keepalive_permit_without_calls;
+  /** keep-alive state machine state */
+  grpc_chttp2_keepalive_state keepalive_state;
 };
 
 typedef enum {
@@ -362,12 +433,10 @@
   /** HTTP2 stream id for this stream, or zero if one has not been assigned */
   uint32_t id;
 
-  /** window available for us to send to peer */
-  int64_t outgoing_window;
-  /** The number of bytes the upper layers have offered to receive.
-      As the upper layer offers more bytes, this value increases.
-      As bytes are read, this value decreases. */
-  uint32_t max_recv_bytes;
+  /** window available for us to send to peer, over or under the initial window
+    * size of the transport... ie:
+    * outgoing_window = outgoing_window_delta + transport.initial_window_size */
+  int64_t outgoing_window_delta;
   /** things the upper layers would like to send */
   grpc_metadata_batch *send_initial_metadata;
   grpc_closure *send_initial_metadata_finished;
@@ -428,8 +497,10 @@
   grpc_error *forced_close_error;
   /** how many header frames have we received? */
   uint8_t header_frames_received;
-  /** window available for peer to send to us */
-  int64_t incoming_window;
+  /** window available for peer to send to us (as a delta on
+   * transport.initial_window_size)
+   * incoming_window = incoming_window_delta + transport.initial_window_size */
+  int64_t incoming_window_delta;
   /** parsing state for data frames */
   grpc_chttp2_data_parser data_parser;
   /** number of bytes received - reset at end of parse thread execution */
@@ -478,36 +549,43 @@
                                           grpc_chttp2_stream *s);
 /** Get a writable stream
     returns non-zero if there was a stream available */
-int grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t,
-                                         grpc_chttp2_stream **s);
+bool grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t,
+                                          grpc_chttp2_stream **s);
 bool grpc_chttp2_list_remove_writable_stream(
     grpc_chttp2_transport *t, grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
 
 bool grpc_chttp2_list_add_writing_stream(grpc_chttp2_transport *t,
                                          grpc_chttp2_stream *s);
-int grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t);
-int grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t,
-                                        grpc_chttp2_stream **s);
+bool grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t);
+bool grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t,
+                                         grpc_chttp2_stream **s);
 
 void grpc_chttp2_list_add_written_stream(grpc_chttp2_transport *t,
                                          grpc_chttp2_stream *s);
-int grpc_chttp2_list_pop_written_stream(grpc_chttp2_transport *t,
-                                        grpc_chttp2_stream **s);
+bool grpc_chttp2_list_pop_written_stream(grpc_chttp2_transport *t,
+                                         grpc_chttp2_stream **s);
 
 void grpc_chttp2_list_add_waiting_for_concurrency(grpc_chttp2_transport *t,
                                                   grpc_chttp2_stream *s);
-int grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t,
-                                                 grpc_chttp2_stream **s);
+bool grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t,
+                                                  grpc_chttp2_stream **s);
 void grpc_chttp2_list_remove_waiting_for_concurrency(grpc_chttp2_transport *t,
                                                      grpc_chttp2_stream *s);
 
 void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t,
                                                grpc_chttp2_stream *s);
-int grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
-                                              grpc_chttp2_stream **s);
+bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
+                                               grpc_chttp2_stream **s);
 void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t,
                                                   grpc_chttp2_stream *s);
 
+void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t,
+                                            grpc_chttp2_stream *s);
+bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t,
+                                            grpc_chttp2_stream **s);
+bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t,
+                                               grpc_chttp2_stream *s);
+
 grpc_chttp2_stream *grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport *t,
                                                       uint32_t id);
 grpc_chttp2_stream *grpc_chttp2_parsing_accept_stream(grpc_exec_ctx *exec_ctx,
@@ -591,6 +669,44 @@
   GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var,  \
                                  amount)
 
+#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE( \
+    phase, transport, dst_context)                               \
+  if (dst_context->incoming_window_delta < 0) {                  \
+    transport->stream_total_under_incoming_window +=             \
+        dst_context->incoming_window_delta;                      \
+  } else if (dst_context->incoming_window_delta > 0) {           \
+    transport->stream_total_over_incoming_window -=              \
+        dst_context->incoming_window_delta;                      \
+  }
+
+#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE( \
+    phase, transport, dst_context)                                \
+  if (dst_context->incoming_window_delta < 0) {                   \
+    transport->stream_total_under_incoming_window -=              \
+        dst_context->incoming_window_delta;                       \
+  } else if (dst_context->incoming_window_delta > 0) {            \
+    transport->stream_total_over_incoming_window +=               \
+        dst_context->incoming_window_delta;                       \
+  }
+
+#define GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA(                 \
+    phase, transport, dst_context, amount)                                   \
+  GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport,  \
+                                                          dst_context);      \
+  GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context,               \
+                                incoming_window_delta, amount);              \
+  GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \
+                                                           dst_context);
+
+#define GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA(                \
+    phase, transport, dst_context, amount)                                   \
+  GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport,  \
+                                                          dst_context);      \
+  GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context,              \
+                                 incoming_window_delta, amount);             \
+  GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \
+                                                           dst_context);
+
 #define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context,       \
                                       dst_var, amount)                         \
   do {                                                                         \
@@ -618,8 +734,7 @@
                                uint32_t stream_id, int64_t val1, int64_t val2);
 
 void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                             grpc_chttp2_stream *stream,
-                             grpc_status_code status, grpc_slice *details);
+                             grpc_chttp2_stream *stream, grpc_error *error);
 void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
                                     grpc_chttp2_transport *t,
                                     grpc_chttp2_stream *s, int close_reads,
@@ -673,13 +788,23 @@
     grpc_error *error);
 
 void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
-                          const uint8_t *opaque_8bytes);
+                          uint64_t id);
+
+typedef enum {
+  /* don't initiate a transport write, but piggyback on the next one */
+  GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK,
+  /* initiate a covered write */
+  GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
+  /* initiate an uncovered write */
+  GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED
+} grpc_chttp2_stream_write_type;
 
 /** add a ref to the stream and add it to the writable list;
     ref will be dropped in writing.c */
 void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
                                  grpc_chttp2_transport *t,
-                                 grpc_chttp2_stream *s, bool covered_by_poller,
+                                 grpc_chttp2_stream *s,
+                                 grpc_chttp2_stream_write_type type,
                                  const char *reason);
 
 void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
@@ -700,4 +825,6 @@
                                      grpc_chttp2_transport *t,
                                      grpc_chttp2_stream *s, grpc_error *error);
 
+uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t);
+
 #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index 4fb5dc7..7ed0052 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -39,10 +39,11 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
-#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
+#include "src/core/lib/transport/http2_errors.h"
 #include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/status_conversion.h"
 #include "src/core/lib/transport/timeout_encoding.h"
 
 static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx,
@@ -200,7 +201,7 @@
         return err;
       }
       if (t->incoming_frame_size == 0) {
-        err = parse_frame_slice(exec_ctx, t, gpr_empty_slice(), 1);
+        err = parse_frame_slice(exec_ctx, t, grpc_empty_slice(), 1);
         if (err != GRPC_ERROR_NONE) {
           return err;
         }
@@ -335,7 +336,7 @@
   return GRPC_ERROR_NONE;
 }
 
-static void skip_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem *md) {
+static void skip_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem md) {
   GRPC_MDELEM_UNREF(exec_ctx, md);
 }
 
@@ -375,25 +376,43 @@
     return err;
   }
 
-  GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window,
-                                   incoming_frame_size);
-
   if (s != NULL) {
-    if (incoming_frame_size > s->incoming_window) {
+    if (incoming_frame_size >
+        s->incoming_window_delta +
+            t->settings[GRPC_ACKED_SETTINGS]
+                       [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) {
       char *msg;
       gpr_asprintf(&msg,
                    "frame of size %d overflows incoming window of %" PRId64,
-                   t->incoming_frame_size, s->incoming_window);
+                   t->incoming_frame_size,
+                   s->incoming_window_delta +
+                       t->settings[GRPC_ACKED_SETTINGS]
+                                  [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
       grpc_error *err = GRPC_ERROR_CREATE(msg);
       gpr_free(msg);
       return err;
     }
 
-    GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", t, s, incoming_window,
-                                  incoming_frame_size);
+    GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA("parse", t, s,
+                                                        incoming_frame_size);
+    if ((int64_t)t->settings[GRPC_SENT_SETTINGS]
+                            [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] +
+            (int64_t)s->incoming_window_delta - (int64_t)s->announce_window <=
+        (int64_t)t->settings[GRPC_SENT_SETTINGS]
+                            [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] /
+            2) {
+      grpc_chttp2_become_writable(exec_ctx, t, s,
+                                  GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
+                                  "window-update-required");
+    }
     s->received_bytes += incoming_frame_size;
-    s->max_recv_bytes -=
-        (uint32_t)GPR_MIN(s->max_recv_bytes, incoming_frame_size);
+  }
+
+  uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t);
+  GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window,
+                                   incoming_frame_size);
+  if (t->incoming_window <= target_incoming_window / 2) {
+    grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control");
   }
 
   return GRPC_ERROR_NONE;
@@ -432,7 +451,7 @@
     }
     grpc_slice_buffer_add(
         &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
-                                                GRPC_CHTTP2_PROTOCOL_ERROR,
+                                                GRPC_HTTP2_PROTOCOL_ERROR,
                                                 &s->stats.outgoing));
     return init_skip_frame_parser(exec_ctx, t, 0);
   } else {
@@ -443,7 +462,7 @@
 static void free_timeout(void *p) { gpr_free(p); }
 
 static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
-                              grpc_mdelem *md) {
+                              grpc_mdelem md) {
   grpc_chttp2_transport *t = tp;
   grpc_chttp2_stream *s = t->incoming_stream;
 
@@ -451,32 +470,42 @@
 
   GPR_ASSERT(s != NULL);
 
-  GRPC_CHTTP2_IF_TRACING(gpr_log(
-      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR",
-      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
+  if (grpc_http_trace) {
+    char *key = grpc_slice_to_c_string(GRPC_MDKEY(md));
+    char *value =
+        grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
+    gpr_log(GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id,
+            t->is_client ? "CLI" : "SVR", key, value);
+    gpr_free(key);
+    gpr_free(value);
+  }
 
-  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
+  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
+      !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
     /* TODO(ctiller): check for a status like " 0" */
     s->seen_error = true;
   }
 
-  if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
+  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
     gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
-    if (!cached_timeout) {
+    gpr_timespec timeout;
+    if (cached_timeout == NULL) {
       /* not already parsed: parse it now, and store the result away */
       cached_timeout = gpr_malloc(sizeof(gpr_timespec));
-      if (!grpc_http2_decode_timeout(grpc_mdstr_as_c_string(md->value),
-                                     cached_timeout)) {
-        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
-                grpc_mdstr_as_c_string(md->value));
+      if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), cached_timeout)) {
+        char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
+        gpr_free(val);
         *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
       }
-      cached_timeout =
-          grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+      timeout = *cached_timeout;
+      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+    } else {
+      timeout = *cached_timeout;
     }
     grpc_chttp2_incoming_metadata_buffer_set_deadline(
         &s->metadata_buffer[0],
-        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
+        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), timeout));
     GRPC_MDELEM_UNREF(exec_ctx, md);
   } else {
     const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
@@ -505,7 +534,7 @@
 }
 
 static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp,
-                               grpc_mdelem *md) {
+                               grpc_mdelem md) {
   grpc_chttp2_transport *t = tp;
   grpc_chttp2_stream *s = t->incoming_stream;
 
@@ -513,11 +542,18 @@
 
   GPR_ASSERT(s != NULL);
 
-  GRPC_CHTTP2_IF_TRACING(gpr_log(
-      GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR",
-      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
+  if (grpc_http_trace) {
+    char *key = grpc_slice_to_c_string(GRPC_MDKEY(md));
+    char *value =
+        grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
+    gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id,
+            t->is_client ? "CLI" : "SVR", key, value);
+    gpr_free(key);
+    gpr_free(value);
+  }
 
-  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
+  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
+      !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
     /* TODO(ctiller): check for a status like " 0" */
     s->seen_error = true;
   }
@@ -733,14 +769,13 @@
     if (grpc_http_trace) {
       const char *msg = grpc_error_string(err);
       gpr_log(GPR_ERROR, "%s", msg);
-      grpc_error_free_string(msg);
     }
     grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
     if (s) {
       s->forced_close_error = err;
       grpc_slice_buffer_add(
           &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
-                                                  GRPC_CHTTP2_PROTOCOL_ERROR,
+                                                  GRPC_HTTP2_PROTOCOL_ERROR,
                                                   &s->stats.outgoing));
     } else {
       GRPC_ERROR_UNREF(err);
diff --git a/src/core/ext/transport/chttp2/transport/status_conversion.c b/src/core/ext/transport/chttp2/transport/status_conversion.c
deleted file mode 100644
index 5dce2f2..0000000
--- a/src/core/ext/transport/chttp2/transport/status_conversion.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
-
-int grpc_chttp2_grpc_status_to_http2_error(grpc_status_code status) {
-  switch (status) {
-    case GRPC_STATUS_OK:
-      return GRPC_CHTTP2_NO_ERROR;
-    case GRPC_STATUS_CANCELLED:
-      return GRPC_CHTTP2_CANCEL;
-    case GRPC_STATUS_DEADLINE_EXCEEDED:
-      return GRPC_CHTTP2_CANCEL;
-    case GRPC_STATUS_RESOURCE_EXHAUSTED:
-      return GRPC_CHTTP2_ENHANCE_YOUR_CALM;
-    case GRPC_STATUS_PERMISSION_DENIED:
-      return GRPC_CHTTP2_INADEQUATE_SECURITY;
-    case GRPC_STATUS_UNAVAILABLE:
-      return GRPC_CHTTP2_REFUSED_STREAM;
-    default:
-      return GRPC_CHTTP2_INTERNAL_ERROR;
-  }
-}
-
-grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
-    grpc_chttp2_error_code error, gpr_timespec deadline) {
-  switch (error) {
-    case GRPC_CHTTP2_NO_ERROR:
-      /* should never be received */
-      return GRPC_STATUS_INTERNAL;
-    case GRPC_CHTTP2_CANCEL:
-      /* http2 cancel translates to STATUS_CANCELLED iff deadline hasn't been
-       * exceeded */
-      return gpr_time_cmp(gpr_now(deadline.clock_type), deadline) >= 0
-                 ? GRPC_STATUS_DEADLINE_EXCEEDED
-                 : GRPC_STATUS_CANCELLED;
-    case GRPC_CHTTP2_ENHANCE_YOUR_CALM:
-      return GRPC_STATUS_RESOURCE_EXHAUSTED;
-    case GRPC_CHTTP2_INADEQUATE_SECURITY:
-      return GRPC_STATUS_PERMISSION_DENIED;
-    case GRPC_CHTTP2_REFUSED_STREAM:
-      return GRPC_STATUS_UNAVAILABLE;
-    default:
-      return GRPC_STATUS_INTERNAL;
-  }
-}
-
-grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status) {
-  switch (status) {
-    /* these HTTP2 status codes are called out explicitly in status.proto */
-    case 200:
-      return GRPC_STATUS_OK;
-    case 400:
-      return GRPC_STATUS_INVALID_ARGUMENT;
-    case 401:
-      return GRPC_STATUS_UNAUTHENTICATED;
-    case 403:
-      return GRPC_STATUS_PERMISSION_DENIED;
-    case 404:
-      return GRPC_STATUS_NOT_FOUND;
-    case 409:
-      return GRPC_STATUS_ABORTED;
-    case 412:
-      return GRPC_STATUS_FAILED_PRECONDITION;
-    case 429:
-      return GRPC_STATUS_RESOURCE_EXHAUSTED;
-    case 499:
-      return GRPC_STATUS_CANCELLED;
-    case 500:
-      return GRPC_STATUS_UNKNOWN;
-    case 501:
-      return GRPC_STATUS_UNIMPLEMENTED;
-    case 503:
-      return GRPC_STATUS_UNAVAILABLE;
-    case 504:
-      return GRPC_STATUS_DEADLINE_EXCEEDED;
-    /* everything else is unknown */
-    default:
-      return GRPC_STATUS_UNKNOWN;
-  }
-}
-
-int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status) {
-  return 200;
-}
diff --git a/src/core/ext/transport/chttp2/transport/status_conversion.h b/src/core/ext/transport/chttp2/transport/status_conversion.h
deleted file mode 100644
index 953bc9f..0000000
--- a/src/core/ext/transport/chttp2/transport/status_conversion.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STATUS_CONVERSION_H
-#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STATUS_CONVERSION_H
-
-#include <grpc/grpc.h>
-#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
-
-/* Conversion of grpc status codes to http2 error codes (for RST_STREAM) */
-grpc_chttp2_error_code grpc_chttp2_grpc_status_to_http2_error(
-    grpc_status_code status);
-grpc_status_code grpc_chttp2_http2_error_to_grpc_status(
-    grpc_chttp2_error_code error, gpr_timespec deadline);
-
-/* Conversion of HTTP status codes (:status) to grpc status codes */
-grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status);
-int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status);
-
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STATUS_CONVERSION_H */
diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.c b/src/core/ext/transport/chttp2/transport/stream_lists.c
index a60264c..078818f 100644
--- a/src/core/ext/transport/chttp2/transport/stream_lists.c
+++ b/src/core/ext/transport/chttp2/transport/stream_lists.c
@@ -37,14 +37,14 @@
 
 /* core list management */
 
-static int stream_list_empty(grpc_chttp2_transport *t,
-                             grpc_chttp2_stream_list_id id) {
+static bool stream_list_empty(grpc_chttp2_transport *t,
+                              grpc_chttp2_stream_list_id id) {
   return t->lists[id].head == NULL;
 }
 
-static int stream_list_pop(grpc_chttp2_transport *t,
-                           grpc_chttp2_stream **stream,
-                           grpc_chttp2_stream_list_id id) {
+static bool stream_list_pop(grpc_chttp2_transport *t,
+                            grpc_chttp2_stream **stream,
+                            grpc_chttp2_stream_list_id id) {
   grpc_chttp2_stream *s = t->lists[id].head;
   if (s) {
     grpc_chttp2_stream *new_head = s->links[id].next;
@@ -124,8 +124,8 @@
   return stream_list_add(t, s, GRPC_CHTTP2_LIST_WRITABLE);
 }
 
-int grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t,
-                                         grpc_chttp2_stream **s) {
+bool grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t,
+                                          grpc_chttp2_stream **s) {
   return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WRITABLE);
 }
 
@@ -139,12 +139,12 @@
   return stream_list_add(t, s, GRPC_CHTTP2_LIST_WRITING);
 }
 
-int grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t) {
+bool grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t) {
   return !stream_list_empty(t, GRPC_CHTTP2_LIST_WRITING);
 }
 
-int grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t,
-                                        grpc_chttp2_stream **s) {
+bool grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t,
+                                         grpc_chttp2_stream **s) {
   return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WRITING);
 }
 
@@ -153,8 +153,8 @@
   stream_list_add(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
 }
 
-int grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t,
-                                                 grpc_chttp2_stream **s) {
+bool grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t,
+                                                  grpc_chttp2_stream **s) {
   return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
 }
 
@@ -168,8 +168,8 @@
   stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
 }
 
-int grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
-                                              grpc_chttp2_stream **s) {
+bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
+                                               grpc_chttp2_stream **s) {
   return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
 }
 
@@ -177,3 +177,18 @@
                                                   grpc_chttp2_stream *s) {
   stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
 }
+
+void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t,
+                                            grpc_chttp2_stream *s) {
+  stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
+}
+
+bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t,
+                                            grpc_chttp2_stream **s) {
+  return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
+}
+
+bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t,
+                                               grpc_chttp2_stream *s) {
+  return stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
+}
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
index ef2010a..2b9d93c 100644
--- a/src/core/ext/transport/chttp2/transport/writing.c
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -37,9 +37,9 @@
 
 #include <grpc/support/log.h>
 
-#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/http2_errors.h"
 
 static void add_to_write_list(grpc_chttp2_write_cb **list,
                               grpc_chttp2_write_cb *cb) {
@@ -56,6 +56,75 @@
   t->write_cb_pool = cb;
 }
 
+static void collapse_pings_from_into(grpc_chttp2_transport *t,
+                                     grpc_chttp2_ping_type ping_type,
+                                     grpc_chttp2_ping_queue *pq) {
+  for (size_t i = 0; i < GRPC_CHTTP2_PCL_COUNT; i++) {
+    grpc_closure_list_move(&t->ping_queues[ping_type].lists[i], &pq->lists[i]);
+  }
+}
+
+static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
+                                grpc_chttp2_transport *t,
+                                grpc_chttp2_ping_type ping_type) {
+  grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type];
+  if (grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
+    /* no ping needed: wait */
+    return;
+  }
+  if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) {
+    /* ping already in-flight: wait */
+    if (grpc_http_trace || grpc_bdp_estimator_trace) {
+      gpr_log(GPR_DEBUG, "Ping delayed [%p]: already pinging", t->peer_string);
+    }
+    return;
+  }
+  if (t->ping_state.pings_before_data_required == 0 &&
+      t->ping_policy.max_pings_without_data != 0) {
+    /* need to send something of substance before sending a ping again */
+    if (grpc_http_trace || grpc_bdp_estimator_trace) {
+      gpr_log(GPR_DEBUG, "Ping delayed [%p]: too many recent pings: %d/%d",
+              t->peer_string, t->ping_state.pings_before_data_required,
+              t->ping_policy.max_pings_without_data);
+    }
+    return;
+  }
+  gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
+  gpr_timespec elapsed = gpr_time_sub(now, t->ping_state.last_ping_sent_time);
+  /*gpr_log(GPR_DEBUG, "elapsed:%d.%09d min:%d.%09d", (int)elapsed.tv_sec,
+          elapsed.tv_nsec, (int)t->ping_policy.min_time_between_pings.tv_sec,
+          (int)t->ping_policy.min_time_between_pings.tv_nsec);*/
+  if (gpr_time_cmp(elapsed, t->ping_policy.min_time_between_pings) < 0) {
+    /* not enough elapsed time between successive pings */
+    if (grpc_http_trace || grpc_bdp_estimator_trace) {
+      gpr_log(GPR_DEBUG,
+              "Ping delayed [%p]: not enough time elapsed since last ping",
+              t->peer_string);
+    }
+    return;
+  }
+  /* coalesce equivalent pings into this one */
+  switch (ping_type) {
+    case GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE:
+      collapse_pings_from_into(t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, pq);
+      break;
+    case GRPC_CHTTP2_PING_ON_NEXT_WRITE:
+      break;
+    case GRPC_CHTTP2_PING_TYPE_COUNT:
+      GPR_UNREACHABLE_CODE(break);
+  }
+  pq->inflight_id = t->ping_ctr * GRPC_CHTTP2_PING_TYPE_COUNT + ping_type;
+  t->ping_ctr++;
+  grpc_closure_list_sched(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INITIATE]);
+  grpc_closure_list_move(&pq->lists[GRPC_CHTTP2_PCL_NEXT],
+                         &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
+  grpc_slice_buffer_add(&t->outbuf,
+                        grpc_chttp2_ping_create(false, pq->inflight_id));
+  t->ping_state.last_ping_sent_time = now;
+  t->ping_state.pings_before_data_required -=
+      (t->ping_state.pings_before_data_required != 0);
+}
+
 static void update_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
                         grpc_chttp2_stream *s, int64_t send_bytes,
                         grpc_chttp2_write_cb **list, grpc_error *error) {
@@ -74,6 +143,26 @@
   GRPC_ERROR_UNREF(error);
 }
 
+static bool stream_ref_if_not_destroyed(gpr_refcount *r) {
+  gpr_atm count;
+  do {
+    count = gpr_atm_acq_load(&r->count);
+    if (count == 0) return false;
+  } while (!gpr_atm_rel_cas(&r->count, count, count + 1));
+  return true;
+}
+
+uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t) {
+  return (uint32_t)GPR_MAX(
+      (int64_t)((1u << 31) - 1),
+      t->stream_total_over_incoming_window +
+          (int64_t)GPR_MAX(
+              t->settings[GRPC_SENT_SETTINGS]
+                         [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] -
+                  t->stream_total_under_incoming_window,
+              0));
+}
+
 bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
                              grpc_chttp2_transport *t) {
   grpc_chttp2_stream *s;
@@ -101,8 +190,11 @@
 
   if (t->outgoing_window > 0) {
     while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) {
-      grpc_chttp2_become_writable(exec_ctx, t, s, false,
-                                  "transport.read_flow_control");
+      if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s) &&
+          stream_ref_if_not_destroyed(&s->refcount->refs)) {
+        grpc_chttp2_initiate_write(exec_ctx, t, false,
+                                   "transport.read_flow_control");
+      }
     }
   }
 
@@ -127,6 +219,8 @@
       s->sent_initial_metadata = true;
       sent_initial_metadata = true;
       now_writing = true;
+      t->ping_state.pings_before_data_required =
+          t->ping_policy.max_pings_without_data;
     }
     /* send any window updates */
     if (s->announce_window > 0) {
@@ -134,15 +228,22 @@
       grpc_slice_buffer_add(&t->outbuf,
                             grpc_chttp2_window_update_create(
                                 s->id, s->announce_window, &s->stats.outgoing));
+      t->ping_state.pings_before_data_required =
+          t->ping_policy.max_pings_without_data;
       GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, announce_window, announce);
     }
     if (sent_initial_metadata) {
       /* send any body bytes, if allowed by flow control */
       if (s->flow_controlled_buffer.length > 0) {
-        uint32_t max_outgoing =
-            (uint32_t)GPR_MIN(t->settings[GRPC_ACKED_SETTINGS]
-                                         [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
-                              GPR_MIN(s->outgoing_window, t->outgoing_window));
+        uint32_t stream_outgoing_window = (uint32_t)GPR_MAX(
+            0,
+            s->outgoing_window_delta +
+                (int64_t)t->settings[GRPC_PEER_SETTINGS]
+                                    [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
+        uint32_t max_outgoing = (uint32_t)GPR_MIN(
+            t->settings[GRPC_ACKED_SETTINGS]
+                       [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
+            GPR_MIN(stream_outgoing_window, t->outgoing_window));
         if (max_outgoing > 0) {
           uint32_t send_bytes =
               (uint32_t)GPR_MIN(max_outgoing, s->flow_controlled_buffer.length);
@@ -155,16 +256,18 @@
           grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, send_bytes,
                                   is_last_frame, &s->stats.outgoing,
                                   &t->outbuf);
-          GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, outgoing_window,
+          GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, outgoing_window_delta,
                                         send_bytes);
           GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", t, outgoing_window,
                                            send_bytes);
+          t->ping_state.pings_before_data_required =
+              t->ping_policy.max_pings_without_data;
           if (is_last_frame) {
             s->send_trailing_metadata = NULL;
             s->sent_trailing_metadata = true;
             if (!t->is_client && !s->read_closed) {
               grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_rst_stream_create(
-                                                    s->id, GRPC_CHTTP2_NO_ERROR,
+                                                    s->id, GRPC_HTTP2_NO_ERROR,
                                                     &s->stats.outgoing));
             }
           }
@@ -177,6 +280,9 @@
         } else if (t->outgoing_window == 0) {
           grpc_chttp2_list_add_stalled_by_transport(t, s);
           now_writing = true;
+        } else if (stream_outgoing_window == 0) {
+          grpc_chttp2_list_add_stalled_by_stream(t, s);
+          now_writing = true;
         }
       }
       if (s->send_trailing_metadata != NULL &&
@@ -197,7 +303,7 @@
         if (!t->is_client && !s->read_closed) {
           grpc_slice_buffer_add(
               &t->outbuf, grpc_chttp2_rst_stream_create(
-                              s->id, GRPC_CHTTP2_NO_ERROR, &s->stats.outgoing));
+                              s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing));
         }
         now_writing = true;
       }
@@ -215,16 +321,32 @@
 
   /* if the grpc_chttp2_transport is ready to send a window update, do so here
      also; 3/4 is a magic number that will likely get tuned soon */
-  if (t->announce_incoming_window > 0) {
-    uint32_t announced =
-        (uint32_t)GPR_MIN(t->announce_incoming_window, UINT32_MAX);
-    GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", t, announce_incoming_window,
-                                     announced);
+  uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t);
+  uint32_t threshold_to_send_transport_window_update =
+      t->outbuf.count > 0 ? 3 * target_incoming_window / 4
+                          : target_incoming_window / 2;
+  if (t->incoming_window <= threshold_to_send_transport_window_update &&
+      t->incoming_window != target_incoming_window) {
+    maybe_initiate_ping(exec_ctx, t,
+                        GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE);
+    uint32_t announced = (uint32_t)GPR_CLAMP(
+        target_incoming_window - t->incoming_window, 0, UINT32_MAX);
+    GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("write", t, incoming_window, announced);
     grpc_transport_one_way_stats throwaway_stats;
     grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_window_update_create(
                                           0, announced, &throwaway_stats));
+    t->ping_state.pings_before_data_required =
+        t->ping_policy.max_pings_without_data;
   }
 
+  for (size_t i = 0; i < t->ping_ack_count; i++) {
+    grpc_slice_buffer_add(&t->outbuf,
+                          grpc_chttp2_ping_create(1, t->ping_acks[i]));
+  }
+  t->ping_ack_count = 0;
+
+  maybe_initiate_ping(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE);
+
   GPR_TIMER_END("grpc_chttp2_begin_write", 0);
 
   return t->outbuf.count > 0;
diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
index 477cf07..b6e9e84 100644
--- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
+++ b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
@@ -39,6 +39,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
+#include "src/core/ext/transport/cronet/transport/cronet_transport.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/transport/transport_impl.h"
 
@@ -54,16 +55,14 @@
 GRPCAPI grpc_channel *grpc_cronet_secure_channel_create(
     void *engine, const char *target, const grpc_channel_args *args,
     void *reserved) {
-  cronet_transport *ct = gpr_malloc(sizeof(cronet_transport));
-  ct->base.vtable = &grpc_cronet_vtable;
-  ct->engine = engine;
-  ct->host = gpr_malloc(strlen(target) + 1);
-  strcpy(ct->host, target);
   gpr_log(GPR_DEBUG,
           "grpc_create_cronet_transport: stream_engine = %p, target=%s", engine,
-          ct->host);
+          target);
+
+  grpc_transport *ct =
+      grpc_create_cronet_transport(engine, target, args, reserved);
 
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   return grpc_channel_create(&exec_ctx, target, args,
-                             GRPC_CLIENT_DIRECT_CHANNEL, (grpc_transport *)ct);
+                             GRPC_CLIENT_DIRECT_CHANNEL, ct);
 }
diff --git a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c
index 74327a4..0dc6a51 100644
--- a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c
+++ b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c
@@ -38,7 +38,7 @@
 
 #include <grpc/support/log.h>
 
-#include "third_party/Cronet/bidirectional_stream_c.h"
+#include "third_party/objective_c/Cronet/bidirectional_stream_c.h"
 
 #ifdef GRPC_COMPILE_WITH_CRONET
 /* link with the real CRONET library in the build system */
@@ -80,4 +80,16 @@
   GPR_ASSERT(0);
 }
 
+void bidirectional_stream_disable_auto_flush(bidirectional_stream* stream,
+                                             bool disable_auto_flush) {
+  GPR_ASSERT(0);
+}
+
+void bidirectional_stream_delay_request_headers_until_flush(
+    bidirectional_stream* stream, bool delay_headers_until_flush) {
+  GPR_ASSERT(0);
+}
+
+void bidirectional_stream_flush(bidirectional_stream* stream) { GPR_ASSERT(0); }
+
 #endif /* GRPC_COMPILE_WITH_CRONET */
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index 6f58163..01a0353 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -44,12 +44,14 @@
 #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/transport/metadata_batch.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "src/core/lib/transport/transport_impl.h"
-#include "third_party/Cronet/bidirectional_stream_c.h"
+#include "third_party/objective_c/Cronet/bidirectional_stream_c.h"
 
 #define GRPC_HEADER_SIZE_IN_BYTES 5
 
@@ -86,7 +88,7 @@
 
 /* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */
 
-static void on_request_headers_sent(bidirectional_stream *);
+static void on_stream_ready(bidirectional_stream *);
 static void on_response_headers_received(
     bidirectional_stream *, const bidirectional_stream_header_array *,
     const char *);
@@ -98,7 +100,7 @@
 static void on_failed(bidirectional_stream *, int);
 static void on_canceled(bidirectional_stream *);
 static bidirectional_stream_callback cronet_callbacks = {
-    on_request_headers_sent,
+    on_stream_ready,
     on_response_headers_received,
     on_read_completed,
     on_write_completed,
@@ -112,6 +114,7 @@
   grpc_transport base; /* must be first element in this structure */
   stream_engine *engine;
   char *host;
+  bool use_packet_coalescing;
 };
 typedef struct grpc_cronet_transport grpc_cronet_transport;
 
@@ -150,6 +153,9 @@
   bool state_callback_received[OP_NUM_OPS];
   bool fail_state;
   bool flush_read;
+  bool flush_cronet_when_ready;
+  bool pending_write_for_trailer;
+  bool unprocessed_send_message;
   grpc_error *cancel_error;
   /* data structure for storing data coming from server */
   struct read_state rs;
@@ -173,7 +179,7 @@
 struct stream_obj {
   struct op_and_state *oas;
   grpc_transport_stream_op *curr_op;
-  grpc_cronet_transport curr_ct;
+  grpc_cronet_transport *curr_ct;
   grpc_stream *curr_gs;
   bidirectional_stream *cbs;
   bidirectional_stream_header_array header_array;
@@ -272,6 +278,9 @@
   new_op->next = storage->head;
   storage->head = new_op;
   storage->num_pending_ops++;
+  if (op->send_message) {
+    s->state.unprocessed_send_message = true;
+  }
   CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op,
              storage->num_pending_ops);
   gpr_mu_unlock(&s->mu);
@@ -404,9 +413,10 @@
 /*
   Cronet callback
 */
-static void on_request_headers_sent(bidirectional_stream *stream) {
-  CRONET_LOG(GPR_DEBUG, "W: on_request_headers_sent(%p)", stream);
+static void on_stream_ready(bidirectional_stream *stream) {
+  CRONET_LOG(GPR_DEBUG, "W: on_stream_ready(%p)", stream);
   stream_obj *s = (stream_obj *)stream->annotation;
+  grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
   gpr_mu_lock(&s->mu);
   s->state.state_op_done[OP_SEND_INITIAL_METADATA] = true;
   s->state.state_callback_received[OP_SEND_INITIAL_METADATA] = true;
@@ -415,6 +425,14 @@
     gpr_free(s->header_array.headers);
     s->header_array.headers = NULL;
   }
+  /* Send the initial metadata on wire if there is no SEND_MESSAGE or
+   * SEND_TRAILING_METADATA ops pending */
+  if (t->use_packet_coalescing) {
+    if (s->state.flush_cronet_when_ready) {
+      CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_flush (%p)", s->cbs);
+      bidirectional_stream_flush(stream);
+    }
+  }
   gpr_mu_unlock(&s->mu);
   execute_from_storage(s);
 }
@@ -437,9 +455,11 @@
   for (size_t i = 0; i < headers->count; i++) {
     grpc_chttp2_incoming_metadata_buffer_add(
         &s->state.rs.initial_metadata,
-        grpc_mdelem_from_metadata_strings(
-            &exec_ctx, grpc_mdstr_from_string(headers->headers[i].key),
-            grpc_mdstr_from_string(headers->headers[i].value)));
+        grpc_mdelem_from_slices(
+            &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(
+                           headers->headers[i].key)),
+            grpc_slice_intern(
+                grpc_slice_from_static_string(headers->headers[i].value))));
   }
   s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true;
   if (!(s->state.state_op_done[OP_CANCEL_ERROR] ||
@@ -524,6 +544,7 @@
   CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream,
              trailers);
   stream_obj *s = (stream_obj *)stream->annotation;
+  grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
   gpr_mu_lock(&s->mu);
   memset(&s->state.rs.trailing_metadata, 0,
          sizeof(s->state.rs.trailing_metadata));
@@ -534,9 +555,11 @@
                trailers->headers[i].value);
     grpc_chttp2_incoming_metadata_buffer_add(
         &s->state.rs.trailing_metadata,
-        grpc_mdelem_from_metadata_strings(
-            &exec_ctx, grpc_mdstr_from_string(trailers->headers[i].key),
-            grpc_mdstr_from_string(trailers->headers[i].value)));
+        grpc_mdelem_from_slices(
+            &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(
+                           trailers->headers[i].key)),
+            grpc_slice_intern(
+                grpc_slice_from_static_string(trailers->headers[i].value))));
     s->state.rs.trailing_metadata_valid = true;
     if (0 == strcmp(trailers->headers[i].key, "grpc-status") &&
         0 != strcmp(trailers->headers[i].value, "0")) {
@@ -552,6 +575,10 @@
     CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
     s->state.state_callback_received[OP_SEND_MESSAGE] = false;
     bidirectional_stream_write(s->cbs, "", 0, true);
+    if (t->use_packet_coalescing) {
+      CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
+      bidirectional_stream_flush(s->cbs);
+    }
     s->state.state_op_done[OP_SEND_TRAILING_METADATA] = true;
 
     gpr_mu_unlock(&s->mu);
@@ -601,7 +628,7 @@
     curr = curr->next;
     num_headers_available++;
   }
-  /* Allocate enough memory. It is freed in the on_request_headers_sent callback
+  /* Allocate enough memory. It is freed in the on_stream_ready callback
    */
   bidirectional_stream_header *headers =
       (bidirectional_stream_header *)gpr_malloc(
@@ -616,27 +643,33 @@
   curr = head;
   size_t num_headers = 0;
   while (num_headers < num_headers_available) {
-    grpc_mdelem *mdelem = curr->md;
+    grpc_mdelem mdelem = curr->md;
     curr = curr->next;
-    const char *key = grpc_mdstr_as_c_string(mdelem->key);
-    const char *value = grpc_mdstr_as_c_string(mdelem->value);
-    if (mdelem->key == GRPC_MDSTR_SCHEME ||
-        mdelem->key == GRPC_MDSTR_AUTHORITY) {
+    char *key = grpc_slice_to_c_string(GRPC_MDKEY(mdelem));
+    char *value = grpc_slice_to_c_string(GRPC_MDVALUE(mdelem));
+    if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_SCHEME) ||
+        grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_AUTHORITY)) {
       /* Cronet populates these fields on its own */
+      gpr_free(key);
+      gpr_free(value);
       continue;
     }
-    if (mdelem->key == GRPC_MDSTR_METHOD) {
-      if (mdelem->value == GRPC_MDSTR_PUT) {
+    if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_METHOD)) {
+      if (grpc_slice_eq(GRPC_MDVALUE(mdelem), GRPC_MDSTR_PUT)) {
         *method = "PUT";
       } else {
         /* POST method in default*/
         *method = "POST";
       }
+      gpr_free(key);
+      gpr_free(value);
       continue;
     }
-    if (mdelem->key == GRPC_MDSTR_PATH) {
+    if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_PATH)) {
       /* Create URL by appending :path value to the hostname */
       gpr_asprintf(pp_url, "https://%s%s", host, value);
+      gpr_free(key);
+      gpr_free(value);
       continue;
     }
     CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value);
@@ -662,7 +695,7 @@
 
 static bool header_has_authority(grpc_linked_mdelem *head) {
   while (head != NULL) {
-    if (head->md->key == GRPC_MDSTR_AUTHORITY) {
+    if (grpc_slice_eq(GRPC_MDKEY(head->md), GRPC_MDSTR_AUTHORITY)) {
       return true;
     }
     head = head->next;
@@ -675,8 +708,10 @@
   executed. This is the heart of the state machine.
 */
 static bool op_can_be_run(grpc_transport_stream_op *curr_op,
-                          struct op_state *stream_state,
-                          struct op_state *op_state, enum e_op_id op_id) {
+                          struct stream_obj *s, struct op_state *op_state,
+                          enum e_op_id op_id) {
+  struct op_state *stream_state = &s->state;
+  grpc_cronet_transport *t = s->curr_ct;
   bool result = true;
   /* When call is canceled, every op can be run, except under following
   conditions
@@ -743,12 +778,14 @@
     else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
       result = false;
     /* we haven't sent message yet */
-    else if (curr_op->send_message &&
+    else if (stream_state->unprocessed_send_message &&
              !stream_state->state_op_done[OP_SEND_MESSAGE])
       result = false;
     /* we haven't got on_write_completed for the send yet */
     else if (stream_state->state_op_done[OP_SEND_MESSAGE] &&
-             !stream_state->state_callback_received[OP_SEND_MESSAGE])
+             !stream_state->state_callback_received[OP_SEND_MESSAGE] &&
+             !(t->use_packet_coalescing &&
+               stream_state->pending_write_for_trailer))
       result = false;
   } else if (op_id == OP_CANCEL_ERROR) {
     /* already executed */
@@ -821,52 +858,49 @@
                                           struct op_and_state *oas) {
   grpc_transport_stream_op *stream_op = &oas->op;
   struct stream_obj *s = oas->s;
+  grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
   struct op_state *stream_state = &s->state;
   enum e_op_result result = NO_ACTION_POSSIBLE;
   if (stream_op->send_initial_metadata &&
-      op_can_be_run(stream_op, stream_state, &oas->state,
-                    OP_SEND_INITIAL_METADATA)) {
+      op_can_be_run(stream_op, s, &oas->state, OP_SEND_INITIAL_METADATA)) {
     CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas);
     /* Start new cronet stream. It is destroyed in on_succeeded, on_canceled,
      * on_failed */
     GPR_ASSERT(s->cbs == NULL);
     GPR_ASSERT(!stream_state->state_op_done[OP_SEND_INITIAL_METADATA]);
-    s->cbs = bidirectional_stream_create(s->curr_ct.engine, s->curr_gs,
-                                         &cronet_callbacks);
+    s->cbs =
+        bidirectional_stream_create(t->engine, s->curr_gs, &cronet_callbacks);
     CRONET_LOG(GPR_DEBUG, "%p = bidirectional_stream_create()", s->cbs);
+    if (t->use_packet_coalescing) {
+      bidirectional_stream_disable_auto_flush(s->cbs, true);
+      bidirectional_stream_delay_request_headers_until_flush(s->cbs, true);
+    }
     char *url = NULL;
     const char *method = "POST";
     s->header_array.headers = NULL;
     convert_metadata_to_cronet_headers(
-        stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url,
+        stream_op->send_initial_metadata->list.head, t->host, &url,
         &s->header_array.headers, &s->header_array.count, &method);
     s->header_array.capacity = s->header_array.count;
     CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url);
     bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false);
-    stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true;
-    result = ACTION_TAKEN_WITH_CALLBACK;
-  } else if (stream_op->recv_initial_metadata &&
-             op_can_be_run(stream_op, stream_state, &oas->state,
-                           OP_RECV_INITIAL_METADATA)) {
-    CRONET_LOG(GPR_DEBUG, "running: %p  OP_RECV_INITIAL_METADATA", oas);
-    if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
-      grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
-                         GRPC_ERROR_NONE);
-    } else if (stream_state->state_callback_received[OP_FAILED]) {
-      grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
-                         GRPC_ERROR_NONE);
-    } else {
-      grpc_chttp2_incoming_metadata_buffer_publish(
-          &oas->s->state.rs.initial_metadata, stream_op->recv_initial_metadata);
-      grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
-                         GRPC_ERROR_NONE);
+    unsigned int header_index;
+    for (header_index = 0; header_index < s->header_array.count;
+         header_index++) {
+      gpr_free((void *)s->header_array.headers[header_index].key);
+      gpr_free((void *)s->header_array.headers[header_index].value);
     }
-    stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true;
-    result = ACTION_TAKEN_NO_CALLBACK;
+    stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true;
+    if (t->use_packet_coalescing) {
+      if (!stream_op->send_message && !stream_op->send_trailing_metadata) {
+        s->state.flush_cronet_when_ready = true;
+      }
+    }
+    result = ACTION_TAKEN_WITH_CALLBACK;
   } else if (stream_op->send_message &&
-             op_can_be_run(stream_op, stream_state, &oas->state,
-                           OP_SEND_MESSAGE)) {
+             op_can_be_run(stream_op, s, &oas->state, OP_SEND_MESSAGE)) {
     CRONET_LOG(GPR_DEBUG, "running: %p  OP_SEND_MESSAGE", oas);
+    stream_state->unprocessed_send_message = false;
     if (stream_state->state_callback_received[OP_FAILED]) {
       result = NO_ACTION_POSSIBLE;
       CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
@@ -897,16 +931,63 @@
         stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
         bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer,
                                    (int)write_buffer_size, false);
-        result = ACTION_TAKEN_WITH_CALLBACK;
+        if (t->use_packet_coalescing) {
+          if (!stream_op->send_trailing_metadata) {
+            CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
+            bidirectional_stream_flush(s->cbs);
+            result = ACTION_TAKEN_WITH_CALLBACK;
+          } else {
+            stream_state->pending_write_for_trailer = true;
+            result = ACTION_TAKEN_NO_CALLBACK;
+          }
+        } else {
+          result = ACTION_TAKEN_WITH_CALLBACK;
+        }
       } else {
         result = NO_ACTION_POSSIBLE;
       }
     }
     stream_state->state_op_done[OP_SEND_MESSAGE] = true;
     oas->state.state_op_done[OP_SEND_MESSAGE] = true;
+  } else if (stream_op->send_trailing_metadata &&
+             op_can_be_run(stream_op, s, &oas->state,
+                           OP_SEND_TRAILING_METADATA)) {
+    CRONET_LOG(GPR_DEBUG, "running: %p  OP_SEND_TRAILING_METADATA", oas);
+    if (stream_state->state_callback_received[OP_FAILED]) {
+      result = NO_ACTION_POSSIBLE;
+      CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
+    } else {
+      CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
+      stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
+      bidirectional_stream_write(s->cbs, "", 0, true);
+      if (t->use_packet_coalescing) {
+        CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
+        bidirectional_stream_flush(s->cbs);
+      }
+      result = ACTION_TAKEN_WITH_CALLBACK;
+    }
+    stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true;
+  } else if (stream_op->recv_initial_metadata &&
+             op_can_be_run(stream_op, s, &oas->state,
+                           OP_RECV_INITIAL_METADATA)) {
+    CRONET_LOG(GPR_DEBUG, "running: %p  OP_RECV_INITIAL_METADATA", oas);
+    if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
+      grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+                         GRPC_ERROR_NONE);
+    } else if (stream_state->state_callback_received[OP_FAILED]) {
+      grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+                         GRPC_ERROR_NONE);
+    } else {
+      grpc_chttp2_incoming_metadata_buffer_publish(
+          exec_ctx, &oas->s->state.rs.initial_metadata,
+          stream_op->recv_initial_metadata);
+      grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+                         GRPC_ERROR_NONE);
+    }
+    stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true;
+    result = ACTION_TAKEN_NO_CALLBACK;
   } else if (stream_op->recv_message &&
-             op_can_be_run(stream_op, stream_state, &oas->state,
-                           OP_RECV_MESSAGE)) {
+             op_can_be_run(stream_op, s, &oas->state, OP_RECV_MESSAGE)) {
     CRONET_LOG(GPR_DEBUG, "running: %p  OP_RECV_MESSAGE", oas);
     if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
       CRONET_LOG(GPR_DEBUG, "Stream is cancelled.");
@@ -961,6 +1042,16 @@
                              GRPC_ERROR_NONE);
           stream_state->state_op_done[OP_RECV_MESSAGE] = true;
           oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+
+          /* Extra read to trigger on_succeed */
+          stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes;
+          stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
+          stream_state->rs.received_bytes = 0;
+          CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
+          stream_state->state_op_done[OP_READ_REQ_MADE] =
+              true; /* Indicates that at least one read request has been made */
+          bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
+                                    stream_state->rs.remaining_bytes);
           result = ACTION_TAKEN_NO_CALLBACK;
         }
       } else if (stream_state->rs.remaining_bytes == 0) {
@@ -1008,34 +1099,19 @@
       result = ACTION_TAKEN_NO_CALLBACK;
     }
   } else if (stream_op->recv_trailing_metadata &&
-             op_can_be_run(stream_op, stream_state, &oas->state,
+             op_can_be_run(stream_op, s, &oas->state,
                            OP_RECV_TRAILING_METADATA)) {
     CRONET_LOG(GPR_DEBUG, "running: %p  OP_RECV_TRAILING_METADATA", oas);
     if (oas->s->state.rs.trailing_metadata_valid) {
       grpc_chttp2_incoming_metadata_buffer_publish(
-          &oas->s->state.rs.trailing_metadata,
+          exec_ctx, &oas->s->state.rs.trailing_metadata,
           stream_op->recv_trailing_metadata);
       stream_state->rs.trailing_metadata_valid = false;
     }
     stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true;
     result = ACTION_TAKEN_NO_CALLBACK;
-  } else if (stream_op->send_trailing_metadata &&
-             op_can_be_run(stream_op, stream_state, &oas->state,
-                           OP_SEND_TRAILING_METADATA)) {
-    CRONET_LOG(GPR_DEBUG, "running: %p  OP_SEND_TRAILING_METADATA", oas);
-    if (stream_state->state_callback_received[OP_FAILED]) {
-      result = NO_ACTION_POSSIBLE;
-      CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
-    } else {
-      CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
-      stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
-      bidirectional_stream_write(s->cbs, "", 0, true);
-      result = ACTION_TAKEN_WITH_CALLBACK;
-    }
-    stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true;
   } else if (stream_op->cancel_error &&
-             op_can_be_run(stream_op, stream_state, &oas->state,
-                           OP_CANCEL_ERROR)) {
+             op_can_be_run(stream_op, s, &oas->state, OP_CANCEL_ERROR)) {
     CRONET_LOG(GPR_DEBUG, "running: %p  OP_CANCEL_ERROR", oas);
     CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs);
     if (s->cbs) {
@@ -1049,8 +1125,7 @@
       stream_state->cancel_error = GRPC_ERROR_REF(stream_op->cancel_error);
     }
   } else if (stream_op->on_complete &&
-             op_can_be_run(stream_op, stream_state, &oas->state,
-                           OP_ON_COMPLETE)) {
+             op_can_be_run(stream_op, s, &oas->state, OP_ON_COMPLETE)) {
     CRONET_LOG(GPR_DEBUG, "running: %p  OP_ON_COMPLETE", oas);
     if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
       grpc_closure_sched(exec_ctx, stream_op->on_complete,
@@ -1114,6 +1189,12 @@
          sizeof(s->state.state_callback_received));
   s->state.fail_state = s->state.flush_read = false;
   s->state.cancel_error = NULL;
+  s->state.flush_cronet_when_ready = s->state.pending_write_for_trailer = false;
+  s->state.unprocessed_send_message = false;
+
+  s->curr_gs = gs;
+  s->curr_ct = (grpc_cronet_transport *)gt;
+
   gpr_mu_init(&s->mu);
   return 0;
 }
@@ -1129,8 +1210,6 @@
                               grpc_stream *gs, grpc_transport_stream_op *op) {
   CRONET_LOG(GPR_DEBUG, "perform_stream_op");
   stream_obj *s = (stream_obj *)gs;
-  s->curr_gs = gs;
-  memcpy(&s->curr_ct, gt, sizeof(grpc_cronet_transport));
   add_to_storage(s, op);
   if (op->send_initial_metadata &&
       header_has_authority(op->send_initial_metadata->list.head)) {
@@ -1178,14 +1257,58 @@
 static void perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
                        grpc_transport_op *op) {}
 
-const grpc_transport_vtable grpc_cronet_vtable = {sizeof(stream_obj),
-                                                  "cronet_http",
-                                                  init_stream,
-                                                  set_pollset_do_nothing,
-                                                  set_pollset_set_do_nothing,
-                                                  perform_stream_op,
-                                                  perform_op,
-                                                  destroy_stream,
-                                                  destroy_transport,
-                                                  get_peer,
-                                                  get_endpoint};
+static const grpc_transport_vtable grpc_cronet_vtable = {
+    sizeof(stream_obj),
+    "cronet_http",
+    init_stream,
+    set_pollset_do_nothing,
+    set_pollset_set_do_nothing,
+    perform_stream_op,
+    perform_op,
+    destroy_stream,
+    destroy_transport,
+    get_peer,
+    get_endpoint};
+
+grpc_transport *grpc_create_cronet_transport(void *engine, const char *target,
+                                             const grpc_channel_args *args,
+                                             void *reserved) {
+  grpc_cronet_transport *ct = gpr_malloc(sizeof(grpc_cronet_transport));
+  if (!ct) {
+    goto error;
+  }
+  ct->base.vtable = &grpc_cronet_vtable;
+  ct->engine = engine;
+  ct->host = gpr_malloc(strlen(target) + 1);
+  if (!ct->host) {
+    goto error;
+  }
+  strcpy(ct->host, target);
+
+  ct->use_packet_coalescing = true;
+  if (args) {
+    for (size_t i = 0; i < args->num_args; i++) {
+      if (0 ==
+          strcmp(args->args[i].key, GRPC_ARG_USE_CRONET_PACKET_COALESCING)) {
+        if (args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
+                  GRPC_ARG_USE_CRONET_PACKET_COALESCING);
+        } else {
+          ct->use_packet_coalescing = (args->args[i].value.integer != 0);
+        }
+      }
+    }
+  }
+
+  return &ct->base;
+
+error:
+  if (ct) {
+    if (ct->host) {
+      gpr_free(ct->host);
+    }
+    gpr_free(ct);
+  }
+
+  return NULL;
+}
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.h b/src/core/ext/transport/cronet/transport/cronet_transport.h
new file mode 100644
index 0000000..169ce31
--- /dev/null
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H
+#define GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H
+
+#include "src/core/lib/transport/transport.h"
+
+grpc_transport *grpc_create_cronet_transport(void *engine, const char *target,
+                                             const grpc_channel_args *args,
+                                             void *reserved);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H */
diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c
index 8f08b42..3fb2a60 100644
--- a/src/core/lib/channel/channel_stack.c
+++ b/src/core/lib/channel/channel_stack.c
@@ -170,10 +170,9 @@
     grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
     int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg,
     grpc_call_context_element *context, const void *transport_server_data,
-    grpc_mdstr *path, gpr_timespec start_time, gpr_timespec deadline,
+    grpc_slice path, gpr_timespec start_time, gpr_timespec deadline,
     grpc_call_stack *call_stack) {
   grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
-  grpc_call_element_args args;
   size_t count = channel_stack->count;
   grpc_call_element *call_elems;
   char *user_data;
@@ -188,13 +187,15 @@
 
   /* init per-filter data */
   grpc_error *first_error = GRPC_ERROR_NONE;
-  args.start_time = start_time;
+  const grpc_call_element_args args = {
+      .start_time = start_time,
+      .call_stack = call_stack,
+      .server_transport_data = transport_server_data,
+      .context = context,
+      .path = path,
+      .deadline = deadline,
+  };
   for (i = 0; i < count; i++) {
-    args.call_stack = call_stack;
-    args.server_transport_data = transport_server_data;
-    args.context = context;
-    args.path = path;
-    args.deadline = deadline;
     call_elems[i].filter = channel_elems[i].filter;
     call_elems[i].channel_data = channel_elems[i].channel_data;
     call_elems[i].call_data = user_data;
@@ -288,41 +289,10 @@
       sizeof(grpc_call_stack)));
 }
 
-static void destroy_op(grpc_exec_ctx *exec_ctx, void *op, grpc_error *error) {
-  gpr_free(op);
-}
-
-void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
-                                   grpc_call_element *elem) {
-  grpc_transport_stream_op *op = gpr_malloc(sizeof(*op));
-  memset(op, 0, sizeof(*op));
-  op->cancel_error = GRPC_ERROR_CANCELLED;
-  op->on_complete =
-      grpc_closure_create(destroy_op, op, grpc_schedule_on_exec_ctx);
-  elem->filter->start_transport_stream_op(exec_ctx, elem, op);
-}
-
-void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx,
-                                                grpc_call_element *elem,
-                                                grpc_status_code status,
-                                                grpc_slice *optional_message) {
-  grpc_transport_stream_op *op = gpr_malloc(sizeof(*op));
-  memset(op, 0, sizeof(*op));
-  op->on_complete =
-      grpc_closure_create(destroy_op, op, grpc_schedule_on_exec_ctx);
-  grpc_transport_stream_op_add_cancellation_with_message(exec_ctx, op, status,
-                                                         optional_message);
-  elem->filter->start_transport_stream_op(exec_ctx, elem, op);
-}
-
-void grpc_call_element_send_close_with_message(grpc_exec_ctx *exec_ctx,
-                                               grpc_call_element *elem,
-                                               grpc_status_code status,
-                                               grpc_slice *optional_message) {
-  grpc_transport_stream_op *op = gpr_malloc(sizeof(*op));
-  memset(op, 0, sizeof(*op));
-  op->on_complete =
-      grpc_closure_create(destroy_op, op, grpc_schedule_on_exec_ctx);
-  grpc_transport_stream_op_add_close(exec_ctx, op, status, optional_message);
+void grpc_call_element_signal_error(grpc_exec_ctx *exec_ctx,
+                                    grpc_call_element *elem,
+                                    grpc_error *error) {
+  grpc_transport_stream_op *op = grpc_make_transport_stream_op(NULL);
+  op->cancel_error = error;
   elem->filter->start_transport_stream_op(exec_ctx, elem, op);
 }
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index d9d3a85..6d3340b 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -81,7 +81,7 @@
   grpc_call_stack *call_stack;
   const void *server_transport_data;
   grpc_call_context_element *context;
-  grpc_mdstr *path;
+  grpc_slice path;
   gpr_timespec start_time;
   gpr_timespec deadline;
 } grpc_call_element_args;
@@ -128,10 +128,11 @@
      server_transport_data is an opaque pointer. If it is NULL, this call is
      on a client; if it is non-NULL, then it points to memory owned by the
      transport and is on the server. Most filters want to ignore this
-     argument. */
+     argument.
+     Implementations may assume that elem->call_data is all zeros. */
   grpc_error *(*init_call_elem)(grpc_exec_ctx *exec_ctx,
                                 grpc_call_element *elem,
-                                grpc_call_element_args *args);
+                                const grpc_call_element_args *args);
   void (*set_pollset_or_pollset_set)(grpc_exec_ctx *exec_ctx,
                                      grpc_call_element *elem,
                                      grpc_polling_entity *pollent);
@@ -152,7 +153,8 @@
      is what needs initializing.
      is_first, is_last designate this elements position in the stack, and are
      useful for asserting correct configuration by upper layer code.
-     The filter does not need to do any chaining */
+     The filter does not need to do any chaining.
+     Implementations may assume that elem->call_data is all zeros. */
   grpc_error *(*init_channel_elem)(grpc_exec_ctx *exec_ctx,
                                    grpc_channel_element *elem,
                                    grpc_channel_element_args *args);
@@ -238,7 +240,7 @@
     grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
     int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg,
     grpc_call_context_element *context, const void *transport_server_data,
-    grpc_mdstr *path, gpr_timespec start_time, gpr_timespec deadline,
+    grpc_slice path, gpr_timespec start_time, gpr_timespec deadline,
     grpc_call_stack *call_stack);
 /* Set a pollset or a pollset_set for a call stack: must occur before the first
  * op is started */
@@ -299,18 +301,9 @@
 void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
                       grpc_call_element *elem, grpc_transport_stream_op *op);
 
-void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
-                                   grpc_call_element *cur_elem);
-
-void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx,
-                                                grpc_call_element *cur_elem,
-                                                grpc_status_code status,
-                                                grpc_slice *optional_message);
-
-void grpc_call_element_send_close_with_message(grpc_exec_ctx *exec_ctx,
-                                               grpc_call_element *cur_elem,
-                                               grpc_status_code status,
-                                               grpc_slice *optional_message);
+void grpc_call_element_signal_error(grpc_exec_ctx *exec_ctx,
+                                    grpc_call_element *cur_elem,
+                                    grpc_error *error);
 
 extern int grpc_trace_channel;
 
diff --git a/src/core/lib/channel/channel_stack_builder.c b/src/core/lib/channel/channel_stack_builder.c
index 5f9e3b4..b515b73 100644
--- a/src/core/lib/channel/channel_stack_builder.c
+++ b/src/core/lib/channel/channel_stack_builder.c
@@ -65,8 +65,7 @@
 };
 
 grpc_channel_stack_builder *grpc_channel_stack_builder_create(void) {
-  grpc_channel_stack_builder *b = gpr_malloc(sizeof(*b));
-  memset(b, 0, sizeof(*b));
+  grpc_channel_stack_builder *b = gpr_zalloc(sizeof(*b));
 
   b->begin.filter = NULL;
   b->end.filter = NULL;
@@ -251,7 +250,7 @@
   size_t channel_stack_size = grpc_channel_stack_size(filters, num_filters);
 
   // allocate memory, with prefix_bytes followed by channel_stack_size
-  *result = gpr_malloc(prefix_bytes + channel_stack_size);
+  *result = gpr_zalloc(prefix_bytes + channel_stack_size);
   // fetch a pointer to the channel stack
   grpc_channel_stack *channel_stack =
       (grpc_channel_stack *)((char *)(*result) + prefix_bytes);
diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c
index 337c194..aa41014 100644
--- a/src/core/lib/channel/compress_filter.c
+++ b/src/core/lib/channel/compress_filter.c
@@ -45,6 +45,7 @@
 #include "src/core/lib/compression/message_compress.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/transport/static_metadata.h"
 
@@ -80,39 +81,6 @@
   uint32_t supported_compression_algorithms;
 } channel_data;
 
-/** For each \a md element from the incoming metadata, filter out the entry for
- * "grpc-encoding", using its value to populate the call data's
- * compression_algorithm field. */
-static grpc_mdelem *compression_md_filter(grpc_exec_ctx *exec_ctx,
-                                          void *user_data, grpc_mdelem *md) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  channel_data *channeld = elem->channel_data;
-
-  if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) {
-    const char *md_c_str = grpc_mdstr_as_c_string(md->value);
-    if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
-                                          &calld->compression_algorithm)) {
-      gpr_log(GPR_ERROR,
-              "Invalid compression algorithm: '%s' (unknown). Ignoring.",
-              md_c_str);
-      calld->compression_algorithm = GRPC_COMPRESS_NONE;
-    }
-    if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
-                    calld->compression_algorithm)) {
-      gpr_log(GPR_ERROR,
-              "Invalid compression algorithm: '%s' (previously disabled). "
-              "Ignoring.",
-              md_c_str);
-      calld->compression_algorithm = GRPC_COMPRESS_NONE;
-    }
-    calld->has_compression_algorithm = 1;
-    return NULL;
-  }
-
-  return md;
-}
-
 static int skip_compression(grpc_call_element *elem, uint32_t flags) {
   call_data *calld = elem->call_data;
   channel_data *channeld = elem->channel_data;
@@ -131,32 +99,67 @@
 }
 
 /** Filter initial metadata */
-static void process_send_initial_metadata(
+static grpc_error *process_send_initial_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+    grpc_metadata_batch *initial_metadata) GRPC_MUST_USE_RESULT;
+static grpc_error *process_send_initial_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
     grpc_metadata_batch *initial_metadata) {
   call_data *calld = elem->call_data;
   channel_data *channeld = elem->channel_data;
   /* Parse incoming request for compression. If any, it'll be available
    * at calld->compression_algorithm */
-  grpc_metadata_batch_filter(exec_ctx, initial_metadata, compression_md_filter,
-                             elem);
-  if (!calld->has_compression_algorithm) {
+  if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) {
+    grpc_mdelem md =
+        initial_metadata->idx.named.grpc_internal_encoding_request->md;
+    if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
+                                          &calld->compression_algorithm)) {
+      char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+      gpr_log(GPR_ERROR,
+              "Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
+      gpr_free(val);
+      calld->compression_algorithm = GRPC_COMPRESS_NONE;
+    }
+    if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
+                    calld->compression_algorithm)) {
+      char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+      gpr_log(GPR_ERROR,
+              "Invalid compression algorithm: '%s' (previously disabled). "
+              "Ignoring.",
+              val);
+      gpr_free(val);
+      calld->compression_algorithm = GRPC_COMPRESS_NONE;
+    }
+    calld->has_compression_algorithm = 1;
+
+    grpc_metadata_batch_remove(
+        exec_ctx, initial_metadata,
+        initial_metadata->idx.named.grpc_internal_encoding_request);
+  } else {
     /* If no algorithm was found in the metadata and we aren't
      * exceptionally skipping compression, fall back to the channel
      * default */
     calld->compression_algorithm = channeld->default_compression_algorithm;
     calld->has_compression_algorithm = 1; /* GPR_TRUE */
   }
+
+  grpc_error *error = GRPC_ERROR_NONE;
   /* hint compression algorithm */
-  grpc_metadata_batch_add_tail(
-      initial_metadata, &calld->compression_algorithm_storage,
-      grpc_compression_encoding_mdelem(calld->compression_algorithm));
+  if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
+    error = grpc_metadata_batch_add_tail(
+        exec_ctx, initial_metadata, &calld->compression_algorithm_storage,
+        grpc_compression_encoding_mdelem(calld->compression_algorithm));
+  }
+
+  if (error != GRPC_ERROR_NONE) return error;
 
   /* convey supported compression algorithms */
-  grpc_metadata_batch_add_tail(initial_metadata,
-                               &calld->accept_encoding_storage,
-                               GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
-                                   channeld->supported_compression_algorithms));
+  error = grpc_metadata_batch_add_tail(
+      exec_ctx, initial_metadata, &calld->accept_encoding_storage,
+      GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
+          channeld->supported_compression_algorithms));
+
+  return error;
 }
 
 static void continue_send_message(grpc_exec_ctx *exec_ctx,
@@ -247,7 +250,12 @@
   GPR_TIMER_BEGIN("compress_start_transport_stream_op", 0);
 
   if (op->send_initial_metadata) {
-    process_send_initial_metadata(exec_ctx, elem, op->send_initial_metadata);
+    grpc_error *error = process_send_initial_metadata(
+        exec_ctx, elem, op->send_initial_metadata);
+    if (error != GRPC_ERROR_NONE) {
+      grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
+      return;
+    }
   }
   if (op->send_message != NULL &&
       !skip_compression(elem, op->send_message->flags)) {
@@ -266,7 +274,7 @@
 /* Constructor for call_data */
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   /* grab pointers to our data from the call element */
   call_data *calld = elem->call_data;
 
diff --git a/src/core/lib/channel/connected_channel.c b/src/core/lib/channel/connected_channel.c
index ccc0619..29796f7 100644
--- a/src/core/lib/channel/connected_channel.c
+++ b/src/core/lib/channel/connected_channel.c
@@ -83,7 +83,7 @@
 /* Constructor for call_data */
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
   int r = grpc_transport_init_stream(
@@ -140,7 +140,7 @@
                                  grpc_channel_element *elem,
                                  const grpc_channel_info *channel_info) {}
 
-static const grpc_channel_filter connected_channel_filter = {
+const grpc_channel_filter grpc_connected_filter = {
     con_start_transport_stream_op,
     con_start_transport_op,
     sizeof(call_data),
@@ -158,7 +158,7 @@
 static void bind_transport(grpc_channel_stack *channel_stack,
                            grpc_channel_element *elem, void *t) {
   channel_data *cd = (channel_data *)elem->channel_data;
-  GPR_ASSERT(elem->filter == &connected_channel_filter);
+  GPR_ASSERT(elem->filter == &grpc_connected_filter);
   GPR_ASSERT(cd->transport == NULL);
   cd->transport = t;
 
@@ -178,7 +178,7 @@
   grpc_transport *t = grpc_channel_stack_builder_get_transport(builder);
   GPR_ASSERT(t != NULL);
   return grpc_channel_stack_builder_append_filter(
-      builder, &connected_channel_filter, bind_transport, t);
+      builder, &grpc_connected_filter, bind_transport, t);
 }
 
 grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem) {
diff --git a/src/core/lib/channel/connected_channel.h b/src/core/lib/channel/connected_channel.h
index 3585c0e..5c7ea9e 100644
--- a/src/core/lib/channel/connected_channel.h
+++ b/src/core/lib/channel/connected_channel.h
@@ -36,8 +36,13 @@
 
 #include "src/core/lib/channel/channel_stack_builder.h"
 
+extern const grpc_channel_filter grpc_connected_filter;
+
 bool grpc_add_connected_filter(grpc_exec_ctx *exec_ctx,
                                grpc_channel_stack_builder *builder,
                                void *arg_must_be_null);
 
+/* Debug helper to dig the transport stream out of a call element */
+grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem);
+
 #endif /* GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H */
diff --git a/src/core/lib/channel/context.h b/src/core/lib/channel/context.h
index 6c931ad..2c1174c 100644
--- a/src/core/lib/channel/context.h
+++ b/src/core/lib/channel/context.h
@@ -50,6 +50,9 @@
   /// Reserved for traffic_class_context.
   GRPC_CONTEXT_TRAFFIC,
 
+  /// Costs for Load Reporting.
+  GRPC_CONTEXT_LR_COST,
+
   GRPC_CONTEXT_COUNT
 } grpc_context_index;
 
diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c
index a45a4d4..5a12d62 100644
--- a/src/core/lib/channel/deadline_filter.c
+++ b/src/core/lib/channel/deadline_filter.c
@@ -52,66 +52,75 @@
                            grpc_error* error) {
   grpc_call_element* elem = arg;
   grpc_deadline_state* deadline_state = elem->call_data;
-  gpr_mu_lock(&deadline_state->timer_mu);
-  deadline_state->timer_pending = false;
-  gpr_mu_unlock(&deadline_state->timer_mu);
   if (error != GRPC_ERROR_CANCELLED) {
-    grpc_slice msg = grpc_slice_from_static_string("Deadline Exceeded");
-    grpc_call_element_send_cancel_with_message(
-        exec_ctx, elem, GRPC_STATUS_DEADLINE_EXCEEDED, &msg);
-    grpc_slice_unref_internal(exec_ctx, msg);
+    grpc_call_element_signal_error(
+        exec_ctx, elem,
+        grpc_error_set_int(GRPC_ERROR_CREATE("Deadline Exceeded"),
+                           GRPC_ERROR_INT_GRPC_STATUS,
+                           GRPC_STATUS_DEADLINE_EXCEEDED));
   }
   GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer");
 }
 
 // Starts the deadline timer.
-static void start_timer_if_needed_locked(grpc_exec_ctx* exec_ctx,
-                                         grpc_call_element* elem,
-                                         gpr_timespec deadline) {
-  grpc_deadline_state* deadline_state = elem->call_data;
-  deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
-  // Note: We do not start the timer if there is already a timer
-  // pending.  This should be okay, because this is only called from two
-  // functions exported by this module: grpc_deadline_state_start(), which
-  // starts the initial timer, and grpc_deadline_state_reset(), which
-  // cancels any pre-existing timer before starting a new one.  In
-  // particular, we want to ensure that if grpc_deadline_state_start()
-  // winds up trying to start the timer after grpc_deadline_state_reset()
-  // has already done so, we ignore the value from the former.
-  if (!deadline_state->timer_pending &&
-      gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) {
-    // Take a reference to the call stack, to be owned by the timer.
-    GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
-    deadline_state->timer_pending = true;
-    grpc_closure_init(&deadline_state->timer_callback, timer_callback, elem,
-                      grpc_schedule_on_exec_ctx);
-    grpc_timer_init(exec_ctx, &deadline_state->timer, deadline,
-                    &deadline_state->timer_callback,
-                    gpr_now(GPR_CLOCK_MONOTONIC));
-  }
-}
 static void start_timer_if_needed(grpc_exec_ctx* exec_ctx,
                                   grpc_call_element* elem,
                                   gpr_timespec deadline) {
+  deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
+  if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) == 0) {
+    return;
+  }
   grpc_deadline_state* deadline_state = elem->call_data;
-  gpr_mu_lock(&deadline_state->timer_mu);
-  start_timer_if_needed_locked(exec_ctx, elem, deadline);
-  gpr_mu_unlock(&deadline_state->timer_mu);
+  grpc_deadline_timer_state cur_state;
+  grpc_closure* closure = NULL;
+retry:
+  cur_state =
+      (grpc_deadline_timer_state)gpr_atm_acq_load(&deadline_state->timer_state);
+  switch (cur_state) {
+    case GRPC_DEADLINE_STATE_PENDING:
+      // Note: We do not start the timer if there is already a timer
+      return;
+    case GRPC_DEADLINE_STATE_FINISHED:
+      if (gpr_atm_rel_cas(&deadline_state->timer_state,
+                          GRPC_DEADLINE_STATE_FINISHED,
+                          GRPC_DEADLINE_STATE_PENDING)) {
+        // If we've already created and destroyed a timer, we always create a
+        // new closure: we have no other guarantee that the inlined closure is
+        // not in use (it may hold a pending call to timer_callback)
+        closure = grpc_closure_create(timer_callback, elem,
+                                      grpc_schedule_on_exec_ctx);
+      } else {
+        goto retry;
+      }
+      break;
+    case GRPC_DEADLINE_STATE_INITIAL:
+      if (gpr_atm_rel_cas(&deadline_state->timer_state,
+                          GRPC_DEADLINE_STATE_INITIAL,
+                          GRPC_DEADLINE_STATE_PENDING)) {
+        closure =
+            grpc_closure_init(&deadline_state->timer_callback, timer_callback,
+                              elem, grpc_schedule_on_exec_ctx);
+      } else {
+        goto retry;
+      }
+      break;
+  }
+  GPR_ASSERT(closure);
+  GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
+  grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, closure,
+                  gpr_now(GPR_CLOCK_MONOTONIC));
 }
 
 // Cancels the deadline timer.
-static void cancel_timer_if_needed_locked(grpc_exec_ctx* exec_ctx,
-                                          grpc_deadline_state* deadline_state) {
-  if (deadline_state->timer_pending) {
-    grpc_timer_cancel(exec_ctx, &deadline_state->timer);
-    deadline_state->timer_pending = false;
-  }
-}
 static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx,
                                    grpc_deadline_state* deadline_state) {
-  gpr_mu_lock(&deadline_state->timer_mu);
-  cancel_timer_if_needed_locked(exec_ctx, deadline_state);
-  gpr_mu_unlock(&deadline_state->timer_mu);
+  if (gpr_atm_rel_cas(&deadline_state->timer_state, GRPC_DEADLINE_STATE_PENDING,
+                      GRPC_DEADLINE_STATE_FINISHED)) {
+    grpc_timer_cancel(exec_ctx, &deadline_state->timer);
+  } else {
+    // timer was either in STATE_INITAL (nothing to cancel)
+    // OR in STATE_FINISHED (again nothing to cancel)
+  }
 }
 
 // Callback run when the call is complete.
@@ -119,8 +128,8 @@
   grpc_deadline_state* deadline_state = arg;
   cancel_timer_if_needed(exec_ctx, deadline_state);
   // Invoke the next callback.
-  deadline_state->next_on_complete->cb(
-      exec_ctx, deadline_state->next_on_complete->cb_arg, error);
+  grpc_closure_run(exec_ctx, deadline_state->next_on_complete,
+                   GRPC_ERROR_REF(error));
 }
 
 // Inject our own on_complete callback into op.
@@ -135,16 +144,13 @@
 void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
                               grpc_call_stack* call_stack) {
   grpc_deadline_state* deadline_state = elem->call_data;
-  memset(deadline_state, 0, sizeof(*deadline_state));
   deadline_state->call_stack = call_stack;
-  gpr_mu_init(&deadline_state->timer_mu);
 }
 
 void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
                                  grpc_call_element* elem) {
   grpc_deadline_state* deadline_state = elem->call_data;
   cancel_timer_if_needed(exec_ctx, deadline_state);
-  gpr_mu_destroy(&deadline_state->timer_mu);
 }
 
 // Callback and associated state for starting the timer after call stack
@@ -186,18 +192,15 @@
 void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
                                gpr_timespec new_deadline) {
   grpc_deadline_state* deadline_state = elem->call_data;
-  gpr_mu_lock(&deadline_state->timer_mu);
-  cancel_timer_if_needed_locked(exec_ctx, deadline_state);
-  start_timer_if_needed_locked(exec_ctx, elem, new_deadline);
-  gpr_mu_unlock(&deadline_state->timer_mu);
+  cancel_timer_if_needed(exec_ctx, deadline_state);
+  start_timer_if_needed(exec_ctx, elem, new_deadline);
 }
 
 void grpc_deadline_state_client_start_transport_stream_op(
     grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
     grpc_transport_stream_op* op) {
   grpc_deadline_state* deadline_state = elem->call_data;
-  if (op->cancel_error != GRPC_ERROR_NONE ||
-      op->close_error != GRPC_ERROR_NONE) {
+  if (op->cancel_error != GRPC_ERROR_NONE) {
     cancel_timer_if_needed(exec_ctx, deadline_state);
   } else {
     // Make sure we know when the call is complete, so that we can cancel
@@ -244,9 +247,7 @@
 // Constructor for call_data.  Used for both client and server filters.
 static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
                                   grpc_call_element* elem,
-                                  grpc_call_element_args* args) {
-  // Note: size of call data is different between client and server.
-  memset(elem->call_data, 0, elem->filter->sizeof_call_data);
+                                  const grpc_call_element_args* args) {
   grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
   grpc_deadline_state_start(exec_ctx, elem, args->deadline);
   return GRPC_ERROR_NONE;
@@ -285,8 +286,7 @@
                                              grpc_call_element* elem,
                                              grpc_transport_stream_op* op) {
   server_call_data* calld = elem->call_data;
-  if (op->cancel_error != GRPC_ERROR_NONE ||
-      op->close_error != GRPC_ERROR_NONE) {
+  if (op->cancel_error != GRPC_ERROR_NONE) {
     cancel_timer_if_needed(exec_ctx, &calld->base.deadline_state);
   } else {
     // If we're receiving initial metadata, we need to get the deadline
diff --git a/src/core/lib/channel/deadline_filter.h b/src/core/lib/channel/deadline_filter.h
index bd2b84f..72cd5cb 100644
--- a/src/core/lib/channel/deadline_filter.h
+++ b/src/core/lib/channel/deadline_filter.h
@@ -35,16 +35,18 @@
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/iomgr/timer.h"
 
+typedef enum grpc_deadline_timer_state {
+  GRPC_DEADLINE_STATE_INITIAL,
+  GRPC_DEADLINE_STATE_PENDING,
+  GRPC_DEADLINE_STATE_FINISHED
+} grpc_deadline_timer_state;
+
 // State used for filters that enforce call deadlines.
 // Must be the first field in the filter's call_data.
 typedef struct grpc_deadline_state {
   // We take a reference to the call stack for the timer callback.
   grpc_call_stack* call_stack;
-  // Guards access to timer_pending and timer.
-  gpr_mu timer_mu;
-  // True if the timer callback is currently pending.
-  bool timer_pending;
-  // The deadline timer.
+  gpr_atm timer_state;
   grpc_timer timer;
   grpc_closure timer_callback;
   // Closure to invoke when the call is complete.
@@ -60,6 +62,7 @@
 // elem->call_data is a grpc_deadline_state.
 //
 
+// assumes elem->call_data is zero'd
 void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
                               grpc_call_stack* call_stack);
 void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
diff --git a/src/core/lib/channel/handshaker.c b/src/core/lib/channel/handshaker.c
index c052ca5..1b4240b 100644
--- a/src/core/lib/channel/handshaker.c
+++ b/src/core/lib/channel/handshaker.c
@@ -55,8 +55,8 @@
 }
 
 void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
-                              grpc_handshaker* handshaker) {
-  handshaker->vtable->shutdown(exec_ctx, handshaker);
+                              grpc_handshaker* handshaker, grpc_error* why) {
+  handshaker->vtable->shutdown(exec_ctx, handshaker, why);
 }
 
 void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx,
@@ -92,16 +92,52 @@
   void* user_data;
   // Handshaker args.
   grpc_handshaker_args args;
+  // Links to the previous and next managers in a list of all pending handshakes
+  // Used at server side only.
+  grpc_handshake_manager* prev;
+  grpc_handshake_manager* next;
 };
 
 grpc_handshake_manager* grpc_handshake_manager_create() {
-  grpc_handshake_manager* mgr = gpr_malloc(sizeof(grpc_handshake_manager));
-  memset(mgr, 0, sizeof(*mgr));
+  grpc_handshake_manager* mgr = gpr_zalloc(sizeof(grpc_handshake_manager));
   gpr_mu_init(&mgr->mu);
   gpr_ref_init(&mgr->refs, 1);
   return mgr;
 }
 
+void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head,
+                                             grpc_handshake_manager* mgr) {
+  GPR_ASSERT(mgr->prev == NULL);
+  GPR_ASSERT(mgr->next == NULL);
+  mgr->next = *head;
+  if (*head) {
+    (*head)->prev = mgr;
+  }
+  *head = mgr;
+}
+
+void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head,
+                                                grpc_handshake_manager* mgr) {
+  if (mgr->next != NULL) {
+    mgr->next->prev = mgr->prev;
+  }
+  if (mgr->prev != NULL) {
+    mgr->prev->next = mgr->next;
+  } else {
+    GPR_ASSERT(*head == mgr);
+    *head = mgr->next;
+  }
+}
+
+void grpc_handshake_manager_pending_list_shutdown_all(
+    grpc_exec_ctx* exec_ctx, grpc_handshake_manager* head, grpc_error* why) {
+  while (head != NULL) {
+    grpc_handshake_manager_shutdown(exec_ctx, head, GRPC_ERROR_REF(why));
+    head = head->next;
+  }
+  GRPC_ERROR_UNREF(why);
+}
+
 static bool is_power_of_2(size_t n) { return (n & (n - 1)) == 0; }
 
 void grpc_handshake_manager_add(grpc_handshake_manager* mgr,
@@ -141,14 +177,17 @@
 }
 
 void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx,
-                                     grpc_handshake_manager* mgr) {
+                                     grpc_handshake_manager* mgr,
+                                     grpc_error* why) {
   gpr_mu_lock(&mgr->mu);
   // Shutdown the handshaker that's currently in progress, if any.
   if (!mgr->shutdown && mgr->index > 0) {
     mgr->shutdown = true;
-    grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[mgr->index - 1]);
+    grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[mgr->index - 1],
+                             GRPC_ERROR_REF(why));
   }
   gpr_mu_unlock(&mgr->mu);
+  GRPC_ERROR_UNREF(why);
 }
 
 // Helper function to call either the next handshaker or the
@@ -197,7 +236,8 @@
 static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
   grpc_handshake_manager* mgr = arg;
   if (error == GRPC_ERROR_NONE) {  // Timer fired, rather than being cancelled.
-    grpc_handshake_manager_shutdown(exec_ctx, mgr);
+    grpc_handshake_manager_shutdown(exec_ctx, mgr,
+                                    GRPC_ERROR_CREATE("Handshake timed out"));
   }
   grpc_handshake_manager_unref(exec_ctx, mgr);
 }
diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h
index 450b7ad..5f97c3f 100644
--- a/src/core/lib/channel/handshaker.h
+++ b/src/core/lib/channel/handshaker.h
@@ -86,7 +86,8 @@
 
   /// Shuts down the handshaker (e.g., to clean up when the operation is
   /// aborted in the middle).
-  void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker);
+  void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker,
+                   grpc_error* why);
 
   /// Performs handshaking, modifying \a args as needed (e.g., to
   /// replace \a endpoint with a wrapped endpoint).
@@ -111,7 +112,7 @@
 void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx,
                              grpc_handshaker* handshaker);
 void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
-                              grpc_handshaker* handshaker);
+                              grpc_handshaker* handshaker, grpc_error* why);
 void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx,
                                   grpc_handshaker* handshaker,
                                   grpc_tcp_server_acceptor* acceptor,
@@ -141,7 +142,8 @@
 /// The caller must still call grpc_handshake_manager_destroy() after
 /// calling this function.
 void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx,
-                                     grpc_handshake_manager* mgr);
+                                     grpc_handshake_manager* mgr,
+                                     grpc_error* why);
 
 /// Invokes handshakers in the order they were added.
 /// Takes ownership of \a endpoint, and then passes that ownership to
@@ -161,4 +163,20 @@
     gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor,
     grpc_iomgr_cb_func on_handshake_done, void* user_data);
 
+/// Add \a mgr to the server side list of all pending handshake managers, the
+/// list starts with \a *head.
+// Not thread-safe. Caller needs to synchronize.
+void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head,
+                                             grpc_handshake_manager* mgr);
+
+/// Remove \a mgr from the server side list of all pending handshake managers.
+// Not thread-safe. Caller needs to synchronize.
+void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head,
+                                                grpc_handshake_manager* mgr);
+
+/// Shutdown all pending handshake managers on the server side.
+// Not thread-safe. Caller needs to synchronize.
+void grpc_handshake_manager_pending_list_shutdown_all(
+    grpc_exec_ctx* exec_ctx, grpc_handshake_manager* head, grpc_error* why);
+
 #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index d154450..c031533 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -38,6 +38,7 @@
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/percent_encoding.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "src/core/lib/transport/transport_impl.h"
@@ -88,77 +89,104 @@
 } call_data;
 
 typedef struct channel_data {
-  grpc_mdelem *static_scheme;
-  grpc_mdelem *user_agent;
+  grpc_mdelem static_scheme;
+  grpc_mdelem user_agent;
   size_t max_payload_size_for_get;
 } channel_data;
 
-static grpc_mdelem *client_recv_filter(grpc_exec_ctx *exec_ctx, void *user_data,
-                                       grpc_mdelem *md) {
-  grpc_call_element *elem = user_data;
-  if (md == GRPC_MDELEM_STATUS_200) {
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_STATUS) {
-    char *message_string;
-    gpr_asprintf(&message_string, "Received http2 header with status: %s",
-                 grpc_mdstr_as_c_string(md->value));
-    grpc_slice message = grpc_slice_from_copied_string(message_string);
-    gpr_free(message_string);
-    grpc_call_element_send_close_with_message(exec_ctx, elem,
-                                              GRPC_STATUS_CANCELLED, &message);
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_GRPC_MESSAGE) {
-    grpc_slice pct_decoded_msg =
-        grpc_permissive_percent_decode_slice(md->value->slice);
-    if (grpc_slice_is_equivalent(pct_decoded_msg, md->value->slice)) {
-      grpc_slice_unref_internal(exec_ctx, pct_decoded_msg);
-      return md;
+static grpc_error *client_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
+                                                   grpc_call_element *elem,
+                                                   grpc_metadata_batch *b) {
+  if (b->idx.named.status != NULL) {
+    if (grpc_mdelem_eq(b->idx.named.status->md, GRPC_MDELEM_STATUS_200)) {
+      grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.status);
     } else {
-      return grpc_mdelem_from_metadata_strings(
-          exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
-          grpc_mdstr_from_slice(exec_ctx, pct_decoded_msg));
+      char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.status->md),
+                                  GPR_DUMP_ASCII);
+      char *msg;
+      gpr_asprintf(&msg, "Received http2 header with status: %s", val);
+      grpc_error *e = grpc_error_set_str(
+          grpc_error_set_int(
+              grpc_error_set_str(
+                  GRPC_ERROR_CREATE(
+                      "Received http2 :status header with non-200 OK status"),
+                  GRPC_ERROR_STR_VALUE, val),
+              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED),
+          GRPC_ERROR_STR_GRPC_MESSAGE, msg);
+      gpr_free(val);
+      gpr_free(msg);
+      return e;
     }
-  } else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
-    const char *value_str = grpc_mdstr_as_c_string(md->value);
-    if (strncmp(value_str, EXPECTED_CONTENT_TYPE,
-                EXPECTED_CONTENT_TYPE_LENGTH) == 0 &&
-        (value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
-         value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) {
-      /* Although the C implementation doesn't (currently) generate them,
-         any custom +-suffix is explicitly valid. */
-      /* TODO(klempner): We should consider preallocating common values such
-         as +proto or +json, or at least stashing them if we see them. */
-      /* TODO(klempner): Should we be surfacing this to application code? */
-    } else {
-      /* TODO(klempner): We're currently allowing this, but we shouldn't
-         see it without a proxy so log for now. */
-      gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str);
-    }
-    return NULL;
   }
-  return md;
+
+  if (b->idx.named.grpc_message != NULL) {
+    grpc_slice pct_decoded_msg = grpc_permissive_percent_decode_slice(
+        GRPC_MDVALUE(b->idx.named.grpc_message->md));
+    if (grpc_slice_is_equivalent(pct_decoded_msg,
+                                 GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
+      grpc_slice_unref_internal(exec_ctx, pct_decoded_msg);
+    } else {
+      grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message,
+                                    pct_decoded_msg);
+    }
+  }
+
+  if (b->idx.named.content_type != NULL) {
+    if (!grpc_mdelem_eq(b->idx.named.content_type->md,
+                        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
+      if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md),
+                                  EXPECTED_CONTENT_TYPE,
+                                  EXPECTED_CONTENT_TYPE_LENGTH) &&
+          (GRPC_SLICE_START_PTR(GRPC_MDVALUE(
+               b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
+               '+' ||
+           GRPC_SLICE_START_PTR(GRPC_MDVALUE(
+               b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
+               ';')) {
+        /* Although the C implementation doesn't (currently) generate them,
+           any custom +-suffix is explicitly valid. */
+        /* TODO(klempner): We should consider preallocating common values such
+           as +proto or +json, or at least stashing them if we see them. */
+        /* TODO(klempner): Should we be surfacing this to application code? */
+      } else {
+        /* TODO(klempner): We're currently allowing this, but we shouldn't
+           see it without a proxy so log for now. */
+        char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md),
+                                    GPR_DUMP_ASCII);
+        gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
+        gpr_free(val);
+      }
+    }
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type);
+  }
+
+  return GRPC_ERROR_NONE;
 }
 
 static void hc_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx,
                                         void *user_data, grpc_error *error) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
-  grpc_metadata_batch_filter(exec_ctx, calld->recv_initial_metadata,
-                             client_recv_filter, elem);
-  grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata,
-                   GRPC_ERROR_REF(error));
+  if (error == GRPC_ERROR_NONE) {
+    error = client_filter_incoming_metadata(exec_ctx, elem,
+                                            calld->recv_initial_metadata);
+  } else {
+    GRPC_ERROR_REF(error);
+  }
+  grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata, error);
 }
 
 static void hc_on_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
                                          void *user_data, grpc_error *error) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
-  grpc_metadata_batch_filter(exec_ctx, calld->recv_trailing_metadata,
-                             client_recv_filter, elem);
-  grpc_closure_run(exec_ctx, calld->on_done_recv_trailing_metadata,
-                   GRPC_ERROR_REF(error));
+  if (error == GRPC_ERROR_NONE) {
+    error = client_filter_incoming_metadata(exec_ctx, elem,
+                                            calld->recv_trailing_metadata);
+  } else {
+    GRPC_ERROR_REF(error);
+  }
+  grpc_closure_run(exec_ctx, calld->on_done_recv_trailing_metadata, error);
 }
 
 static void hc_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -179,15 +207,12 @@
   calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error);
 }
 
-static grpc_mdelem *client_strip_filter(grpc_exec_ctx *exec_ctx,
-                                        void *user_data, grpc_mdelem *md) {
-  /* eat the things we'd like to set ourselves */
-  if (md->key == GRPC_MDSTR_METHOD) return NULL;
-  if (md->key == GRPC_MDSTR_SCHEME) return NULL;
-  if (md->key == GRPC_MDSTR_TE) return NULL;
-  if (md->key == GRPC_MDSTR_CONTENT_TYPE) return NULL;
-  if (md->key == GRPC_MDSTR_USER_AGENT) return NULL;
-  return md;
+static void remove_if_present(grpc_exec_ctx *exec_ctx,
+                              grpc_metadata_batch *batch,
+                              grpc_metadata_batch_callouts_index idx) {
+  if (batch->idx.array[idx] != NULL) {
+    grpc_metadata_batch_remove(exec_ctx, batch, batch->idx.array[idx]);
+  }
 }
 
 static void continue_send_message(grpc_exec_ctx *exec_ctx,
@@ -226,18 +251,20 @@
   }
 }
 
-static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                         grpc_transport_stream_op *op) {
+static grpc_error *hc_mutate_op(grpc_exec_ctx *exec_ctx,
+                                grpc_call_element *elem,
+                                grpc_transport_stream_op *op) {
   /* grab pointers to our data from the call element */
   call_data *calld = elem->call_data;
   channel_data *channeld = elem->channel_data;
+  grpc_error *error;
 
   if (op->send_initial_metadata != NULL) {
     /* Decide which HTTP VERB to use. We use GET if the request is marked
     cacheable, and the operation contains both initial metadata and send
     message, and the payload is below the size threshold, and all the data
     for this request is immediately available. */
-    grpc_mdelem *method = GRPC_MDELEM_METHOD_POST;
+    grpc_mdelem method = GRPC_MDELEM_METHOD_POST;
     if ((op->send_initial_metadata_flags &
          GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) &&
         op->send_message != NULL &&
@@ -254,7 +281,7 @@
     }
 
     /* Attempt to read the data from send_message and create a header field. */
-    if (method == GRPC_MDELEM_METHOD_GET) {
+    if (grpc_mdelem_eq(method, GRPC_MDELEM_METHOD_GET)) {
       /* allocate memory to hold the entire payload */
       calld->payload_bytes = gpr_malloc(op->send_message->length);
 
@@ -267,12 +294,14 @@
       if (calld->send_message_blocked == false) {
         /* when all the send_message data is available, then create a MDELEM and
         append to headers */
-        grpc_mdelem *payload_bin = grpc_mdelem_from_metadata_strings(
+        grpc_mdelem payload_bin = grpc_mdelem_from_slices(
             exec_ctx, GRPC_MDSTR_GRPC_PAYLOAD_BIN,
-            grpc_mdstr_from_buffer(calld->payload_bytes,
-                                   op->send_message->length));
-        grpc_metadata_batch_add_tail(op->send_initial_metadata,
-                                     &calld->payload_bin, payload_bin);
+            grpc_slice_from_copied_buffer((const char *)calld->payload_bytes,
+                                          op->send_message->length));
+        error =
+            grpc_metadata_batch_add_tail(exec_ctx, op->send_initial_metadata,
+                                         &calld->payload_bin, payload_bin);
+        if (error != GRPC_ERROR_NONE) return error;
         calld->on_complete = op->on_complete;
         op->on_complete = &calld->hc_on_complete;
         op->send_message = NULL;
@@ -285,21 +314,35 @@
       }
     }
 
-    grpc_metadata_batch_filter(exec_ctx, op->send_initial_metadata,
-                               client_strip_filter, elem);
+    remove_if_present(exec_ctx, op->send_initial_metadata, GRPC_BATCH_METHOD);
+    remove_if_present(exec_ctx, op->send_initial_metadata, GRPC_BATCH_SCHEME);
+    remove_if_present(exec_ctx, op->send_initial_metadata, GRPC_BATCH_TE);
+    remove_if_present(exec_ctx, op->send_initial_metadata,
+                      GRPC_BATCH_CONTENT_TYPE);
+    remove_if_present(exec_ctx, op->send_initial_metadata,
+                      GRPC_BATCH_USER_AGENT);
+
     /* Send : prefixed headers, which have to be before any application
        layer headers. */
-    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method,
-                                 method);
-    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme,
-                                 channeld->static_scheme);
-    grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers,
-                                 GRPC_MDELEM_TE_TRAILERS);
-    grpc_metadata_batch_add_tail(
-        op->send_initial_metadata, &calld->content_type,
+    error = grpc_metadata_batch_add_head(exec_ctx, op->send_initial_metadata,
+                                         &calld->method, method);
+    if (error != GRPC_ERROR_NONE) return error;
+    error =
+        grpc_metadata_batch_add_head(exec_ctx, op->send_initial_metadata,
+                                     &calld->scheme, channeld->static_scheme);
+    if (error != GRPC_ERROR_NONE) return error;
+    error = grpc_metadata_batch_add_tail(exec_ctx, op->send_initial_metadata,
+                                         &calld->te_trailers,
+                                         GRPC_MDELEM_TE_TRAILERS);
+    if (error != GRPC_ERROR_NONE) return error;
+    error = grpc_metadata_batch_add_tail(
+        exec_ctx, op->send_initial_metadata, &calld->content_type,
         GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
-    grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent,
-                                 GRPC_MDELEM_REF(channeld->user_agent));
+    if (error != GRPC_ERROR_NONE) return error;
+    error = grpc_metadata_batch_add_tail(exec_ctx, op->send_initial_metadata,
+                                         &calld->user_agent,
+                                         GRPC_MDELEM_REF(channeld->user_agent));
+    if (error != GRPC_ERROR_NONE) return error;
   }
 
   if (op->recv_initial_metadata != NULL) {
@@ -315,6 +358,8 @@
     calld->on_done_recv_trailing_metadata = op->on_complete;
     op->on_complete = &calld->hc_on_recv_trailing_metadata;
   }
+
+  return GRPC_ERROR_NONE;
 }
 
 static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
@@ -322,21 +367,26 @@
                                   grpc_transport_stream_op *op) {
   GPR_TIMER_BEGIN("hc_start_transport_op", 0);
   GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
-  hc_mutate_op(exec_ctx, elem, op);
-  GPR_TIMER_END("hc_start_transport_op", 0);
-  call_data *calld = elem->call_data;
-  if (op->send_message != NULL && calld->send_message_blocked) {
-    /* Don't forward the op. send_message contains slices that aren't ready
-    yet. The call will be forwarded by the op_complete of slice read call. */
+  grpc_error *error = hc_mutate_op(exec_ctx, elem, op);
+  if (error != GRPC_ERROR_NONE) {
+    grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
   } else {
-    grpc_call_next_op(exec_ctx, elem, op);
+    call_data *calld = elem->call_data;
+    if (op->send_message != NULL && calld->send_message_blocked) {
+      /* Don't forward the op. send_message contains slices that aren't ready
+      yet. The call will be forwarded by the op_complete of slice read call.
+      */
+    } else {
+      grpc_call_next_op(exec_ctx, elem, op);
+    }
   }
+  GPR_TIMER_END("hc_start_transport_op", 0);
 }
 
 /* Constructor for call_data */
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   calld->on_done_recv_initial_metadata = NULL;
   calld->on_done_recv_trailing_metadata = NULL;
@@ -367,18 +417,18 @@
   grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices);
 }
 
-static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) {
+static grpc_mdelem scheme_from_args(const grpc_channel_args *args) {
   unsigned i;
   size_t j;
-  grpc_mdelem *valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP,
-                                  GRPC_MDELEM_SCHEME_HTTPS};
+  grpc_mdelem valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP,
+                                 GRPC_MDELEM_SCHEME_HTTPS};
   if (args != NULL) {
     for (i = 0; i < args->num_args; ++i) {
       if (args->args[i].type == GRPC_ARG_STRING &&
           strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) {
         for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) {
-          if (0 == strcmp(grpc_mdstr_as_c_string(valid_schemes[j]->value),
-                          args->args[i].value.string)) {
+          if (0 == grpc_slice_str_cmp(GRPC_MDVALUE(valid_schemes[j]),
+                                      args->args[i].value.string)) {
             return valid_schemes[j];
           }
         }
@@ -404,13 +454,13 @@
   return kMaxPayloadSizeForGet;
 }
 
-static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args,
-                                        const char *transport_name) {
+static grpc_slice user_agent_from_args(const grpc_channel_args *args,
+                                       const char *transport_name) {
   gpr_strvec v;
   size_t i;
   int is_first = 1;
   char *tmp;
-  grpc_mdstr *result;
+  grpc_slice result;
 
   gpr_strvec_init(&v);
 
@@ -448,7 +498,7 @@
 
   tmp = gpr_strvec_flatten(&v, NULL);
   gpr_strvec_destroy(&v);
-  result = grpc_mdstr_from_string(tmp);
+  result = grpc_slice_intern(grpc_slice_from_static_string(tmp));
   gpr_free(tmp);
 
   return result;
@@ -464,7 +514,7 @@
   chand->static_scheme = scheme_from_args(args->channel_args);
   chand->max_payload_size_for_get =
       max_payload_size_from_args(args->channel_args);
-  chand->user_agent = grpc_mdelem_from_metadata_strings(
+  chand->user_agent = grpc_mdelem_from_slices(
       exec_ctx, GRPC_MDSTR_USER_AGENT,
       user_agent_from_args(args->channel_args,
                            args->optional_transport->vtable->name));
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index f508231..fb70de8 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -39,6 +39,7 @@
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/percent_encoding.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/transport/static_metadata.h"
 
 #define EXPECTED_CONTENT_TYPE "application/grpc"
@@ -47,18 +48,13 @@
 extern int grpc_http_trace;
 
 typedef struct call_data {
-  uint8_t seen_path;
-  uint8_t seen_method;
-  uint8_t sent_status;
-  uint8_t seen_scheme;
-  uint8_t seen_te_trailers;
-  uint8_t seen_authority;
-  uint8_t seen_payload_bin;
   grpc_linked_mdelem status;
   grpc_linked_mdelem content_type;
 
+  /* did this request come with payload-bin */
+  bool seen_payload_bin;
   /* flag to ensure payload_bin is delivered only once */
-  uint8_t payload_bin_delivered;
+  bool payload_bin_delivered;
 
   grpc_metadata_batch *recv_initial_metadata;
   bool *recv_idempotent_request;
@@ -83,109 +79,155 @@
 
 typedef struct channel_data { uint8_t unused; } channel_data;
 
-static grpc_mdelem *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx,
-                                                    void *user_data,
-                                                    grpc_mdelem *md) {
-  if (md->key == GRPC_MDSTR_GRPC_MESSAGE) {
+static grpc_error *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx,
+                                                   grpc_call_element *elem,
+                                                   grpc_metadata_batch *b) {
+  if (b->idx.named.grpc_message != NULL) {
     grpc_slice pct_encoded_msg = grpc_percent_encode_slice(
-        md->value->slice, grpc_compatible_percent_encoding_unreserved_bytes);
-    if (grpc_slice_is_equivalent(pct_encoded_msg, md->value->slice)) {
+        GRPC_MDVALUE(b->idx.named.grpc_message->md),
+        grpc_compatible_percent_encoding_unreserved_bytes);
+    if (grpc_slice_is_equivalent(pct_encoded_msg,
+                                 GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
       grpc_slice_unref_internal(exec_ctx, pct_encoded_msg);
-      return md;
     } else {
-      return grpc_mdelem_from_metadata_strings(
-          exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
-          grpc_mdstr_from_slice(exec_ctx, pct_encoded_msg));
+      grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message,
+                                    pct_encoded_msg);
     }
-  } else {
-    return md;
   }
+  return GRPC_ERROR_NONE;
 }
 
-static grpc_mdelem *server_filter(grpc_exec_ctx *exec_ctx, void *user_data,
-                                  grpc_mdelem *md) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
+static void add_error(const char *error_name, grpc_error **cumulative,
+                      grpc_error *new) {
+  if (new == GRPC_ERROR_NONE) return;
+  if (*cumulative == GRPC_ERROR_NONE) {
+    *cumulative = GRPC_ERROR_CREATE(error_name);
+  }
+  *cumulative = grpc_error_add_child(*cumulative, new);
+}
 
-  /* Check if it is one of the headers we care about. */
-  if (md == GRPC_MDELEM_TE_TRAILERS || md == GRPC_MDELEM_METHOD_POST ||
-      md == GRPC_MDELEM_METHOD_PUT || md == GRPC_MDELEM_METHOD_GET ||
-      md == GRPC_MDELEM_SCHEME_HTTP || md == GRPC_MDELEM_SCHEME_HTTPS ||
-      md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
-    /* swallow it */
-    if (md == GRPC_MDELEM_METHOD_POST) {
-      calld->seen_method = 1;
+static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
+                                                   grpc_call_element *elem,
+                                                   grpc_metadata_batch *b) {
+  call_data *calld = elem->call_data;
+  grpc_error *error = GRPC_ERROR_NONE;
+  static const char *error_name = "Failed processing incoming headers";
+
+  if (b->idx.named.method != NULL) {
+    if (grpc_mdelem_eq(b->idx.named.method->md, GRPC_MDELEM_METHOD_POST)) {
       *calld->recv_idempotent_request = false;
       *calld->recv_cacheable_request = false;
-    } else if (md == GRPC_MDELEM_METHOD_PUT) {
-      calld->seen_method = 1;
+    } else if (grpc_mdelem_eq(b->idx.named.method->md,
+                              GRPC_MDELEM_METHOD_PUT)) {
       *calld->recv_idempotent_request = true;
-    } else if (md == GRPC_MDELEM_METHOD_GET) {
-      calld->seen_method = 1;
+    } else if (grpc_mdelem_eq(b->idx.named.method->md,
+                              GRPC_MDELEM_METHOD_GET)) {
       *calld->recv_cacheable_request = true;
-    } else if (md->key == GRPC_MDSTR_SCHEME) {
-      calld->seen_scheme = 1;
-    } else if (md == GRPC_MDELEM_TE_TRAILERS) {
-      calld->seen_te_trailers = 1;
-    }
-    /* TODO(klempner): Track that we've seen all the headers we should
-       require */
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
-    const char *value_str = grpc_mdstr_as_c_string(md->value);
-    if (strncmp(value_str, EXPECTED_CONTENT_TYPE,
-                EXPECTED_CONTENT_TYPE_LENGTH) == 0 &&
-        (value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
-         value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) {
-      /* Although the C implementation doesn't (currently) generate them,
-         any custom +-suffix is explicitly valid. */
-      /* TODO(klempner): We should consider preallocating common values such
-         as +proto or +json, or at least stashing them if we see them. */
-      /* TODO(klempner): Should we be surfacing this to application code? */
     } else {
-      /* TODO(klempner): We're currently allowing this, but we shouldn't
-         see it without a proxy so log for now. */
-      gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str);
+      add_error(error_name, &error,
+                grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
+                                        b->idx.named.method->md));
     }
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD ||
-             md->key == GRPC_MDSTR_SCHEME) {
-    gpr_log(GPR_ERROR, "Invalid %s: header: '%s'",
-            grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value));
-    /* swallow it and error everything out. */
-    /* TODO(klempner): We ought to generate more descriptive error messages
-       on the wire here. */
-    grpc_call_element_send_cancel(exec_ctx, elem);
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_PATH) {
-    if (calld->seen_path) {
-      gpr_log(GPR_ERROR, "Received :path twice");
-      return NULL;
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.method);
+  } else {
+    add_error(error_name, &error,
+              grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
+                                 GRPC_ERROR_STR_KEY, ":method"));
+  }
+
+  if (b->idx.named.te != NULL) {
+    if (!grpc_mdelem_eq(b->idx.named.te->md, GRPC_MDELEM_TE_TRAILERS)) {
+      add_error(error_name, &error,
+                grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
+                                        b->idx.named.te->md));
     }
-    calld->seen_path = 1;
-    return md;
-  } else if (md->key == GRPC_MDSTR_AUTHORITY) {
-    calld->seen_authority = 1;
-    return md;
-  } else if (md->key == GRPC_MDSTR_HOST) {
-    /* translate host to :authority since :authority may be
-       omitted */
-    grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
-        exec_ctx, GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value));
-    calld->seen_authority = 1;
-    return authority;
-  } else if (md->key == GRPC_MDSTR_GRPC_PAYLOAD_BIN) {
-    /* Retrieve the payload from the value of the 'grpc-internal-payload-bin'
-       header field */
-    calld->seen_payload_bin = 1;
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.te);
+  } else {
+    add_error(error_name, &error,
+              grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
+                                 GRPC_ERROR_STR_KEY, "te"));
+  }
+
+  if (b->idx.named.scheme != NULL) {
+    if (!grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTP) &&
+        !grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTPS) &&
+        !grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_GRPC)) {
+      add_error(error_name, &error,
+                grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
+                                        b->idx.named.scheme->md));
+    }
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.scheme);
+  } else {
+    add_error(error_name, &error,
+              grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
+                                 GRPC_ERROR_STR_KEY, ":scheme"));
+  }
+
+  if (b->idx.named.content_type != NULL) {
+    if (!grpc_mdelem_eq(b->idx.named.content_type->md,
+                        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
+      if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md),
+                                  EXPECTED_CONTENT_TYPE,
+                                  EXPECTED_CONTENT_TYPE_LENGTH) &&
+          (GRPC_SLICE_START_PTR(GRPC_MDVALUE(
+               b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
+               '+' ||
+           GRPC_SLICE_START_PTR(GRPC_MDVALUE(
+               b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
+               ';')) {
+        /* Although the C implementation doesn't (currently) generate them,
+           any custom +-suffix is explicitly valid. */
+        /* TODO(klempner): We should consider preallocating common values such
+           as +proto or +json, or at least stashing them if we see them. */
+        /* TODO(klempner): Should we be surfacing this to application code? */
+      } else {
+        /* TODO(klempner): We're currently allowing this, but we shouldn't
+           see it without a proxy so log for now. */
+        char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md),
+                                    GPR_DUMP_ASCII);
+        gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
+        gpr_free(val);
+      }
+    }
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type);
+  }
+
+  if (b->idx.named.path == NULL) {
+    add_error(error_name, &error,
+              grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
+                                 GRPC_ERROR_STR_KEY, ":path"));
+  }
+
+  if (b->idx.named.host != NULL && b->idx.named.authority == NULL) {
+    grpc_linked_mdelem *el = b->idx.named.host;
+    grpc_mdelem md = GRPC_MDELEM_REF(el->md);
+    grpc_metadata_batch_remove(exec_ctx, b, el);
+    add_error(
+        error_name, &error,
+        grpc_metadata_batch_add_head(
+            exec_ctx, b, el, grpc_mdelem_from_slices(
+                                 exec_ctx, GRPC_MDSTR_AUTHORITY,
+                                 grpc_slice_ref_internal(GRPC_MDVALUE(md)))));
+    GRPC_MDELEM_UNREF(exec_ctx, md);
+  }
+
+  if (b->idx.named.authority == NULL) {
+    add_error(error_name, &error,
+              grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
+                                 GRPC_ERROR_STR_KEY, ":authority"));
+  }
+
+  if (b->idx.named.grpc_payload_bin != NULL) {
+    calld->seen_payload_bin = true;
     grpc_slice_buffer_add(&calld->read_slice_buffer,
-                          grpc_slice_ref_internal(md->value->slice));
+                          grpc_slice_ref_internal(
+                              GRPC_MDVALUE(b->idx.named.grpc_payload_bin->md)));
     grpc_slice_buffer_stream_init(&calld->read_stream,
                                   &calld->read_slice_buffer, 0);
-    return NULL;
-  } else {
-    return md;
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_payload_bin);
   }
+
+  return error;
 }
 
 static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -193,49 +235,12 @@
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
   if (err == GRPC_ERROR_NONE) {
-    grpc_metadata_batch_filter(exec_ctx, calld->recv_initial_metadata,
-                               server_filter, elem);
-    /* Have we seen the required http2 transport headers?
-       (:method, :scheme, content-type, with :path and :authority covered
-       at the channel level right now) */
-    if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers &&
-        calld->seen_path && calld->seen_authority) {
-      /* do nothing */
-    } else {
-      err = GRPC_ERROR_CREATE("Bad incoming HTTP headers");
-      if (!calld->seen_path) {
-        err = grpc_error_add_child(err,
-                                   GRPC_ERROR_CREATE("Missing :path header"));
-      }
-      if (!calld->seen_authority) {
-        err = grpc_error_add_child(
-            err, GRPC_ERROR_CREATE("Missing :authority header"));
-      }
-      if (!calld->seen_method) {
-        err = grpc_error_add_child(err,
-                                   GRPC_ERROR_CREATE("Missing :method header"));
-      }
-      if (!calld->seen_scheme) {
-        err = grpc_error_add_child(err,
-                                   GRPC_ERROR_CREATE("Missing :scheme header"));
-      }
-      if (!calld->seen_te_trailers) {
-        err = grpc_error_add_child(
-            err, GRPC_ERROR_CREATE("Missing te: trailers header"));
-      }
-      /* Error this call out */
-      if (grpc_http_trace) {
-        const char *error_str = grpc_error_string(err);
-        gpr_log(GPR_ERROR, "Invalid http2 headers: %s", error_str);
-        grpc_error_free_string(error_str);
-      }
-      grpc_call_element_send_cancel(exec_ctx, elem);
-    }
+    err = server_filter_incoming_metadata(exec_ctx, elem,
+                                          calld->recv_initial_metadata);
   } else {
     GRPC_ERROR_REF(err);
   }
-  calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, err);
-  GRPC_ERROR_UNREF(err);
+  grpc_closure_run(exec_ctx, calld->on_done_recv, err);
 }
 
 static void hs_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -247,12 +252,11 @@
     *calld->pp_recv_message = calld->payload_bin_delivered
                                   ? NULL
                                   : (grpc_byte_stream *)&calld->read_stream;
-    calld->recv_message_ready->cb(exec_ctx, calld->recv_message_ready->cb_arg,
-                                  err);
+    grpc_closure_run(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err));
     calld->recv_message_ready = NULL;
     calld->payload_bin_delivered = true;
   }
-  calld->on_complete->cb(exec_ctx, calld->on_complete->cb_arg, err);
+  grpc_closure_run(exec_ctx, calld->on_complete, GRPC_ERROR_REF(err));
 }
 
 static void hs_recv_message_ready(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -263,8 +267,7 @@
     /* do nothing. This is probably a GET request, and payload will be returned
     in hs_on_complete callback. */
   } else {
-    calld->recv_message_ready->cb(exec_ctx, calld->recv_message_ready->cb_arg,
-                                  err);
+    grpc_closure_run(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err));
   }
 }
 
@@ -273,13 +276,23 @@
   /* grab pointers to our data from the call element */
   call_data *calld = elem->call_data;
 
-  if (op->send_initial_metadata != NULL && !calld->sent_status) {
-    calld->sent_status = 1;
-    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->status,
-                                 GRPC_MDELEM_STATUS_200);
-    grpc_metadata_batch_add_tail(
-        op->send_initial_metadata, &calld->content_type,
-        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
+  if (op->send_initial_metadata != NULL) {
+    grpc_error *error = GRPC_ERROR_NONE;
+    static const char *error_name = "Failed sending initial metadata";
+    add_error(error_name, &error, grpc_metadata_batch_add_head(
+                                      exec_ctx, op->send_initial_metadata,
+                                      &calld->status, GRPC_MDELEM_STATUS_200));
+    add_error(error_name, &error,
+              grpc_metadata_batch_add_tail(
+                  exec_ctx, op->send_initial_metadata, &calld->content_type,
+                  GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC));
+    add_error(error_name, &error,
+              server_filter_outgoing_metadata(exec_ctx, elem,
+                                              op->send_initial_metadata));
+    if (error != GRPC_ERROR_NONE) {
+      grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
+      return;
+    }
   }
 
   if (op->recv_initial_metadata) {
@@ -306,8 +319,12 @@
   }
 
   if (op->send_trailing_metadata) {
-    grpc_metadata_batch_filter(exec_ctx, op->send_trailing_metadata,
-                               server_filter_outgoing_metadata, elem);
+    grpc_error *error = server_filter_outgoing_metadata(
+        exec_ctx, elem, op->send_trailing_metadata);
+    if (error != GRPC_ERROR_NONE) {
+      grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
+      return;
+    }
   }
 }
 
@@ -324,11 +341,10 @@
 /* Constructor for call_data */
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   /* grab pointers to our data from the call element */
   call_data *calld = elem->call_data;
   /* initialize members */
-  memset(calld, 0, sizeof(*calld));
   grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem,
                     grpc_schedule_on_exec_ctx);
   grpc_closure_init(&calld->hs_on_complete, hs_on_complete, elem,
diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c
index 862090b..b424c0d 100644
--- a/src/core/lib/channel/message_size_filter.c
+++ b/src/core/lib/channel/message_size_filter.c
@@ -58,7 +58,7 @@
   gpr_free(value);
 }
 
-static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = {
+static const grpc_slice_hash_table_vtable message_size_limits_vtable = {
     message_size_limits_free, message_size_limits_copy};
 
 static void* message_size_limits_create_from_json(const grpc_json* json) {
@@ -68,12 +68,16 @@
     if (field->key == NULL) continue;
     if (strcmp(field->key, "maxRequestMessageBytes") == 0) {
       if (max_request_message_bytes >= 0) return NULL;  // Duplicate.
-      if (field->type != GRPC_JSON_STRING) return NULL;
+      if (field->type != GRPC_JSON_STRING && field->type != GRPC_JSON_NUMBER) {
+        return NULL;
+      }
       max_request_message_bytes = gpr_parse_nonnegative_int(field->value);
       if (max_request_message_bytes == -1) return NULL;
     } else if (strcmp(field->key, "maxResponseMessageBytes") == 0) {
       if (max_response_message_bytes >= 0) return NULL;  // Duplicate.
-      if (field->type != GRPC_JSON_STRING) return NULL;
+      if (field->type != GRPC_JSON_STRING && field->type != GRPC_JSON_NUMBER) {
+        return NULL;
+      }
       max_response_message_bytes = gpr_parse_nonnegative_int(field->value);
       if (max_response_message_bytes == -1) return NULL;
     }
@@ -101,7 +105,7 @@
   int max_send_size;
   int max_recv_size;
   // Maps path names to message_size_limits structs.
-  grpc_mdstr_hash_table* method_limit_table;
+  grpc_slice_hash_table* method_limit_table;
 } channel_data;
 
 // Callback invoked when we receive a message.  Here we check the max
@@ -142,10 +146,12 @@
     char* message_string;
     gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %d)",
                  op->send_message->length, calld->max_send_size);
-    grpc_slice message = grpc_slice_from_copied_string(message_string);
+    grpc_transport_stream_op_finish_with_failure(
+        exec_ctx, op, grpc_error_set_int(GRPC_ERROR_CREATE(message_string),
+                                         GRPC_ERROR_INT_GRPC_STATUS,
+                                         GRPC_STATUS_INVALID_ARGUMENT));
     gpr_free(message_string);
-    grpc_call_element_send_close_with_message(
-        exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message);
+    return;
   }
   // Inject callback for receiving a message.
   if (op->recv_message_ready != NULL) {
@@ -160,7 +166,7 @@
 // Constructor for call_data.
 static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
                                   grpc_call_element* elem,
-                                  grpc_call_element_args* args) {
+                                  const grpc_call_element_args* args) {
   channel_data* chand = elem->channel_data;
   call_data* calld = elem->call_data;
   calld->next_recv_message_ready = NULL;
@@ -202,7 +208,6 @@
                                      grpc_channel_element_args* args) {
   GPR_ASSERT(!args->is_last);
   channel_data* chand = elem->channel_data;
-  memset(chand, 0, sizeof(*chand));
   chand->max_send_size = GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH;
   chand->max_recv_size = GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH;
   for (size_t i = 0; i < args->channel_args->num_args; ++i) {
@@ -243,7 +248,7 @@
 static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
                                  grpc_channel_element* elem) {
   channel_data* chand = elem->channel_data;
-  grpc_mdstr_hash_table_unref(exec_ctx, chand->method_limit_table);
+  grpc_slice_hash_table_unref(exec_ctx, chand->method_limit_table);
 }
 
 const grpc_channel_filter grpc_message_size_filter = {
diff --git a/src/core/lib/compression/algorithm_metadata.h b/src/core/lib/compression/algorithm_metadata.h
index 1f9cc15..58dfe62 100644
--- a/src/core/lib/compression/algorithm_metadata.h
+++ b/src/core/lib/compression/algorithm_metadata.h
@@ -38,16 +38,16 @@
 #include "src/core/lib/transport/metadata.h"
 
 /** Return compression algorithm based metadata value */
-grpc_mdstr *grpc_compression_algorithm_mdstr(
+grpc_slice grpc_compression_algorithm_slice(
     grpc_compression_algorithm algorithm);
 
 /** Return compression algorithm based metadata element (grpc-encoding: xxx) */
-grpc_mdelem *grpc_compression_encoding_mdelem(
+grpc_mdelem grpc_compression_encoding_mdelem(
     grpc_compression_algorithm algorithm);
 
 /** Find compression algorithm based on passed in mdstr - returns
  * GRPC_COMPRESS_ALGORITHM_COUNT on failure */
-grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
-    grpc_mdstr *str);
+grpc_compression_algorithm grpc_compression_algorithm_from_slice(
+    grpc_slice str);
 
 #endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */
diff --git a/src/core/lib/compression/compression.c b/src/core/lib/compression/compression.c
index 54efb5e..ce4f597 100644
--- a/src/core/lib/compression/compression.c
+++ b/src/core/lib/compression/compression.c
@@ -41,30 +41,24 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/transport/static_metadata.h"
 
-int grpc_compression_algorithm_parse(const char *name, size_t name_length,
+int grpc_compression_algorithm_parse(grpc_slice name,
                                      grpc_compression_algorithm *algorithm) {
   /* we use strncmp not only because it's safer (even though in this case it
    * doesn't matter, given that we are comparing against string literals, but
    * because this way we needn't have "name" nil-terminated (useful for slice
    * data, for example) */
-  GRPC_API_TRACE(
-      "grpc_compression_algorithm_parse("
-      "name=%*.*s, name_length=%lu, algorithm=%p)",
-      5, ((int)name_length, (int)name_length, name, (unsigned long)name_length,
-          algorithm));
-  if (name_length == 0) {
-    return 0;
-  }
-  if (strncmp(name, "identity", name_length) == 0) {
+  if (grpc_slice_eq(name, GRPC_MDSTR_IDENTITY)) {
     *algorithm = GRPC_COMPRESS_NONE;
-  } else if (strncmp(name, "gzip", name_length) == 0) {
+    return 1;
+  } else if (grpc_slice_eq(name, GRPC_MDSTR_GZIP)) {
     *algorithm = GRPC_COMPRESS_GZIP;
-  } else if (strncmp(name, "deflate", name_length) == 0) {
+    return 1;
+  } else if (grpc_slice_eq(name, GRPC_MDSTR_DEFLATE)) {
     *algorithm = GRPC_COMPRESS_DEFLATE;
+    return 1;
   } else {
     return 0;
   }
-  return 1;
 }
 
 int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
@@ -87,15 +81,15 @@
   return 0;
 }
 
-grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
-    grpc_mdstr *str) {
-  if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE;
-  if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE;
-  if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP;
+grpc_compression_algorithm grpc_compression_algorithm_from_slice(
+    grpc_slice str) {
+  if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_COMPRESS_NONE;
+  if (grpc_slice_eq(str, GRPC_MDSTR_DEFLATE)) return GRPC_COMPRESS_DEFLATE;
+  if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_COMPRESS_GZIP;
   return GRPC_COMPRESS_ALGORITHMS_COUNT;
 }
 
-grpc_mdstr *grpc_compression_algorithm_mdstr(
+grpc_slice grpc_compression_algorithm_slice(
     grpc_compression_algorithm algorithm) {
   switch (algorithm) {
     case GRPC_COMPRESS_NONE:
@@ -105,12 +99,12 @@
     case GRPC_COMPRESS_GZIP:
       return GRPC_MDSTR_GZIP;
     case GRPC_COMPRESS_ALGORITHMS_COUNT:
-      return NULL;
+      return grpc_empty_slice();
   }
-  return NULL;
+  return grpc_empty_slice();
 }
 
-grpc_mdelem *grpc_compression_encoding_mdelem(
+grpc_mdelem grpc_compression_encoding_mdelem(
     grpc_compression_algorithm algorithm) {
   switch (algorithm) {
     case GRPC_COMPRESS_NONE:
@@ -122,7 +116,7 @@
     default:
       break;
   }
-  return NULL;
+  return GRPC_MDNULL;
 }
 
 void grpc_compression_options_init(grpc_compression_options *opts) {
diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c
index fb21089..6d7aa43 100644
--- a/src/core/lib/http/httpcli.c
+++ b/src/core/lib/http/httpcli.c
@@ -93,8 +93,9 @@
   context->pollset_set = grpc_pollset_set_create();
 }
 
-void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
-  grpc_pollset_set_destroy(context->pollset_set);
+void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx,
+                                  grpc_httpcli_context *context) {
+  grpc_pollset_set_destroy(exec_ctx, context->pollset_set);
 }
 
 static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
diff --git a/src/core/lib/http/httpcli.h b/src/core/lib/http/httpcli.h
index 11e03b4..8ae03ee 100644
--- a/src/core/lib/http/httpcli.h
+++ b/src/core/lib/http/httpcli.h
@@ -83,7 +83,8 @@
 typedef struct grpc_http_response grpc_httpcli_response;
 
 void grpc_httpcli_context_init(grpc_httpcli_context *context);
-void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
+void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx,
+                                  grpc_httpcli_context *context);
 
 /* Asynchronously perform a HTTP GET.
    'context' specifies the http context under which to do the get
diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c
index 440817c..354d2f4 100644
--- a/src/core/lib/http/httpcli_security_connector.c
+++ b/src/core/lib/http/httpcli_security_connector.c
@@ -118,8 +118,7 @@
     return GRPC_SECURITY_ERROR;
   }
 
-  c = gpr_malloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
-  memset(c, 0, sizeof(grpc_httpcli_ssl_channel_security_connector));
+  c = gpr_zalloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
 
   gpr_ref_init(&c->base.base.refcount, 1);
   c->base.base.vtable = &httpcli_ssl_vtable;
@@ -156,7 +155,7 @@
   if (error != GRPC_ERROR_NONE) {
     const char *msg = grpc_error_string(error);
     gpr_log(GPR_ERROR, "Secure transport setup failed: %s", msg);
-    grpc_error_free_string(msg);
+
     c->func(exec_ctx, c->arg, NULL);
   } else {
     grpc_channel_args_destroy(exec_ctx, args->args);
diff --git a/src/core/lib/iomgr/closure.c b/src/core/lib/iomgr/closure.c
index da0ec87..509c1ff 100644
--- a/src/core/lib/iomgr/closure.c
+++ b/src/core/lib/iomgr/closure.c
@@ -34,6 +34,7 @@
 #include "src/core/lib/iomgr/closure.h"
 
 #include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
 
 #include "src/core/lib/profiling/timers.h"
 
@@ -50,20 +51,22 @@
   closure_list->head = closure_list->tail = NULL;
 }
 
-void grpc_closure_list_append(grpc_closure_list *closure_list,
+bool grpc_closure_list_append(grpc_closure_list *closure_list,
                               grpc_closure *closure, grpc_error *error) {
   if (closure == NULL) {
     GRPC_ERROR_UNREF(error);
-    return;
+    return false;
   }
   closure->error_data.error = error;
   closure->next_data.next = NULL;
-  if (closure_list->head == NULL) {
+  bool was_empty = (closure_list->head == NULL);
+  if (was_empty) {
     closure_list->head = closure;
   } else {
     closure_list->tail->next_data.next = closure;
   }
   closure_list->tail = closure;
+  return was_empty;
 }
 
 void grpc_closure_list_fail_all(grpc_closure_list *list,
diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h
index ee386fb..2510d50 100644
--- a/src/core/lib/iomgr/closure.h
+++ b/src/core/lib/iomgr/closure.h
@@ -66,6 +66,7 @@
               grpc_error *error);
   void (*sched)(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
                 grpc_error *error);
+  const char *name;
 } grpc_closure_scheduler_vtable;
 
 /** Abstract type that can schedule closures for execution */
@@ -115,8 +116,9 @@
 void grpc_closure_list_init(grpc_closure_list *list);
 
 /** add \a closure to the end of \a list
-    and set \a closure's result to \a error */
-void grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure,
+    and set \a closure's result to \a error
+    Returns true if \a list becomes non-empty */
+bool grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure,
                               grpc_error *error);
 
 /** force all success bits in \a list to false */
diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c
index c26a73b..fa9966c 100644
--- a/src/core/lib/iomgr/combiner.c
+++ b/src/core/lib/iomgr/combiner.c
@@ -72,6 +72,7 @@
   bool final_list_covered_by_poller;
   grpc_closure_list final_list;
   grpc_closure offload;
+  gpr_refcount refs;
 };
 
 static void combiner_exec_uncovered(grpc_exec_ctx *exec_ctx,
@@ -86,13 +87,17 @@
                                           grpc_error *error);
 
 static const grpc_closure_scheduler_vtable scheduler_uncovered = {
-    combiner_exec_uncovered, combiner_exec_uncovered};
+    combiner_exec_uncovered, combiner_exec_uncovered,
+    "combiner:immediately:uncovered"};
 static const grpc_closure_scheduler_vtable scheduler_covered = {
-    combiner_exec_covered, combiner_exec_covered};
+    combiner_exec_covered, combiner_exec_covered,
+    "combiner:immediately:covered"};
 static const grpc_closure_scheduler_vtable finally_scheduler_uncovered = {
-    combiner_finally_exec_uncovered, combiner_finally_exec_uncovered};
+    combiner_finally_exec_uncovered, combiner_finally_exec_uncovered,
+    "combiner:finally:uncovered"};
 static const grpc_closure_scheduler_vtable finally_scheduler_covered = {
-    combiner_finally_exec_covered, combiner_finally_exec_covered};
+    combiner_finally_exec_covered, combiner_finally_exec_covered,
+    "combiner:finally:covered"};
 
 static void offload(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
 
@@ -122,6 +127,7 @@
 
 grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) {
   grpc_combiner *lock = gpr_malloc(sizeof(*lock));
+  gpr_ref_init(&lock->refs, 1);
   lock->next_combiner_on_this_exec_ctx = NULL;
   lock->time_to_execute_final_list = false;
   lock->optional_workqueue = optional_workqueue;
@@ -148,7 +154,7 @@
   gpr_free(lock);
 }
 
-void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
+static void start_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
   gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED);
   GRPC_COMBINER_TRACE(gpr_log(
       GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state));
@@ -157,6 +163,30 @@
   }
 }
 
+#ifdef GRPC_COMBINER_REFCOUNT_DEBUG
+#define GRPC_COMBINER_DEBUG_SPAM(op, delta)                               \
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,                             \
+          "combiner[%p] %s %" PRIdPTR " --> %" PRIdPTR " %s", lock, (op), \
+          gpr_atm_no_barrier_load(&lock->refs.count),                     \
+          gpr_atm_no_barrier_load(&lock->refs.count) + (delta), reason);
+#else
+#define GRPC_COMBINER_DEBUG_SPAM(op, delta)
+#endif
+
+void grpc_combiner_unref(grpc_exec_ctx *exec_ctx,
+                         grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) {
+  GRPC_COMBINER_DEBUG_SPAM("UNREF", -1);
+  if (gpr_unref(&lock->refs)) {
+    start_destroy(exec_ctx, lock);
+  }
+}
+
+grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) {
+  GRPC_COMBINER_DEBUG_SPAM("  REF", 1);
+  gpr_ref(&lock->refs);
+  return lock;
+}
+
 static void push_last_on_exec_ctx(grpc_exec_ctx *exec_ctx,
                                   grpc_combiner *lock) {
   lock->next_combiner_on_this_exec_ctx = NULL;
diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h
index 81dff85..75dcb0b 100644
--- a/src/core/lib/iomgr/combiner.h
+++ b/src/core/lib/iomgr/combiner.h
@@ -48,8 +48,27 @@
 // Initialize the lock, with an optional workqueue to shift load to when
 // necessary
 grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue);
-// Destroy the lock
-void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock);
+
+//#define GRPC_COMBINER_REFCOUNT_DEBUG
+#ifdef GRPC_COMBINER_REFCOUNT_DEBUG
+#define GRPC_COMBINER_DEBUG_ARGS \
+  , const char *file, int line, const char *reason
+#define GRPC_COMBINER_REF(combiner, reason) \
+  grpc_combiner_ref((combiner), __FILE__, __LINE__, (reason))
+#define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \
+  grpc_combiner_unref((exec_ctx), (combiner), __FILE__, __LINE__, (reason))
+#else
+#define GRPC_COMBINER_DEBUG_ARGS
+#define GRPC_COMBINER_REF(combiner, reason) grpc_combiner_ref((combiner))
+#define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \
+  grpc_combiner_unref((exec_ctx), (combiner))
+#endif
+
+// Ref/unref the lock, for when we're sharing the lock ownership
+// Prefer to use the macros above
+grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS);
+void grpc_combiner_unref(grpc_exec_ctx *exec_ctx,
+                         grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS);
 // Fetch a scheduler to schedule closures against
 grpc_closure_scheduler *grpc_combiner_scheduler(grpc_combiner *lock,
                                                 bool covered_by_poller);
diff --git a/src/core/lib/iomgr/endpoint.c b/src/core/lib/iomgr/endpoint.c
index 2d300f4..bf6e981 100644
--- a/src/core/lib/iomgr/endpoint.c
+++ b/src/core/lib/iomgr/endpoint.c
@@ -54,8 +54,9 @@
   ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set);
 }
 
-void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
-  ep->vtable->shutdown(exec_ctx, ep);
+void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
+                            grpc_error* why) {
+  ep->vtable->shutdown(exec_ctx, ep, why);
 }
 
 void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h
index 1609b64..740357e 100644
--- a/src/core/lib/iomgr/endpoint.h
+++ b/src/core/lib/iomgr/endpoint.h
@@ -57,7 +57,7 @@
                          grpc_pollset *pollset);
   void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                              grpc_pollset_set *pollset);
-  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
+  void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why);
   void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
   grpc_resource_user *(*get_resource_user)(grpc_endpoint *ep);
   char *(*get_peer)(grpc_endpoint *ep);
@@ -96,7 +96,8 @@
 
 /* Causes any pending and future read/write callbacks to run immediately with
    success==0 */
-void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
+void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                            grpc_error *why);
 void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
 
 /* Add an endpoint to a pollset, so that when the pollset is polled, events from
diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c
index f6bb3a0..dbe5b13 100644
--- a/src/core/lib/iomgr/error.c
+++ b/src/core/lib/iomgr/error.c
@@ -33,13 +33,10 @@
 
 #include "src/core/lib/iomgr/error.h"
 
-#include <inttypes.h>
-#include <stdbool.h>
 #include <string.h>
 
 #include <grpc/status.h>
 #include <grpc/support/alloc.h>
-#include <grpc/support/avl.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
@@ -48,6 +45,7 @@
 #include <grpc/support/log_windows.h>
 #endif
 
+#include "src/core/lib/iomgr/error_internal.h"
 #include "src/core/lib/profiling/timers.h"
 
 static void destroy_integer(void *key) {}
@@ -128,6 +126,10 @@
 
 static const char *error_str_name(grpc_error_strs key) {
   switch (key) {
+    case GRPC_ERROR_STR_KEY:
+      return "key";
+    case GRPC_ERROR_STR_VALUE:
+      return "value";
     case GRPC_ERROR_STR_DESCRIPTION:
       return "description";
     case GRPC_ERROR_STR_OS_ERROR:
@@ -160,16 +162,7 @@
   GPR_UNREACHABLE_CODE(return "unknown");
 }
 
-struct grpc_error {
-  gpr_refcount refs;
-  gpr_avl ints;
-  gpr_avl strs;
-  gpr_avl times;
-  gpr_avl errs;
-  uintptr_t next_err;
-};
-
-static bool is_special(grpc_error *err) {
+bool grpc_error_is_special(grpc_error *err) {
   return err == GRPC_ERROR_NONE || err == GRPC_ERROR_OOM ||
          err == GRPC_ERROR_CANCELLED;
 }
@@ -177,7 +170,7 @@
 #ifdef GRPC_ERROR_REFCOUNT_DEBUG
 grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
                            const char *func) {
-  if (is_special(err)) return err;
+  if (grpc_error_is_special(err)) return err;
   gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err,
           err->refs.count, err->refs.count + 1, file, line, func);
   gpr_ref(&err->refs);
@@ -185,25 +178,26 @@
 }
 #else
 grpc_error *grpc_error_ref(grpc_error *err) {
-  if (is_special(err)) return err;
+  if (grpc_error_is_special(err)) return err;
   gpr_ref(&err->refs);
   return err;
 }
 #endif
 
 static void error_destroy(grpc_error *err) {
-  GPR_ASSERT(!is_special(err));
+  GPR_ASSERT(!grpc_error_is_special(err));
   gpr_avl_unref(err->ints);
   gpr_avl_unref(err->strs);
   gpr_avl_unref(err->errs);
   gpr_avl_unref(err->times);
+  gpr_free((void *)gpr_atm_acq_load(&err->error_string));
   gpr_free(err);
 }
 
 #ifdef GRPC_ERROR_REFCOUNT_DEBUG
 void grpc_error_unref(grpc_error *err, const char *file, int line,
                       const char *func) {
-  if (is_special(err)) return;
+  if (grpc_error_is_special(err)) return;
   gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err,
           err->refs.count, err->refs.count - 1, file, line, func);
   if (gpr_unref(&err->refs)) {
@@ -212,7 +206,7 @@
 }
 #else
 void grpc_error_unref(grpc_error *err) {
-  if (is_special(err)) return;
+  if (grpc_error_is_special(err)) return;
   if (gpr_unref(&err->refs)) {
     error_destroy(err);
   }
@@ -247,6 +241,7 @@
   err->times = gpr_avl_add(gpr_avl_create(&avl_vtable_times),
                            (void *)(uintptr_t)GRPC_ERROR_TIME_CREATED,
                            box_time(gpr_now(GPR_CLOCK_REALTIME)));
+  gpr_atm_no_barrier_store(&err->error_string, 0);
   gpr_ref_init(&err->refs, 1);
   GPR_TIMER_END("grpc_error_create", 0);
   return err;
@@ -255,9 +250,10 @@
 static grpc_error *copy_error_and_unref(grpc_error *in) {
   GPR_TIMER_BEGIN("copy_error_and_unref", 0);
   grpc_error *out;
-  if (is_special(in)) {
+  if (grpc_error_is_special(in)) {
     if (in == GRPC_ERROR_NONE)
-      out = GRPC_ERROR_CREATE("no error");
+      out = grpc_error_set_int(GRPC_ERROR_CREATE("no error"),
+                               GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK);
     else if (in == GRPC_ERROR_OOM)
       out = GRPC_ERROR_CREATE("oom");
     else if (in == GRPC_ERROR_CANCELLED)
@@ -275,6 +271,7 @@
     out->strs = gpr_avl_ref(in->strs);
     out->errs = gpr_avl_ref(in->errs);
     out->times = gpr_avl_ref(in->times);
+    gpr_atm_no_barrier_store(&out->error_string, 0);
     out->next_err = in->next_err;
     gpr_ref_init(&out->refs, 1);
     GRPC_ERROR_UNREF(in);
@@ -292,14 +289,29 @@
   return new;
 }
 
+typedef struct {
+  grpc_error *error;
+  grpc_status_code code;
+  const char *msg;
+} special_error_status_map;
+static special_error_status_map error_status_map[] = {
+    {GRPC_ERROR_NONE, GRPC_STATUS_OK, NULL},
+    {GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "Cancelled"},
+    {GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},
+};
+
 bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) {
   GPR_TIMER_BEGIN("grpc_error_get_int", 0);
   void *pp;
-  if (is_special(err)) {
-    if (err == GRPC_ERROR_CANCELLED && which == GRPC_ERROR_INT_GRPC_STATUS) {
-      *p = GRPC_STATUS_CANCELLED;
-      GPR_TIMER_END("grpc_error_get_int", 0);
-      return true;
+  if (grpc_error_is_special(err)) {
+    if (which == GRPC_ERROR_INT_GRPC_STATUS) {
+      for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
+        if (error_status_map[i].error == err) {
+          if (p != NULL) *p = error_status_map[i].code;
+          GPR_TIMER_END("grpc_error_get_int", 0);
+          return true;
+        }
+      }
     }
     GPR_TIMER_END("grpc_error_get_int", 0);
     return false;
@@ -324,66 +336,17 @@
 }
 
 const char *grpc_error_get_str(grpc_error *err, grpc_error_strs which) {
-  if (is_special(err)) return NULL;
-  return gpr_avl_get(err->strs, (void *)(uintptr_t)which);
-}
-
-typedef struct {
-  grpc_error *error;
-  grpc_status_code code;
-  const char *msg;
-} special_error_status_map;
-static special_error_status_map error_status_map[] = {
-    {GRPC_ERROR_NONE, GRPC_STATUS_OK, ""},
-    {GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "RPC cancelled"},
-    {GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},
-};
-
-static grpc_error *recursively_find_error_with_status(grpc_error *error,
-                                                      intptr_t *status) {
-  // If the error itself has a status code, return it.
-  if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, status)) {
-    return error;
-  }
-  // Otherwise, search through its children.
-  intptr_t key = 0;
-  while (true) {
-    grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++);
-    if (child_error == NULL) break;
-    grpc_error *result =
-        recursively_find_error_with_status(child_error, status);
-    if (result != NULL) return result;
-  }
-  return NULL;
-}
-
-void grpc_error_get_status(grpc_error *error, grpc_status_code *code,
-                           const char **msg) {
-  // Handle special errors via the static map.
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); ++i) {
-    if (error == error_status_map[i].error) {
-      *code = error_status_map[i].code;
-      *msg = error_status_map[i].msg;
-      return;
+  if (grpc_error_is_special(err)) {
+    if (which == GRPC_ERROR_STR_GRPC_MESSAGE) {
+      for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
+        if (error_status_map[i].error == err) {
+          return error_status_map[i].msg;
+        }
+      }
     }
+    return NULL;
   }
-  // Populate code.
-  // Start with the parent error and recurse through the tree of children
-  // until we find the first one that has a status code.
-  intptr_t status = GRPC_STATUS_UNKNOWN;  // Default in case we don't find one.
-  grpc_error *found_error = recursively_find_error_with_status(error, &status);
-  *code = (grpc_status_code)status;
-  // Now populate msg.
-  // If we found an error with a status code above, use that; otherwise,
-  // fall back to using the parent error.
-  if (found_error == NULL) found_error = error;
-  // If the error has a status message, use it.  Otherwise, fall back to
-  // the error description.
-  *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE);
-  if (*msg == NULL) {
-    *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION);
-    if (*msg == NULL) *msg = "uknown error";  // Just in case.
-  }
+  return gpr_avl_get(err->strs, (void *)(uintptr_t)which);
 }
 
 grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) {
@@ -535,7 +498,6 @@
   *first = false;
   const char *e = grpc_error_string(n->value);
   append_str(e, s, sz, cap);
-  grpc_error_free_string(e);
   add_errs(n->right, s, sz, cap, first);
 }
 
@@ -557,7 +519,7 @@
   return strcmp(ka->key, kb->key);
 }
 
-static const char *finish_kvs(kv_pairs *kvs) {
+static char *finish_kvs(kv_pairs *kvs) {
   char *s = NULL;
   size_t sz = 0;
   size_t cap = 0;
@@ -578,19 +540,18 @@
   return s;
 }
 
-void grpc_error_free_string(const char *str) {
-  if (str == no_error_string) return;
-  if (str == oom_error_string) return;
-  if (str == cancelled_error_string) return;
-  gpr_free((char *)str);
-}
-
 const char *grpc_error_string(grpc_error *err) {
   GPR_TIMER_BEGIN("grpc_error_string", 0);
   if (err == GRPC_ERROR_NONE) return no_error_string;
   if (err == GRPC_ERROR_OOM) return oom_error_string;
   if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string;
 
+  void *p = (void *)gpr_atm_acq_load(&err->error_string);
+  if (p != NULL) {
+    GPR_TIMER_END("grpc_error_string", 0);
+    return p;
+  }
+
   kv_pairs kvs;
   memset(&kvs, 0, sizeof(kvs));
 
@@ -603,7 +564,13 @@
 
   qsort(kvs.kvs, kvs.num_kvs, sizeof(kv_pair), cmp_kvs);
 
-  const char *out = finish_kvs(&kvs);
+  char *out = finish_kvs(&kvs);
+
+  if (!gpr_atm_rel_cas(&err->error_string, 0, (gpr_atm)out)) {
+    gpr_free(out);
+    out = (char *)gpr_atm_no_barrier_load(&err->error_string);
+  }
+
   GPR_TIMER_END("grpc_error_string", 0);
   return out;
 }
@@ -638,7 +605,6 @@
   if (error == GRPC_ERROR_NONE) return true;
   const char *msg = grpc_error_string(error);
   gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, msg);
-  grpc_error_free_string(msg);
   GRPC_ERROR_UNREF(error);
   return false;
 }
diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h
index f3f3b80..2613512 100644
--- a/src/core/lib/iomgr/error.h
+++ b/src/core/lib/iomgr/error.h
@@ -124,7 +124,11 @@
   /// filename that we were trying to read/write when this error occurred
   GRPC_ERROR_STR_FILENAME,
   /// which data was queued for writing when the error occurred
-  GRPC_ERROR_STR_QUEUED_BUFFERS
+  GRPC_ERROR_STR_QUEUED_BUFFERS,
+  /// key associated with the error
+  GRPC_ERROR_STR_KEY,
+  /// value associated with the error
+  GRPC_ERROR_STR_VALUE,
 } grpc_error_strs;
 
 typedef enum {
@@ -133,15 +137,14 @@
 } grpc_error_times;
 
 /// The following "special" errors can be propagated without allocating memory.
-/// They are always even so that other code (particularly combiner locks) can
-/// safely use the lower bit for themselves.
+/// They are always even so that other code (particularly combiner locks,
+/// polling engines) can safely use the lower bit for themselves.
 
 #define GRPC_ERROR_NONE ((grpc_error *)NULL)
 #define GRPC_ERROR_OOM ((grpc_error *)2)
 #define GRPC_ERROR_CANCELLED ((grpc_error *)4)
 
 const char *grpc_error_string(grpc_error *error);
-void grpc_error_free_string(const char *str);
 
 /// Create an error - but use GRPC_ERROR_CREATE instead
 grpc_error *grpc_error_create(const char *file, int line, const char *desc,
@@ -189,12 +192,6 @@
 /// Caller does NOT own return value.
 const char *grpc_error_get_str(grpc_error *error, grpc_error_strs which);
 
-/// A utility function to get the status code and message to be returned
-/// to the application.  If not set in the top-level message, looks
-/// through child errors until it finds the first one with these attributes.
-void grpc_error_get_status(grpc_error *error, grpc_status_code *code,
-                           const char **msg);
-
 /// Add a child error: an error that is believed to have contributed to this
 /// error occurring. Allows root causing high level errors from lower level
 /// errors that contributed to them.
diff --git a/src/core/lib/iomgr/error_internal.h b/src/core/lib/iomgr/error_internal.h
new file mode 100644
index 0000000..1c89ead
--- /dev/null
+++ b/src/core/lib/iomgr/error_internal.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H
+#define GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <grpc/support/avl.h>
+
+struct grpc_error {
+  gpr_refcount refs;
+  gpr_avl ints;
+  gpr_avl strs;
+  gpr_avl times;
+  gpr_avl errs;
+  uintptr_t next_err;
+  gpr_atm error_string;
+};
+
+bool grpc_error_is_special(grpc_error *err);
+
+#endif /* GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H */
diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c
index 715d057..11208b9 100644
--- a/src/core/lib/iomgr/ev_epoll_linux.c
+++ b/src/core/lib/iomgr/ev_epoll_linux.c
@@ -68,7 +68,7 @@
     gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \
   }
 
-/* Uncomment the following enable extra checks on poll_object operations */
+/* Uncomment the following to enable extra checks on poll_object operations */
 /* #define PO_DEBUG */
 
 static int grpc_wakeup_signal = -1;
@@ -140,23 +140,61 @@
      Ref/Unref by two to avoid altering the orphaned bit */
   gpr_atm refst;
 
-  /* Indicates that the fd is shutdown and that any pending read/write closures
-     should fail */
-  bool shutdown;
+  /* Internally stores data of type (grpc_error *). If the FD is shutdown, this
+     contains reason for shutdown (i.e a pointer to grpc_error) ORed with
+     FD_SHUTDOWN_BIT. Since address allocations are word-aligned, the lower bit
+     of (grpc_error *) addresses is guaranteed to be zero. Even if the
+     (grpc_error *), is of special types like GRPC_ERROR_NONE, GRPC_ERROR_OOM
+     etc, the lower bit is guaranteed to be zero.
 
-  /* The fd is either closed or we relinquished control of it. In either cases,
-     this indicates that the 'fd' on this structure is no longer valid */
+     Once an fd is shutdown, any pending or future read/write closures on the
+     fd should fail */
+  gpr_atm shutdown_error;
+
+  /* The fd is either closed or we relinquished control of it. In either
+     cases, this indicates that the 'fd' on this structure is no longer
+     valid */
   bool orphaned;
 
-  /* TODO: sreek - Move this to a lockfree implementation */
-  grpc_closure *read_closure;
-  grpc_closure *write_closure;
+  /* Closures to call when the fd is readable or writable respectively. These
+     fields contain one of the following values:
+       CLOSURE_READY     : The fd has an I/O event of interest but there is no
+                           closure yet to execute
+
+       CLOSURE_NOT_READY : The fd has no I/O event of interest
+
+       closure ptr       : The closure to be executed when the fd has an I/O
+                           event of interest
+
+       shutdown_error | FD_SHUTDOWN_BIT :
+                          'shutdown_error' field ORed with FD_SHUTDOWN_BIT.
+                           This indicates that the fd is shutdown. Since all
+                           memory allocations are word-aligned, the lower two
+                           bits of the shutdown_error pointer are always 0. So
+                           it is safe to OR these with FD_SHUTDOWN_BIT
+
+     Valid state transitions:
+
+       <closure ptr> <-----3------ CLOSURE_NOT_READY ----1---->  CLOSURE_READY
+         |  |                         ^   |    ^                         |  |
+         |  |                         |   |    |                         |  |
+         |  +--------------4----------+   6    +---------2---------------+  |
+         |                                |                                 |
+         |                                v                                 |
+         +-----5------->  [shutdown_error | FD_SHUTDOWN_BIT] <----7---------+
+
+      For 1, 4 : See set_ready() function
+      For 2, 3 : See notify_on() function
+      For 5,6,7: See set_shutdown() function */
+  gpr_atm read_closure;
+  gpr_atm write_closure;
 
   struct grpc_fd *freelist_next;
   grpc_closure *on_done_closure;
 
-  /* The pollset that last noticed that the fd is readable */
-  grpc_pollset *read_notifier_pollset;
+  /* The pollset that last noticed that the fd is readable. The actual type
+   * stored in this is (grpc_pollset *) */
+  gpr_atm read_notifier_pollset;
 
   grpc_iomgr_object iomgr_object;
 };
@@ -179,8 +217,10 @@
 static void fd_global_init(void);
 static void fd_global_shutdown(void);
 
-#define CLOSURE_NOT_READY ((grpc_closure *)0)
-#define CLOSURE_READY ((grpc_closure *)1)
+#define CLOSURE_NOT_READY ((gpr_atm)0)
+#define CLOSURE_READY ((gpr_atm)2)
+
+#define FD_SHUTDOWN_BIT 1
 
 /*******************************************************************************
  * Polling island Declarations
@@ -321,7 +361,7 @@
 #endif /* defined(GRPC_TSAN) */
 
 static const grpc_closure_scheduler_vtable workqueue_scheduler_vtable = {
-    workqueue_enqueue, workqueue_enqueue};
+    workqueue_enqueue, workqueue_enqueue, "workqueue"};
 
 static void pi_add_ref(polling_island *pi);
 static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi);
@@ -908,6 +948,11 @@
     fd_freelist = fd;
     grpc_iomgr_unregister_object(&fd->iomgr_object);
 
+    grpc_error *err = (grpc_error *)gpr_atm_acq_load(&fd->shutdown_error);
+    /* Clear the least significant bit if it set (in case fd was shutdown) */
+    err = (grpc_error *)((intptr_t)err & ~FD_SHUTDOWN_BIT);
+    GRPC_ERROR_UNREF(err);
+
     gpr_mu_unlock(&fd_freelist_mu);
   } else {
     GPR_ASSERT(old > n);
@@ -970,13 +1015,14 @@
 
   gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
   new_fd->fd = fd;
-  new_fd->shutdown = false;
+  gpr_atm_no_barrier_store(&new_fd->shutdown_error, (gpr_atm)GRPC_ERROR_NONE);
   new_fd->orphaned = false;
-  new_fd->read_closure = CLOSURE_NOT_READY;
-  new_fd->write_closure = CLOSURE_NOT_READY;
+  gpr_atm_no_barrier_store(&new_fd->read_closure, CLOSURE_NOT_READY);
+  gpr_atm_no_barrier_store(&new_fd->write_closure, CLOSURE_NOT_READY);
+  gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
+
   new_fd->freelist_next = NULL;
   new_fd->on_done_closure = NULL;
-  new_fd->read_notifier_pollset = NULL;
 
   gpr_mu_unlock(&new_fd->po.mu);
 
@@ -1058,98 +1104,206 @@
   GRPC_ERROR_UNREF(error);
 }
 
-static grpc_error *fd_shutdown_error(bool shutdown) {
-  if (!shutdown) {
-    return GRPC_ERROR_NONE;
-  } else {
-    return GRPC_ERROR_CREATE("FD shutdown");
+static void notify_on(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
+                      grpc_closure *closure) {
+  while (true) {
+    /* Fast-path: CLOSURE_NOT_READY -> <closure>.
+       The 'release' cas here matches the 'acquire' load in set_ready and
+       set_shutdown ensuring that the closure (scheduled by set_ready or
+       set_shutdown) happens-after the I/O event on the fd */
+    if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, (gpr_atm)closure)) {
+      return; /* Fast-path successful. Return */
+    }
+
+    /* Slowpath. The 'acquire' load matches the 'release' cas in set_ready and
+       set_shutdown */
+    gpr_atm curr = gpr_atm_acq_load(state);
+    switch (curr) {
+      case CLOSURE_NOT_READY: {
+        break; /* retry */
+      }
+
+      case CLOSURE_READY: {
+        /* Change the state to CLOSURE_NOT_READY. Schedule the closure if
+           successful. If not, the state most likely transitioned to shutdown.
+           We should retry.
+
+           This can be a no-barrier cas since the state is being transitioned to
+           CLOSURE_NOT_READY; set_ready and set_shutdown do not schedule any
+           closure when transitioning out of CLOSURE_NO_READY state (i.e there
+           is no other code that needs to 'happen-after' this) */
+        if (gpr_atm_no_barrier_cas(state, CLOSURE_READY, CLOSURE_NOT_READY)) {
+          grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE);
+          return; /* Slow-path successful. Return */
+        }
+
+        break; /* retry */
+      }
+
+      default: {
+        /* 'curr' is either a closure or the fd is shutdown(in which case 'curr'
+           contains a pointer to the shutdown-error). If the fd is shutdown,
+           schedule the closure with the shutdown error */
+        if ((curr & FD_SHUTDOWN_BIT) > 0) {
+          grpc_error *shutdown_err = (grpc_error *)(curr & ~FD_SHUTDOWN_BIT);
+          grpc_closure_sched(
+              exec_ctx, closure,
+              GRPC_ERROR_CREATE_REFERENCING("FD Shutdown", &shutdown_err, 1));
+          return;
+        }
+
+        /* There is already a closure!. This indicates a bug in the code */
+        gpr_log(GPR_ERROR,
+                "notify_on called with a previous callback still pending");
+        abort();
+      }
+    }
   }
+
+  GPR_UNREACHABLE_CODE(return );
 }
 
-static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                             grpc_closure **st, grpc_closure *closure) {
-  if (fd->shutdown) {
-    grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE("FD shutdown"));
-  } else if (*st == CLOSURE_NOT_READY) {
-    /* not ready ==> switch to a waiting state by setting the closure */
-    *st = closure;
-  } else if (*st == CLOSURE_READY) {
-    /* already ready ==> queue the closure to run immediately */
-    *st = CLOSURE_NOT_READY;
-    grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown));
-  } else {
-    /* upcallptr was set to a different closure.  This is an error! */
-    gpr_log(GPR_ERROR,
-            "User called a notify_on function with a previous callback still "
-            "pending");
-    abort();
+static void set_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
+                         grpc_error *shutdown_err) {
+  /* Try the fast-path first (i.e expect the current value to be
+     CLOSURE_NOT_READY */
+  gpr_atm curr = CLOSURE_NOT_READY;
+  gpr_atm new_state = (gpr_atm)shutdown_err | FD_SHUTDOWN_BIT;
+
+  while (true) {
+    /* The 'release' cas here matches the 'acquire' load in notify_on to ensure
+       that the closure it schedules 'happens-after' the set_shutdown is called
+       on the fd */
+    if (gpr_atm_rel_cas(state, curr, new_state)) {
+      return; /* Fast-path successful. Return */
+    }
+
+    /* Fallback to slowpath. This 'acquire' load matches the 'release' cas in
+       notify_on and set_ready */
+    curr = gpr_atm_acq_load(state);
+    switch (curr) {
+      case CLOSURE_READY: {
+        break; /* retry */
+      }
+
+      case CLOSURE_NOT_READY: {
+        break; /* retry */
+      }
+
+      default: {
+        /* 'curr' is either a closure or the fd is already shutdown */
+
+        /* If fd is already shutdown, we are done */
+        if ((curr & FD_SHUTDOWN_BIT) > 0) {
+          return;
+        }
+
+        /* Fd is not shutdown. Schedule the closure and move the state to
+           shutdown state. The 'release' cas here matches the 'acquire' load in
+           notify_on to ensure that the closure it schedules 'happens-after'
+           the set_shutdown is called on the fd */
+        if (gpr_atm_rel_cas(state, curr, new_state)) {
+          grpc_closure_sched(
+              exec_ctx, (grpc_closure *)curr,
+              GRPC_ERROR_CREATE_REFERENCING("FD Shutdown", &shutdown_err, 1));
+          return;
+        }
+
+        /* 'curr' was a closure but now changed to a different state. We will
+          have to retry */
+        break;
+      }
+    }
   }
+
+  GPR_UNREACHABLE_CODE(return );
 }
 
-/* returns 1 if state becomes not ready */
-static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
-                            grpc_closure **st) {
-  if (*st == CLOSURE_READY) {
-    /* duplicate ready ==> ignore */
-    return 0;
-  } else if (*st == CLOSURE_NOT_READY) {
-    /* not ready, and not waiting ==> flag ready */
-    *st = CLOSURE_READY;
-    return 0;
-  } else {
-    /* waiting ==> queue closure */
-    grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown));
-    *st = CLOSURE_NOT_READY;
-    return 1;
+static void set_ready(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state) {
+  /* Try an optimistic case first (i.e assume current state is
+     CLOSURE_NOT_READY).
+
+     This 'release' cas matches the 'acquire' load in notify_on ensuring that
+     any closure (scheduled by notify_on) 'happens-after' the return from
+     epoll_pwait */
+  if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, CLOSURE_READY)) {
+    return; /* early out */
+  }
+
+  /* The 'acquire' load here matches the 'release' cas in notify_on and
+     set_shutdown */
+  gpr_atm curr = gpr_atm_acq_load(state);
+  switch (curr) {
+    case CLOSURE_READY: {
+      /* Already ready. We are done here */
+      break;
+    }
+
+    case CLOSURE_NOT_READY: {
+      /* The state was not CLOSURE_NOT_READY when we checked initially at the
+         beginning of this function but now it is CLOSURE_NOT_READY again.
+         This is only possible if the state transitioned out of
+         CLOSURE_NOT_READY to either CLOSURE_READY or <some closure> and then
+         back to CLOSURE_NOT_READY again (i.e after we entered this function,
+         the fd became "ready" and the necessary actions were already done).
+         So there is no need to make the state CLOSURE_READY now */
+      break;
+    }
+
+    default: {
+      /* 'curr' is either a closure or the fd is shutdown */
+      if ((curr & FD_SHUTDOWN_BIT) > 0) {
+        /* The fd is shutdown. Do nothing */
+      } else if (gpr_atm_no_barrier_cas(state, curr, CLOSURE_NOT_READY)) {
+        /* The cas above was no-barrier since the state is being transitioned to
+           CLOSURE_NOT_READY; notify_on and set_shutdown do not schedule any
+           closures when transitioning out of CLOSURE_NO_READY state (i.e there
+           is no other code that needs to 'happen-after' this) */
+
+        grpc_closure_sched(exec_ctx, (grpc_closure *)curr, GRPC_ERROR_NONE);
+      }
+      /* else the state changed again (only possible by either a racing
+         set_ready or set_shutdown functions. In both these cases, the closure
+         would have been scheduled for execution. So we are done here */
+      break;
+    }
   }
 }
 
 static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
                                                   grpc_fd *fd) {
-  grpc_pollset *notifier = NULL;
-
-  gpr_mu_lock(&fd->po.mu);
-  notifier = fd->read_notifier_pollset;
-  gpr_mu_unlock(&fd->po.mu);
-
-  return notifier;
+  gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset);
+  return (grpc_pollset *)notifier;
 }
 
 static bool fd_is_shutdown(grpc_fd *fd) {
-  gpr_mu_lock(&fd->po.mu);
-  const bool r = fd->shutdown;
-  gpr_mu_unlock(&fd->po.mu);
-  return r;
+  grpc_error *err = (grpc_error *)gpr_atm_acq_load(&fd->shutdown_error);
+  return (((intptr_t)err & FD_SHUTDOWN_BIT) > 0);
 }
 
 /* Might be called multiple times */
-static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  gpr_mu_lock(&fd->po.mu);
-  /* Do the actual shutdown only once */
-  if (!fd->shutdown) {
-    fd->shutdown = true;
-
+static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
+  /* Store the shutdown error ORed with FD_SHUTDOWN_BIT in fd->shutdown_error */
+  if (gpr_atm_rel_cas(&fd->shutdown_error, (gpr_atm)GRPC_ERROR_NONE,
+                      (gpr_atm)why | FD_SHUTDOWN_BIT)) {
     shutdown(fd->fd, SHUT_RDWR);
-    /* Flush any pending read and write closures. Since fd->shutdown is 'true'
-       at this point, the closures would be called with 'success = false' */
-    set_ready_locked(exec_ctx, fd, &fd->read_closure);
-    set_ready_locked(exec_ctx, fd, &fd->write_closure);
+
+    set_shutdown(exec_ctx, fd, &fd->read_closure, why);
+    set_shutdown(exec_ctx, fd, &fd->write_closure, why);
+  } else {
+    /* Shutdown already called */
+    GRPC_ERROR_UNREF(why);
   }
-  gpr_mu_unlock(&fd->po.mu);
 }
 
 static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_closure *closure) {
-  gpr_mu_lock(&fd->po.mu);
-  notify_on_locked(exec_ctx, fd, &fd->read_closure, closure);
-  gpr_mu_unlock(&fd->po.mu);
+  notify_on(exec_ctx, fd, &fd->read_closure, closure);
 }
 
 static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_closure *closure) {
-  gpr_mu_lock(&fd->po.mu);
-  notify_on_locked(exec_ctx, fd, &fd->write_closure, closure);
-  gpr_mu_unlock(&fd->po.mu);
+  notify_on(exec_ctx, fd, &fd->write_closure, closure);
 }
 
 static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) {
@@ -1338,18 +1492,19 @@
 
 static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                                grpc_pollset *notifier) {
-  /* Need the fd->po.mu since we might be racing with fd_notify_on_read */
-  gpr_mu_lock(&fd->po.mu);
-  set_ready_locked(exec_ctx, fd, &fd->read_closure);
-  fd->read_notifier_pollset = notifier;
-  gpr_mu_unlock(&fd->po.mu);
+  set_ready(exec_ctx, fd, &fd->read_closure);
+
+  /* Note, it is possible that fd_become_readable might be called twice with
+     different 'notifier's when an fd becomes readable and it is in two epoll
+     sets (This can happen briefly during polling island merges). In such cases
+     it does not really matter which notifer is set as the read_notifier_pollset
+     (They would both point to the same polling island anyway) */
+  /* Use release store to match with acquire load in fd_get_read_notifier */
+  gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier);
 }
 
 static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  /* Need the fd->po.mu since we might be racing with fd_notify_on_write */
-  gpr_mu_lock(&fd->po.mu);
-  set_ready_locked(exec_ctx, fd, &fd->write_closure);
-  gpr_mu_unlock(&fd->po.mu);
+  set_ready(exec_ctx, fd, &fd->write_closure);
 }
 
 static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx,
@@ -1400,16 +1555,6 @@
   gpr_mu_destroy(&pollset->po.mu);
 }
 
-static void pollset_reset(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->shutting_down);
-  GPR_ASSERT(!pollset_has_workers(pollset));
-  pollset->shutting_down = false;
-  pollset->finish_shutdown_called = false;
-  pollset->kicked_without_pollers = false;
-  pollset->shutdown_done = NULL;
-  GPR_ASSERT(pollset->po.pi == NULL);
-}
-
 static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx,
                                     polling_island *pi) {
   if (gpr_mu_trylock(&pi->workqueue_read_mu)) {
@@ -1527,7 +1672,8 @@
         append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
                      err_desc);
       } else if (data_ptr == &pi->workqueue_wakeup_fd) {
-        append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
+        append_error(error,
+                     grpc_wakeup_fd_consume_wakeup(&pi->workqueue_wakeup_fd),
                      err_desc);
         maybe_do_workqueue_work(exec_ctx, pi);
       } else if (data_ptr == &polling_island_wakeup_fd) {
@@ -1741,7 +1887,7 @@
               (void *)pi_new, FD_FROM_PO(item)->fd, poll_obj_string(bag_type),
               (void *)bag);
           /* No need to lock 'pi_new' here since this is a new polling island
-            * and no one has a reference to it yet */
+             and no one has a reference to it yet */
           polling_island_remove_all_fds_locked(pi_new, true, &error);
 
           /* Ref and unref so that the polling island gets deleted during unref
@@ -1846,13 +1992,12 @@
   return pss;
 }
 
-static void pollset_set_destroy(grpc_pollset_set *pss) {
+static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
+                                grpc_pollset_set *pss) {
   gpr_mu_destroy(&pss->po.mu);
 
   if (pss->po.pi != NULL) {
-    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    PI_UNREF(&exec_ctx, pss->po.pi, "pss_destroy");
-    grpc_exec_ctx_finish(&exec_ctx);
+    PI_UNREF(exec_ctx, pss->po.pi, "pss_destroy");
   }
 
   gpr_free(pss);
@@ -1952,7 +2097,6 @@
 
     .pollset_init = pollset_init,
     .pollset_shutdown = pollset_shutdown,
-    .pollset_reset = pollset_reset,
     .pollset_destroy = pollset_destroy,
     .pollset_work = pollset_work,
     .pollset_kick = pollset_kick,
diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c
index 9477ac3..5ddd531 100644
--- a/src/core/lib/iomgr/ev_poll_posix.c
+++ b/src/core/lib/iomgr/ev_poll_posix.c
@@ -82,6 +82,7 @@
   int shutdown;
   int closed;
   int released;
+  grpc_error *shutdown_error;
 
   /* The watcher list.
 
@@ -148,7 +149,7 @@
 static bool fd_is_orphaned(grpc_fd *fd);
 
 /* Reference counting for fds */
-/*#define GRPC_FD_REF_COUNT_DEBUG*/
+//#define GRPC_FD_REF_COUNT_DEBUG
 #ifdef GRPC_FD_REF_COUNT_DEBUG
 static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
 static void fd_unref(grpc_fd *fd, const char *reason, const char *file,
@@ -190,6 +191,7 @@
   int kicked_without_pollers;
   grpc_closure *shutdown_done;
   grpc_closure_list idle_jobs;
+  int pollset_set_count;
   /* all polled fds */
   size_t fd_count;
   size_t fd_capacity;
@@ -227,7 +229,7 @@
 
 /* Return 1 if the pollset has active threads in pollset_work (pollset must
  * be locked) */
-static int pollset_has_workers(grpc_pollset *pollset);
+static bool pollset_has_workers(grpc_pollset *pollset);
 
 /*******************************************************************************
  * pollset_set definitions
@@ -281,8 +283,8 @@
 static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
                    int line) {
   gpr_log(GPR_DEBUG, "FD %d %p   ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n,
-          gpr_atm_no_barrier_load(&fd->refst),
-          gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
+          (int)gpr_atm_no_barrier_load(&fd->refst),
+          (int)gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
 #else
 #define REF_BY(fd, n, reason) ref_by(fd, n)
 #define UNREF_BY(fd, n, reason) unref_by(fd, n)
@@ -296,8 +298,8 @@
                      int line) {
   gpr_atm old;
   gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n,
-          gpr_atm_no_barrier_load(&fd->refst),
-          gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
+          (int)gpr_atm_no_barrier_load(&fd->refst),
+          (int)gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
 #else
 static void unref_by(grpc_fd *fd, int n) {
   gpr_atm old;
@@ -306,6 +308,7 @@
   if (old == n) {
     gpr_mu_destroy(&fd->mu);
     grpc_iomgr_unregister_object(&fd->iomgr_object);
+    if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error);
     gpr_free(fd);
   } else {
     GPR_ASSERT(old > n);
@@ -444,11 +447,11 @@
 static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
 #endif
 
-static grpc_error *fd_shutdown_error(bool shutdown) {
-  if (!shutdown) {
+static grpc_error *fd_shutdown_error(grpc_fd *fd) {
+  if (!fd->shutdown) {
     return GRPC_ERROR_NONE;
   } else {
-    return GRPC_ERROR_CREATE("FD shutdown");
+    return GRPC_ERROR_CREATE_REFERENCING("FD shutdown", &fd->shutdown_error, 1);
   }
 }
 
@@ -462,7 +465,7 @@
   } else if (*st == CLOSURE_READY) {
     /* already ready ==> queue the closure to run immediately */
     *st = CLOSURE_NOT_READY;
-    grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown));
+    grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd));
     maybe_wake_one_watcher_locked(fd);
   } else {
     /* upcallptr was set to a different closure.  This is an error! */
@@ -485,7 +488,7 @@
     return 0;
   } else {
     /* waiting ==> queue closure */
-    grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown));
+    grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd));
     *st = CLOSURE_NOT_READY;
     return 1;
   }
@@ -496,15 +499,18 @@
   fd->read_notifier_pollset = read_notifier_pollset;
 }
 
-static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
+static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
   gpr_mu_lock(&fd->mu);
   /* only shutdown once */
   if (!fd->shutdown) {
     fd->shutdown = 1;
+    fd->shutdown_error = why;
     /* signal read/write closed to OS so that future operations fail */
     shutdown(fd->fd, SHUT_RDWR);
     set_ready_locked(exec_ctx, fd, &fd->read_closure);
     set_ready_locked(exec_ctx, fd, &fd->write_closure);
+  } else {
+    GRPC_ERROR_UNREF(why);
   }
   gpr_mu_unlock(&fd->mu);
 }
@@ -653,10 +659,18 @@
   worker->next->prev = worker->prev;
 }
 
-static int pollset_has_workers(grpc_pollset *p) {
+static bool pollset_has_workers(grpc_pollset *p) {
   return p->root_worker.next != &p->root_worker;
 }
 
+static bool pollset_in_pollset_sets(grpc_pollset *p) {
+  return p->pollset_set_count;
+}
+
+static bool pollset_has_observers(grpc_pollset *p) {
+  return pollset_has_workers(p) || pollset_in_pollset_sets(p);
+}
+
 static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) {
   if (pollset_has_workers(p)) {
     grpc_pollset_worker *w = p->root_worker.next;
@@ -795,6 +809,7 @@
   pollset->fd_count = 0;
   pollset->fd_capacity = 0;
   pollset->fds = NULL;
+  pollset->pollset_set_count = 0;
 }
 
 static void pollset_destroy(grpc_pollset *pollset) {
@@ -810,16 +825,6 @@
   gpr_mu_destroy(&pollset->mu);
 }
 
-static void pollset_reset(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->shutting_down);
-  GPR_ASSERT(!pollset_has_workers(pollset));
-  GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail);
-  GPR_ASSERT(pollset->fd_count == 0);
-  pollset->shutting_down = 0;
-  pollset->called_shutdown = 0;
-  pollset->kicked_without_pollers = 0;
-}
-
 static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                            grpc_fd *fd) {
   gpr_mu_lock(&pollset->mu);
@@ -1066,7 +1071,7 @@
   if (pollset->shutting_down) {
     if (pollset_has_workers(pollset)) {
       pollset_kick(pollset, NULL);
-    } else if (!pollset->called_shutdown) {
+    } else if (!pollset->called_shutdown && !pollset_has_observers(pollset)) {
       pollset->called_shutdown = 1;
       gpr_mu_unlock(&pollset->mu);
       finish_shutdown(exec_ctx, pollset);
@@ -1098,7 +1103,7 @@
   if (!pollset_has_workers(pollset)) {
     grpc_closure_list_sched(exec_ctx, &pollset->idle_jobs);
   }
-  if (!pollset->called_shutdown && !pollset_has_workers(pollset)) {
+  if (!pollset->called_shutdown && !pollset_has_observers(pollset)) {
     pollset->called_shutdown = 1;
     finish_shutdown(exec_ctx, pollset);
   }
@@ -1126,18 +1131,32 @@
  */
 
 static grpc_pollset_set *pollset_set_create(void) {
-  grpc_pollset_set *pollset_set = gpr_malloc(sizeof(*pollset_set));
-  memset(pollset_set, 0, sizeof(*pollset_set));
+  grpc_pollset_set *pollset_set = gpr_zalloc(sizeof(*pollset_set));
   gpr_mu_init(&pollset_set->mu);
   return pollset_set;
 }
 
-static void pollset_set_destroy(grpc_pollset_set *pollset_set) {
+static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
+                                grpc_pollset_set *pollset_set) {
   size_t i;
   gpr_mu_destroy(&pollset_set->mu);
   for (i = 0; i < pollset_set->fd_count; i++) {
     GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set");
   }
+  for (i = 0; i < pollset_set->pollset_count; i++) {
+    grpc_pollset *pollset = pollset_set->pollsets[i];
+    gpr_mu_lock(&pollset->mu);
+    pollset->pollset_set_count--;
+    /* check shutdown */
+    if (pollset->shutting_down && !pollset->called_shutdown &&
+        !pollset_has_observers(pollset)) {
+      pollset->called_shutdown = 1;
+      gpr_mu_unlock(&pollset->mu);
+      finish_shutdown(exec_ctx, pollset);
+    } else {
+      gpr_mu_unlock(&pollset->mu);
+    }
+  }
   gpr_free(pollset_set->pollsets);
   gpr_free(pollset_set->pollset_sets);
   gpr_free(pollset_set->fds);
@@ -1148,6 +1167,9 @@
                                     grpc_pollset_set *pollset_set,
                                     grpc_pollset *pollset) {
   size_t i, j;
+  gpr_mu_lock(&pollset->mu);
+  pollset->pollset_set_count++;
+  gpr_mu_unlock(&pollset->mu);
   gpr_mu_lock(&pollset_set->mu);
   if (pollset_set->pollset_count == pollset_set->pollset_capacity) {
     pollset_set->pollset_capacity =
@@ -1183,6 +1205,17 @@
     }
   }
   gpr_mu_unlock(&pollset_set->mu);
+  gpr_mu_lock(&pollset->mu);
+  pollset->pollset_set_count--;
+  /* check shutdown */
+  if (pollset->shutting_down && !pollset->called_shutdown &&
+      !pollset_has_observers(pollset)) {
+    pollset->called_shutdown = 1;
+    gpr_mu_unlock(&pollset->mu);
+    finish_shutdown(exec_ctx, pollset);
+  } else {
+    gpr_mu_unlock(&pollset->mu);
+  }
 }
 
 static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
@@ -1509,7 +1542,6 @@
 
     .pollset_init = pollset_init,
     .pollset_shutdown = pollset_shutdown,
-    .pollset_reset = pollset_reset,
     .pollset_destroy = pollset_destroy,
     .pollset_work = pollset_work,
     .pollset_kick = pollset_kick,
diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c
index 2975d61..b5be550 100644
--- a/src/core/lib/iomgr/ev_posix.c
+++ b/src/core/lib/iomgr/ev_posix.c
@@ -52,6 +52,8 @@
  *  tests */
 grpc_poll_function_type grpc_poll_function = poll;
 
+grpc_wakeup_fd grpc_global_wakeup_fd;
+
 static const grpc_event_engine_vtable *g_event_engine;
 static const char *g_poll_strategy_name = NULL;
 
@@ -160,8 +162,8 @@
   g_event_engine->fd_orphan(exec_ctx, fd, on_done, release_fd, reason);
 }
 
-void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
-  g_event_engine->fd_shutdown(exec_ctx, fd);
+void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
+  g_event_engine->fd_shutdown(exec_ctx, fd, why);
 }
 
 bool grpc_fd_is_shutdown(grpc_fd *fd) {
@@ -189,10 +191,6 @@
   g_event_engine->pollset_shutdown(exec_ctx, pollset, closure);
 }
 
-void grpc_pollset_reset(grpc_pollset *pollset) {
-  g_event_engine->pollset_reset(pollset);
-}
-
 void grpc_pollset_destroy(grpc_pollset *pollset) {
   g_event_engine->pollset_destroy(pollset);
 }
@@ -217,8 +215,9 @@
   return g_event_engine->pollset_set_create();
 }
 
-void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {
-  g_event_engine->pollset_set_destroy(pollset_set);
+void grpc_pollset_set_destroy(grpc_exec_ctx *exec_ctx,
+                              grpc_pollset_set *pollset_set) {
+  g_event_engine->pollset_set_destroy(exec_ctx, pollset_set);
 }
 
 void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
index 1068a4b..1a9e5c1 100644
--- a/src/core/lib/iomgr/ev_posix.h
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -51,7 +51,7 @@
   int (*fd_wrapped_fd)(grpc_fd *fd);
   void (*fd_orphan)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
                     int *release_fd, const char *reason);
-  void (*fd_shutdown)(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
+  void (*fd_shutdown)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why);
   void (*fd_notify_on_read)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                             grpc_closure *closure);
   void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
@@ -64,7 +64,6 @@
   void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu);
   void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                            grpc_closure *closure);
-  void (*pollset_reset)(grpc_pollset *pollset);
   void (*pollset_destroy)(grpc_pollset *pollset);
   grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                               grpc_pollset_worker **worker, gpr_timespec now,
@@ -75,7 +74,8 @@
                          struct grpc_fd *fd);
 
   grpc_pollset_set *(*pollset_set_create)(void);
-  void (*pollset_set_destroy)(grpc_pollset_set *pollset_set);
+  void (*pollset_set_destroy)(grpc_exec_ctx *exec_ctx,
+                              grpc_pollset_set *pollset_set);
   void (*pollset_set_add_pollset)(grpc_exec_ctx *exec_ctx,
                                   grpc_pollset_set *pollset_set,
                                   grpc_pollset *pollset);
@@ -140,7 +140,7 @@
 bool grpc_fd_is_shutdown(grpc_fd *fd);
 
 /* Cause any current and future callbacks to fail. */
-void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
+void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why);
 
 /* Register read interest, causing read_cb to be called once when fd becomes
    readable, on deadline specified by deadline, or on shutdown triggered by
diff --git a/src/core/lib/iomgr/exec_ctx.c b/src/core/lib/iomgr/exec_ctx.c
index 6aa788f..83bb436 100644
--- a/src/core/lib/iomgr/exec_ctx.c
+++ b/src/core/lib/iomgr/exec_ctx.c
@@ -42,11 +42,16 @@
 #include "src/core/lib/profiling/timers.h"
 
 bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx) {
-  if (!exec_ctx->cached_ready_to_finish) {
-    exec_ctx->cached_ready_to_finish = exec_ctx->check_ready_to_finish(
-        exec_ctx, exec_ctx->check_ready_to_finish_arg);
+  if ((exec_ctx->flags & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) {
+    if (exec_ctx->check_ready_to_finish(exec_ctx,
+                                        exec_ctx->check_ready_to_finish_arg)) {
+      exec_ctx->flags |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
+      return true;
+    }
+    return false;
+  } else {
+    return true;
   }
-  return exec_ctx->cached_ready_to_finish;
 }
 
 bool grpc_never_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored) {
@@ -82,7 +87,7 @@
 }
 
 void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
-  exec_ctx->cached_ready_to_finish = true;
+  exec_ctx->flags |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
   grpc_exec_ctx_flush(exec_ctx);
 }
 
@@ -101,6 +106,6 @@
 void grpc_exec_ctx_global_shutdown(void) {}
 
 static const grpc_closure_scheduler_vtable exec_ctx_scheduler_vtable = {
-    exec_ctx_run, exec_ctx_sched};
+    exec_ctx_run, exec_ctx_sched, "exec_ctx"};
 static grpc_closure_scheduler exec_ctx_scheduler = {&exec_ctx_scheduler_vtable};
 grpc_closure_scheduler *grpc_schedule_on_exec_ctx = &exec_ctx_scheduler;
diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h
index e566f1b..f99a0fe 100644
--- a/src/core/lib/iomgr/exec_ctx.h
+++ b/src/core/lib/iomgr/exec_ctx.h
@@ -43,6 +43,13 @@
 typedef struct grpc_workqueue grpc_workqueue;
 typedef struct grpc_combiner grpc_combiner;
 
+/* This exec_ctx is ready to return: either pre-populated, or cached as soon as
+   the finish_check returns true */
+#define GRPC_EXEC_CTX_FLAG_IS_FINISHED 1
+/* The exec_ctx's thread is (potentially) owned by a call or channel: care
+   should be given to not delete said call/channel from this exec_ctx */
+#define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP 2
+
 /** Execution context.
  *  A bag of data that collects information along a callstack.
  *  Generally created at public API entry points, and passed down as
@@ -63,36 +70,26 @@
  *  - Instances are always passed as the first argument to a function that
  *    takes it, and always as a pointer (grpc_exec_ctx is never copied).
  */
-#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
 struct grpc_exec_ctx {
   grpc_closure_list closure_list;
   /** currently active combiner: updated only via combiner.c */
   grpc_combiner *active_combiner;
   /** last active combiner in the active combiner list */
   grpc_combiner *last_combiner;
-  bool cached_ready_to_finish;
+  uintptr_t flags;
   void *check_ready_to_finish_arg;
   bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg);
 };
 
 /* initializer for grpc_exec_ctx:
    prefer to use GRPC_EXEC_CTX_INIT whenever possible */
-#define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \
-  { GRPC_CLOSURE_LIST_INIT, NULL, NULL, false, finish_check_arg, finish_check }
-#else
-struct grpc_exec_ctx {
-  bool cached_ready_to_finish;
-  void *check_ready_to_finish_arg;
-  bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg);
-};
-#define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \
-  { false, finish_check_arg, finish_check }
-#endif
+#define GRPC_EXEC_CTX_INITIALIZER(flags, finish_check, finish_check_arg) \
+  { GRPC_CLOSURE_LIST_INIT, NULL, NULL, flags, finish_check_arg, finish_check }
 
 /* initialize an execution context at the top level of an API call into grpc
    (this is safe to use elsewhere, though possibly not as efficient) */
 #define GRPC_EXEC_CTX_INIT \
-  GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(grpc_always_ready_to_finish, NULL)
+  GRPC_EXEC_CTX_INITIALIZER(GRPC_EXEC_CTX_FLAG_IS_FINISHED, NULL, NULL)
 
 extern grpc_closure_scheduler *grpc_schedule_on_exec_ctx;
 
diff --git a/src/core/lib/iomgr/executor.c b/src/core/lib/iomgr/executor.c
index 8527755..a5b62aa 100644
--- a/src/core/lib/iomgr/executor.c
+++ b/src/core/lib/iomgr/executor.c
@@ -158,7 +158,7 @@
   gpr_mu_destroy(&g_executor.mu);
 }
 
-static const grpc_closure_scheduler_vtable executor_vtable = {executor_push,
-                                                              executor_push};
+static const grpc_closure_scheduler_vtable executor_vtable = {
+    executor_push, executor_push, "executor"};
 static grpc_closure_scheduler executor_scheduler = {&executor_vtable};
 grpc_closure_scheduler *grpc_executor_scheduler = &executor_scheduler;
diff --git a/src/core/lib/iomgr/load_file.c b/src/core/lib/iomgr/load_file.c
index 217bc5d..f40c8b2 100644
--- a/src/core/lib/iomgr/load_file.c
+++ b/src/core/lib/iomgr/load_file.c
@@ -47,7 +47,7 @@
                            grpc_slice *output) {
   unsigned char *contents = NULL;
   size_t contents_size = 0;
-  grpc_slice result = gpr_empty_slice();
+  grpc_slice result = grpc_empty_slice();
   FILE *file;
   size_t bytes_read = 0;
   grpc_error *error = GRPC_ERROR_NONE;
diff --git a/src/core/lib/iomgr/network_status_tracker.c b/src/core/lib/iomgr/network_status_tracker.c
index a5ca9ed..4104bf9 100644
--- a/src/core/lib/iomgr/network_status_tracker.c
+++ b/src/core/lib/iomgr/network_status_tracker.c
@@ -31,94 +31,18 @@
  *
  */
 
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
 #include "src/core/lib/iomgr/endpoint.h"
 
-typedef struct endpoint_ll_node {
-  grpc_endpoint *ep;
-  struct endpoint_ll_node *next;
-} endpoint_ll_node;
-
-static endpoint_ll_node *head = NULL;
-static gpr_mu g_endpoint_mutex;
-
-void grpc_network_status_shutdown(void) {
-  if (head != NULL) {
-    gpr_log(GPR_ERROR,
-            "Memory leaked as not all network endpoints were shut down");
-  }
-  gpr_mu_destroy(&g_endpoint_mutex);
-}
+void grpc_network_status_shutdown(void) {}
 
 void grpc_network_status_init(void) {
-  gpr_mu_init(&g_endpoint_mutex);
   // TODO(makarandd): Install callback with OS to monitor network status.
 }
 
-void grpc_destroy_network_status_monitor() {
-  for (endpoint_ll_node *curr = head; curr != NULL;) {
-    endpoint_ll_node *next = curr->next;
-    gpr_free(curr);
-    curr = next;
-  }
-  gpr_mu_destroy(&g_endpoint_mutex);
-}
+void grpc_destroy_network_status_monitor() {}
 
-void grpc_network_status_register_endpoint(grpc_endpoint *ep) {
-  gpr_mu_lock(&g_endpoint_mutex);
-  if (head == NULL) {
-    head = (endpoint_ll_node *)gpr_malloc(sizeof(endpoint_ll_node));
-    head->ep = ep;
-    head->next = NULL;
-  } else {
-    endpoint_ll_node *prev_head = head;
-    head = (endpoint_ll_node *)gpr_malloc(sizeof(endpoint_ll_node));
-    head->ep = ep;
-    head->next = prev_head;
-  }
-  gpr_mu_unlock(&g_endpoint_mutex);
-}
+void grpc_network_status_register_endpoint(grpc_endpoint *ep) { (void)ep; }
 
-void grpc_network_status_unregister_endpoint(grpc_endpoint *ep) {
-  gpr_mu_lock(&g_endpoint_mutex);
-  GPR_ASSERT(head);
-  bool found = false;
-  endpoint_ll_node *prev = head;
-  // if we're unregistering the head, just move head to the next
-  if (ep == head->ep) {
-    head = head->next;
-    gpr_free(prev);
-    found = true;
-  } else {
-    for (endpoint_ll_node *curr = head->next; curr != NULL; curr = curr->next) {
-      if (ep == curr->ep) {
-        prev->next = curr->next;
-        gpr_free(curr);
-        found = true;
-        break;
-      }
-      prev = curr;
-    }
-  }
-  gpr_mu_unlock(&g_endpoint_mutex);
-  GPR_ASSERT(found);
-}
+void grpc_network_status_unregister_endpoint(grpc_endpoint *ep) { (void)ep; }
 
-// Walk the linked-list from head and execute shutdown. It is possible that
-// other threads might be in the process of shutdown as well, but that has
-// no side effect since endpoint shutdown is idempotent.
-void grpc_network_status_shutdown_all_endpoints() {
-  gpr_mu_lock(&g_endpoint_mutex);
-  if (head == NULL) {
-    gpr_mu_unlock(&g_endpoint_mutex);
-    return;
-  }
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  for (endpoint_ll_node *curr = head; curr != NULL; curr = curr->next) {
-    curr->ep->vtable->shutdown(&exec_ctx, curr->ep);
-  }
-  gpr_mu_unlock(&g_endpoint_mutex);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
+void grpc_network_status_shutdown_all_endpoints() {}
diff --git a/src/core/lib/iomgr/pollset.h b/src/core/lib/iomgr/pollset.h
index 8d9edc8..e19ce69 100644
--- a/src/core/lib/iomgr/pollset.h
+++ b/src/core/lib/iomgr/pollset.h
@@ -53,14 +53,12 @@
 typedef struct grpc_pollset_worker grpc_pollset_worker;
 
 size_t grpc_pollset_size(void);
+/* Initialize a pollset: assumes *pollset contains all zeros */
 void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu);
 /* Begin shutting down the pollset, and call closure when done.
  * pollset's mutex must be held */
 void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                            grpc_closure *closure);
-/** Reset the pollset to its initial state (perhaps with some cached objects);
- *  must have been previously shutdown */
-void grpc_pollset_reset(grpc_pollset *pollset);
 void grpc_pollset_destroy(grpc_pollset *pollset);
 
 /* Do some work on a pollset.
diff --git a/src/core/lib/iomgr/pollset_set.h b/src/core/lib/iomgr/pollset_set.h
index 34bb728..d11801d 100644
--- a/src/core/lib/iomgr/pollset_set.h
+++ b/src/core/lib/iomgr/pollset_set.h
@@ -44,7 +44,8 @@
 typedef struct grpc_pollset_set grpc_pollset_set;
 
 grpc_pollset_set *grpc_pollset_set_create(void);
-void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set);
+void grpc_pollset_set_destroy(grpc_exec_ctx *exec_ctx,
+                              grpc_pollset_set *pollset_set);
 void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
                                   grpc_pollset_set *pollset_set,
                                   grpc_pollset *pollset);
diff --git a/src/core/lib/iomgr/pollset_set_uv.c b/src/core/lib/iomgr/pollset_set_uv.c
index e5ef8b2..836cfee 100644
--- a/src/core/lib/iomgr/pollset_set_uv.c
+++ b/src/core/lib/iomgr/pollset_set_uv.c
@@ -41,7 +41,8 @@
   return (grpc_pollset_set*)((intptr_t)0xdeafbeef);
 }
 
-void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {}
+void grpc_pollset_set_destroy(grpc_exec_ctx* exec_ctx,
+                              grpc_pollset_set* pollset_set) {}
 
 void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
                                   grpc_pollset_set* pollset_set,
diff --git a/src/core/lib/iomgr/pollset_set_windows.c b/src/core/lib/iomgr/pollset_set_windows.c
index 645650d..ae18c8a 100644
--- a/src/core/lib/iomgr/pollset_set_windows.c
+++ b/src/core/lib/iomgr/pollset_set_windows.c
@@ -42,7 +42,8 @@
   return (grpc_pollset_set*)((intptr_t)0xdeafbeef);
 }
 
-void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {}
+void grpc_pollset_set_destroy(grpc_exec_ctx* exec_ctx,
+                              grpc_pollset_set* pollset_set) {}
 
 void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
                                   grpc_pollset_set* pollset_set,
diff --git a/src/core/lib/iomgr/pollset_uv.c b/src/core/lib/iomgr/pollset_uv.c
index a39f815..af33949 100644
--- a/src/core/lib/iomgr/pollset_uv.c
+++ b/src/core/lib/iomgr/pollset_uv.c
@@ -82,7 +82,6 @@
 
 void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
   *mu = &grpc_polling_mu;
-  memset(pollset, 0, sizeof(grpc_pollset));
   uv_timer_init(uv_default_loop(), &pollset->timer);
   pollset->shutting_down = 0;
 }
@@ -112,11 +111,6 @@
   }
 }
 
-void grpc_pollset_reset(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->shutting_down);
-  pollset->shutting_down = 0;
-}
-
 static void timer_run_cb(uv_timer_t *timer) {}
 
 grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
diff --git a/src/core/lib/iomgr/pollset_windows.c b/src/core/lib/iomgr/pollset_windows.c
index 2a45e70..17043c1 100644
--- a/src/core/lib/iomgr/pollset_windows.c
+++ b/src/core/lib/iomgr/pollset_windows.c
@@ -98,7 +98,6 @@
 
 void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
   *mu = &grpc_polling_mu;
-  memset(pollset, 0, sizeof(*pollset));
   pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
       pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
           &pollset->root_worker;
@@ -117,16 +116,6 @@
 
 void grpc_pollset_destroy(grpc_pollset *pollset) {}
 
-void grpc_pollset_reset(grpc_pollset *pollset) {
-  GPR_ASSERT(pollset->shutting_down);
-  GPR_ASSERT(
-      !has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
-  pollset->shutting_down = 0;
-  pollset->is_iocp_worker = 0;
-  pollset->kicked_without_pollers = 0;
-  pollset->on_shutdown = NULL;
-}
-
 grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                               grpc_pollset_worker **worker_hdl,
                               gpr_timespec now, gpr_timespec deadline) {
diff --git a/src/core/lib/iomgr/resource_quota.c b/src/core/lib/iomgr/resource_quota.c
index 31590cd..511ffdc 100644
--- a/src/core/lib/iomgr/resource_quota.c
+++ b/src/core/lib/iomgr/resource_quota.c
@@ -33,6 +33,8 @@
 
 #include "src/core/lib/iomgr/resource_quota.h"
 
+#include <limits.h>
+#include <stdint.h>
 #include <string.h>
 
 #include <grpc/support/alloc.h>
@@ -44,6 +46,8 @@
 
 int grpc_resource_quota_trace = 0;
 
+#define MEMORY_USAGE_ESTIMATION_MAX 65536
+
 /* Internal linked list pointers for a resource user */
 typedef struct {
   grpc_resource_user *next;
@@ -126,9 +130,12 @@
   /* refcount */
   gpr_refcount refs;
 
+  /* estimate of current memory usage
+     scaled to the range [0..RESOURCE_USAGE_ESTIMATION_MAX] */
+  gpr_atm memory_usage_estimation;
+
   /* Master combiner lock: all activity on a quota executes under this combiner
-   * (so no mutex is needed for this data structure)
-   */
+   * (so no mutex is needed for this data structure) */
   grpc_combiner *combiner;
   /* Size of the resource quota */
   int64_t size;
@@ -269,6 +276,16 @@
                      GRPC_ERROR_NONE);
 }
 
+/* update the atomically available resource estimate - use no barriers since
+   timeliness of delivery really doesn't matter much */
+static void rq_update_estimate(grpc_resource_quota *resource_quota) {
+  gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation,
+                           (gpr_atm)((1.0 -
+                                      ((double)resource_quota->free_pool) /
+                                          ((double)resource_quota->size)) *
+                                     MEMORY_USAGE_ESTIMATION_MAX));
+}
+
 /* returns true if all allocations are completed */
 static bool rq_alloc(grpc_exec_ctx *exec_ctx,
                      grpc_resource_quota *resource_quota) {
@@ -281,6 +298,7 @@
       int64_t amt = -resource_user->free_pool;
       resource_user->free_pool = 0;
       resource_quota->free_pool -= amt;
+      rq_update_estimate(resource_quota);
       if (grpc_resource_quota_trace) {
         gpr_log(GPR_DEBUG, "RQ %s %s: grant alloc %" PRId64
                            " bytes; rq_free_pool -> %" PRId64,
@@ -315,6 +333,7 @@
       int64_t amt = resource_user->free_pool;
       resource_user->free_pool = 0;
       resource_quota->free_pool += amt;
+      rq_update_estimate(resource_quota);
       if (grpc_resource_quota_trace) {
         gpr_log(GPR_DEBUG, "RQ %s %s: reclaim_from_per_user_free_pool %" PRId64
                            " bytes; rq_free_pool -> %" PRId64,
@@ -378,11 +397,15 @@
   }
 }
 
+static const grpc_slice_refcount_vtable ru_slice_vtable = {
+    ru_slice_ref, ru_slice_unref, grpc_slice_default_eq_impl,
+    grpc_slice_default_hash_impl};
+
 static grpc_slice ru_slice_create(grpc_resource_user *resource_user,
                                   size_t size) {
   ru_slice_refcount *rc = gpr_malloc(sizeof(ru_slice_refcount) + size);
-  rc->base.ref = ru_slice_ref;
-  rc->base.unref = ru_slice_unref;
+  rc->base.vtable = &ru_slice_vtable;
+  rc->base.sub_refcount = &rc->base;
   gpr_ref_init(&rc->refs, 1);
   rc->resource_user = resource_user;
   rc->size = size;
@@ -527,6 +550,7 @@
   int64_t delta = a->size - a->resource_quota->size;
   a->resource_quota->size += delta;
   a->resource_quota->free_pool += delta;
+  rq_update_estimate(a->resource_quota);
   rq_step_sched(exec_ctx, a->resource_quota);
   grpc_resource_quota_unref_internal(exec_ctx, a->resource_quota);
   gpr_free(a);
@@ -553,6 +577,7 @@
   resource_quota->size = INT64_MAX;
   resource_quota->step_scheduled = false;
   resource_quota->reclaiming = false;
+  gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, 0);
   if (name != NULL) {
     resource_quota->name = gpr_strdup(name);
   } else {
@@ -574,7 +599,7 @@
 void grpc_resource_quota_unref_internal(grpc_exec_ctx *exec_ctx,
                                         grpc_resource_quota *resource_quota) {
   if (gpr_unref(&resource_quota->refs)) {
-    grpc_combiner_destroy(exec_ctx, resource_quota->combiner);
+    GRPC_COMBINER_UNREF(exec_ctx, resource_quota->combiner, "resource_quota");
     gpr_free(resource_quota->name);
     gpr_free(resource_quota);
   }
@@ -598,6 +623,13 @@
   grpc_resource_quota_ref_internal(resource_quota);
 }
 
+double grpc_resource_quota_get_memory_pressure(
+    grpc_resource_quota *resource_quota) {
+  return ((double)(gpr_atm_no_barrier_load(
+             &resource_quota->memory_usage_estimation))) /
+         ((double)MEMORY_USAGE_ESTIMATION_MAX);
+}
+
 /* Public API */
 void grpc_resource_quota_resize(grpc_resource_quota *resource_quota,
                                 size_t size) {
@@ -804,12 +836,10 @@
 void grpc_resource_user_slice_allocator_init(
     grpc_resource_user_slice_allocator *slice_allocator,
     grpc_resource_user *resource_user, grpc_iomgr_cb_func cb, void *p) {
-  grpc_closure_init(
-      &slice_allocator->on_allocated, ru_allocated_slices, slice_allocator,
-      grpc_combiner_scheduler(resource_user->resource_quota->combiner, false));
-  grpc_closure_init(
-      &slice_allocator->on_done, cb, p,
-      grpc_combiner_scheduler(resource_user->resource_quota->combiner, false));
+  grpc_closure_init(&slice_allocator->on_allocated, ru_allocated_slices,
+                    slice_allocator, grpc_schedule_on_exec_ctx);
+  grpc_closure_init(&slice_allocator->on_done, cb, p,
+                    grpc_schedule_on_exec_ctx);
   slice_allocator->resource_user = resource_user;
 }
 
diff --git a/src/core/lib/iomgr/resource_quota.h b/src/core/lib/iomgr/resource_quota.h
index d1127ce..b9f62cb 100644
--- a/src/core/lib/iomgr/resource_quota.h
+++ b/src/core/lib/iomgr/resource_quota.h
@@ -84,6 +84,12 @@
 grpc_resource_quota *grpc_resource_quota_from_channel_args(
     const grpc_channel_args *channel_args);
 
+/* Return a number indicating current memory pressure:
+   0.0 ==> no memory usage
+   1.0 ==> maximum memory usage */
+double grpc_resource_quota_get_memory_pressure(
+    grpc_resource_quota *resource_quota);
+
 typedef struct grpc_resource_user grpc_resource_user;
 
 grpc_resource_user *grpc_resource_user_create(
diff --git a/src/core/lib/iomgr/sockaddr_utils.c b/src/core/lib/iomgr/sockaddr_utils.c
index 44bc2f9..ffa62cb 100644
--- a/src/core/lib/iomgr/sockaddr_utils.c
+++ b/src/core/lib/iomgr/sockaddr_utils.c
@@ -190,31 +190,37 @@
 }
 
 char *grpc_sockaddr_to_uri(const grpc_resolved_address *resolved_addr) {
-  char *temp;
-  char *result;
   grpc_resolved_address addr_normalized;
-  const struct sockaddr *addr;
-
   if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
     resolved_addr = &addr_normalized;
   }
+  const char *scheme = grpc_sockaddr_get_uri_scheme(resolved_addr);
+  if (scheme == NULL || strcmp("unix", scheme) == 0) {
+    return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
+  }
+  char *path = NULL;
+  char *uri_str = NULL;
+  if (grpc_sockaddr_to_string(&path, resolved_addr,
+                              false /* suppress errors */) &&
+      scheme != NULL) {
+    gpr_asprintf(&uri_str, "%s:%s", scheme, path);
+  }
+  gpr_free(path);
+  return uri_str != NULL ? uri_str : NULL;
+}
 
-  addr = (const struct sockaddr *)resolved_addr->addr;
-
+const char *grpc_sockaddr_get_uri_scheme(
+    const grpc_resolved_address *resolved_addr) {
+  const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
   switch (addr->sa_family) {
     case AF_INET:
-      grpc_sockaddr_to_string(&temp, resolved_addr, 0);
-      gpr_asprintf(&result, "ipv4:%s", temp);
-      gpr_free(temp);
-      return result;
+      return "ipv4";
     case AF_INET6:
-      grpc_sockaddr_to_string(&temp, resolved_addr, 0);
-      gpr_asprintf(&result, "ipv6:%s", temp);
-      gpr_free(temp);
-      return result;
-    default:
-      return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
+      return "ipv6";
+    case AF_UNIX:
+      return "unix";
   }
+  return NULL;
 }
 
 int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) {
diff --git a/src/core/lib/iomgr/sockaddr_utils.h b/src/core/lib/iomgr/sockaddr_utils.h
index 5371e36..2b22f11 100644
--- a/src/core/lib/iomgr/sockaddr_utils.h
+++ b/src/core/lib/iomgr/sockaddr_utils.h
@@ -84,6 +84,10 @@
 int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr,
                             int normalize);
 
+/* Returns the URI string corresponding to \a addr */
 char *grpc_sockaddr_to_uri(const grpc_resolved_address *addr);
 
+/* Returns the URI scheme corresponding to \a addr */
+const char *grpc_sockaddr_get_uri_scheme(const grpc_resolved_address *addr);
+
 #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */
diff --git a/src/core/lib/iomgr/tcp_client_posix.c b/src/core/lib/iomgr/tcp_client_posix.c
index 9a77c92..0144192 100644
--- a/src/core/lib/iomgr/tcp_client_posix.c
+++ b/src/core/lib/iomgr/tcp_client_posix.c
@@ -118,11 +118,11 @@
     const char *str = grpc_error_string(error);
     gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
             str);
-    grpc_error_free_string(str);
   }
   gpr_mu_lock(&ac->mu);
   if (ac->fd != NULL) {
-    grpc_fd_shutdown(exec_ctx, ac->fd);
+    grpc_fd_shutdown(exec_ctx, ac->fd,
+                     GRPC_ERROR_CREATE("connect() timed out"));
   }
   done = (--ac->refs == 0);
   gpr_mu_unlock(&ac->mu);
@@ -178,7 +178,6 @@
     const char *str = grpc_error_string(error);
     gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
             ac->addr_str, str);
-    grpc_error_free_string(str);
   }
 
   gpr_mu_lock(&ac->mu);
diff --git a/src/core/lib/iomgr/tcp_client_uv.c b/src/core/lib/iomgr/tcp_client_uv.c
index 3de0795..ae66577 100644
--- a/src/core/lib/iomgr/tcp_client_uv.c
+++ b/src/core/lib/iomgr/tcp_client_uv.c
@@ -144,8 +144,7 @@
     }
   }
 
-  connect = gpr_malloc(sizeof(grpc_uv_tcp_connect));
-  memset(connect, 0, sizeof(grpc_uv_tcp_connect));
+  connect = gpr_zalloc(sizeof(grpc_uv_tcp_connect));
   connect->closure = closure;
   connect->endpoint = ep;
   connect->tcp_handle = gpr_malloc(sizeof(uv_tcp_t));
diff --git a/src/core/lib/iomgr/tcp_client_windows.c b/src/core/lib/iomgr/tcp_client_windows.c
index 1e84ec3..c8dc9e6 100644
--- a/src/core/lib/iomgr/tcp_client_windows.c
+++ b/src/core/lib/iomgr/tcp_client_windows.c
@@ -135,12 +135,10 @@
 
 /* Tries to issue one async connection, then schedules both an IOCP
    notification request for the connection, and one timeout alert. */
-void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
-                             grpc_endpoint **endpoint,
-                             grpc_pollset_set *interested_parties,
-                             const grpc_channel_args *channel_args,
-                             const grpc_resolved_address *addr,
-                             gpr_timespec deadline) {
+static void tcp_client_connect_impl(
+    grpc_exec_ctx *exec_ctx, grpc_closure *on_done, grpc_endpoint **endpoint,
+    grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
+    const grpc_resolved_address *addr, gpr_timespec deadline) {
   SOCKET sock = INVALID_SOCKET;
   BOOL success;
   int status;
@@ -252,4 +250,21 @@
   grpc_closure_sched(exec_ctx, on_done, final_error);
 }
 
+// overridden by api_fuzzer.c
+void (*grpc_tcp_client_connect_impl)(
+    grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
+    grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
+    const grpc_resolved_address *addr,
+    gpr_timespec deadline) = tcp_client_connect_impl;
+
+void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
+                             grpc_endpoint **ep,
+                             grpc_pollset_set *interested_parties,
+                             const grpc_channel_args *channel_args,
+                             const grpc_resolved_address *addr,
+                             gpr_timespec deadline) {
+  grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties,
+                               channel_args, addr, deadline);
+}
+
 #endif /* GRPC_WINSOCK_SOCKET */
diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c
index ece4497..a4381f8 100644
--- a/src/core/lib/iomgr/tcp_posix.c
+++ b/src/core/lib/iomgr/tcp_posix.c
@@ -119,9 +119,10 @@
 static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
                              grpc_error *error);
 
-static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                         grpc_error *why) {
   grpc_tcp *tcp = (grpc_tcp *)ep;
-  grpc_fd_shutdown(exec_ctx, tcp->em_fd);
+  grpc_fd_shutdown(exec_ctx, tcp->em_fd, why);
   grpc_resource_user_shutdown(exec_ctx, tcp->resource_user);
 }
 
@@ -181,7 +182,7 @@
     size_t i;
     const char *str = grpc_error_string(error);
     gpr_log(GPR_DEBUG, "read: error=%s", str);
-    grpc_error_free_string(str);
+
     for (i = 0; i < tcp->incoming_buffer->count; i++) {
       char *dump = grpc_dump_slice(tcp->incoming_buffer->slices[i],
                                    GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -435,7 +436,6 @@
     if (grpc_tcp_trace) {
       const char *str = grpc_error_string(error);
       gpr_log(GPR_DEBUG, "write: %s", str);
-      grpc_error_free_string(str);
     }
 
     grpc_closure_run(exec_ctx, cb, error);
@@ -485,7 +485,6 @@
     if (grpc_tcp_trace) {
       const char *str = grpc_error_string(error);
       gpr_log(GPR_DEBUG, "write: %s", str);
-      grpc_error_free_string(str);
     }
     grpc_closure_sched(exec_ctx, cb, error);
   }
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index 20efb67..36f878f 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -44,6 +44,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <ifaddrs.h>
 #include <limits.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -115,6 +116,8 @@
   bool shutdown;
   /* use SO_REUSEPORT */
   bool so_reuseport;
+  /* expand wildcard addresses to a list of all local addresses */
+  bool expand_wildcard_addrs;
 
   /* linked list of server ports */
   grpc_tcp_listener *head;
@@ -161,6 +164,7 @@
   grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
   s->so_reuseport = has_so_reuseport;
   s->resource_quota = grpc_resource_quota_create(NULL);
+  s->expand_wildcard_addrs = false;
   for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
     if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) {
       if (args->args[i].type == GRPC_ARG_INTEGER) {
@@ -183,6 +187,15 @@
         return GRPC_ERROR_CREATE(GRPC_ARG_RESOURCE_QUOTA
                                  " must be a pointer to a buffer pool");
       }
+    } else if (0 == strcmp(GRPC_ARG_EXPAND_WILDCARD_ADDRS, args->args[i].key)) {
+      if (args->args[i].type == GRPC_ARG_INTEGER) {
+        s->expand_wildcard_addrs = (args->args[i].value.integer != 0);
+      } else {
+        grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
+        gpr_free(s);
+        return GRPC_ERROR_CREATE(GRPC_ARG_EXPAND_WILDCARD_ADDRS
+                                 " must be an integer");
+      }
     }
   }
   gpr_ref_init(&s->refs, 1);
@@ -276,7 +289,8 @@
   if (s->active_ports) {
     grpc_tcp_listener *sp;
     for (sp = s->head; sp; sp = sp->next) {
-      grpc_fd_shutdown(exec_ctx, sp->emfd);
+      grpc_fd_shutdown(exec_ctx, sp->emfd,
+                       GRPC_ERROR_CREATE("Server destroyed"));
     }
     gpr_mu_unlock(&s->mu);
   } else {
@@ -503,9 +517,224 @@
   return err;
 }
 
-/* Insert count new listeners after listener. Every new listener will have the
-   same listen address as listener (SO_REUSEPORT must be enabled). Every new
-   listener is a sibling of listener. */
+/* If successful, add a listener to s for addr, set *dsmode for the socket, and
+   return the *listener. */
+static grpc_error *add_addr_to_server(grpc_tcp_server *s,
+                                      const grpc_resolved_address *addr,
+                                      unsigned port_index, unsigned fd_index,
+                                      grpc_dualstack_mode *dsmode,
+                                      grpc_tcp_listener **listener) {
+  grpc_resolved_address addr4_copy;
+  int fd;
+  grpc_error *err =
+      grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd);
+  if (err != GRPC_ERROR_NONE) {
+    return err;
+  }
+  if (*dsmode == GRPC_DSMODE_IPV4 &&
+      grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
+    addr = &addr4_copy;
+  }
+  return add_socket_to_server(s, fd, addr, port_index, fd_index, listener);
+}
+
+/* Bind to "::" to get a port number not used by any address. */
+static grpc_error *get_unused_port(int *port) {
+  grpc_resolved_address wild;
+  grpc_sockaddr_make_wildcard6(0, &wild);
+  grpc_dualstack_mode dsmode;
+  int fd;
+  grpc_error *err =
+      grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd);
+  if (err != GRPC_ERROR_NONE) {
+    return err;
+  }
+  if (dsmode == GRPC_DSMODE_IPV4) {
+    grpc_sockaddr_make_wildcard4(0, &wild);
+  }
+  if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) {
+    err = GRPC_OS_ERROR(errno, "bind");
+    close(fd);
+    return err;
+  }
+  if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) !=
+      0) {
+    err = GRPC_OS_ERROR(errno, "getsockname");
+    close(fd);
+    return err;
+  }
+  close(fd);
+  *port = grpc_sockaddr_get_port(&wild);
+  return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE;
+}
+
+/* Return the listener in s with address addr or NULL. */
+static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s,
+                                                  grpc_resolved_address *addr) {
+  grpc_tcp_listener *l;
+  gpr_mu_lock(&s->mu);
+  for (l = s->head; l != NULL; l = l->next) {
+    if (l->addr.len != addr->len) {
+      continue;
+    }
+    if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) {
+      break;
+    }
+  }
+  gpr_mu_unlock(&s->mu);
+  return l;
+}
+
+/* Get all addresses assigned to network interfaces on the machine and create a
+   listener for each. requested_port is the port to use for every listener, or 0
+   to select one random port that will be used for every listener. Set *out_port
+   to the port selected. Return GRPC_ERROR_NONE only if all listeners were
+   added. */
+static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s,
+                                                 unsigned port_index,
+                                                 int requested_port,
+                                                 int *out_port) {
+  struct ifaddrs *ifa = NULL;
+  struct ifaddrs *ifa_it;
+  unsigned fd_index = 0;
+  grpc_tcp_listener *sp = NULL;
+  grpc_error *err = GRPC_ERROR_NONE;
+  if (requested_port == 0) {
+    /* Note: There could be a race where some local addrs can listen on the
+       selected port and some can't. The sane way to handle this would be to
+       retry by recreating the whole grpc_tcp_server. Backing out individual
+       listeners and orphaning the FDs looks like too much trouble. */
+    if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) {
+      return err;
+    } else if (requested_port <= 0) {
+      return GRPC_ERROR_CREATE("Bad get_unused_port()");
+    }
+    gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port);
+  }
+  if (getifaddrs(&ifa) != 0 || ifa == NULL) {
+    return GRPC_OS_ERROR(errno, "getifaddrs");
+  }
+  for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) {
+    grpc_resolved_address addr;
+    char *addr_str = NULL;
+    grpc_dualstack_mode dsmode;
+    grpc_tcp_listener *new_sp = NULL;
+    const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>");
+    if (ifa_it->ifa_addr == NULL) {
+      continue;
+    } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
+      addr.len = sizeof(struct sockaddr_in);
+    } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
+      addr.len = sizeof(struct sockaddr_in6);
+    } else {
+      continue;
+    }
+    memcpy(addr.addr, ifa_it->ifa_addr, addr.len);
+    if (!grpc_sockaddr_set_port(&addr, requested_port)) {
+      /* Should never happen, because we check sa_family above. */
+      err = GRPC_ERROR_CREATE("Failed to set port");
+      break;
+    }
+    if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) {
+      addr_str = gpr_strdup("<error>");
+    }
+    gpr_log(GPR_DEBUG,
+            "Adding local addr from interface %s flags 0x%x to server: %s",
+            ifa_name, ifa_it->ifa_flags, addr_str);
+    /* We could have multiple interfaces with the same address (e.g., bonding),
+       so look for duplicates. */
+    if (find_listener_with_addr(s, &addr) != NULL) {
+      gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str,
+              ifa_name);
+      gpr_free(addr_str);
+      continue;
+    }
+    if ((err = add_addr_to_server(s, &addr, port_index, fd_index, &dsmode,
+                                  &new_sp)) != GRPC_ERROR_NONE) {
+      char *err_str = NULL;
+      grpc_error *root_err;
+      if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) {
+        err_str = gpr_strdup("Failed to add listener");
+      }
+      root_err = GRPC_ERROR_CREATE(err_str);
+      gpr_free(err_str);
+      gpr_free(addr_str);
+      err = grpc_error_add_child(root_err, err);
+      break;
+    } else {
+      GPR_ASSERT(requested_port == new_sp->port);
+      ++fd_index;
+      if (sp != NULL) {
+        new_sp->is_sibling = 1;
+        sp->sibling = new_sp;
+      }
+      sp = new_sp;
+    }
+    gpr_free(addr_str);
+  }
+  freeifaddrs(ifa);
+  if (err != GRPC_ERROR_NONE) {
+    return err;
+  } else if (sp == NULL) {
+    return GRPC_ERROR_CREATE("No local addresses");
+  } else {
+    *out_port = sp->port;
+    return GRPC_ERROR_NONE;
+  }
+}
+
+/* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
+static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s,
+                                                unsigned port_index,
+                                                int requested_port,
+                                                int *out_port) {
+  grpc_resolved_address wild4;
+  grpc_resolved_address wild6;
+  unsigned fd_index = 0;
+  grpc_dualstack_mode dsmode;
+  grpc_tcp_listener *sp = NULL;
+  grpc_tcp_listener *sp2 = NULL;
+  grpc_error *v6_err = GRPC_ERROR_NONE;
+  grpc_error *v4_err = GRPC_ERROR_NONE;
+  *out_port = -1;
+  if (s->expand_wildcard_addrs) {
+    return add_all_local_addrs_to_server(s, port_index, requested_port,
+                                         out_port);
+  }
+  grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6);
+  /* Try listening on IPv6 first. */
+  if ((v6_err = add_addr_to_server(s, &wild6, port_index, fd_index, &dsmode,
+                                   &sp)) == GRPC_ERROR_NONE) {
+    ++fd_index;
+    requested_port = *out_port = sp->port;
+    if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) {
+      return GRPC_ERROR_NONE;
+    }
+  }
+  /* If we got a v6-only socket or nothing, try adding 0.0.0.0. */
+  grpc_sockaddr_set_port(&wild4, requested_port);
+  if ((v4_err = add_addr_to_server(s, &wild4, port_index, fd_index, &dsmode,
+                                   &sp2)) == GRPC_ERROR_NONE) {
+    *out_port = sp2->port;
+    if (sp != NULL) {
+      sp2->is_sibling = 1;
+      sp->sibling = sp2;
+    }
+  }
+  if (*out_port > 0) {
+    GRPC_LOG_IF_ERROR("Failed to add :: listener", v6_err);
+    GRPC_LOG_IF_ERROR("Failed to add 0.0.0.0 listener", v4_err);
+    return GRPC_ERROR_NONE;
+  } else {
+    grpc_error *root_err =
+        GRPC_ERROR_CREATE("Failed to add any wildcard listeners");
+    GPR_ASSERT(v6_err != GRPC_ERROR_NONE && v4_err != GRPC_ERROR_NONE);
+    root_err = grpc_error_add_child(root_err, v6_err);
+    root_err = grpc_error_add_child(root_err, v4_err);
+    return root_err;
+  }
+}
+
 static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
   grpc_tcp_listener *sp = NULL;
   char *addr_str;
@@ -558,19 +787,13 @@
                                      const grpc_resolved_address *addr,
                                      int *out_port) {
   grpc_tcp_listener *sp;
-  grpc_tcp_listener *sp2 = NULL;
-  int fd;
-  grpc_dualstack_mode dsmode;
-  grpc_resolved_address addr6_v4mapped;
-  grpc_resolved_address wild4;
-  grpc_resolved_address wild6;
-  grpc_resolved_address addr4_copy;
-  grpc_resolved_address *allocated_addr = NULL;
   grpc_resolved_address sockname_temp;
-  int port;
+  grpc_resolved_address addr6_v4mapped;
+  int requested_port = grpc_sockaddr_get_port(addr);
   unsigned port_index = 0;
-  unsigned fd_index = 0;
-  grpc_error *errs[2] = {GRPC_ERROR_NONE, GRPC_ERROR_NONE};
+  grpc_dualstack_mode dsmode;
+  grpc_error *err;
+  *out_port = -1;
   if (s->tail != NULL) {
     port_index = s->tail->port_index + 1;
   }
@@ -578,85 +801,34 @@
 
   /* Check if this is a wildcard port, and if so, try to keep the port the same
      as some previously created listener. */
-  if (grpc_sockaddr_get_port(addr) == 0) {
+  if (requested_port == 0) {
     for (sp = s->head; sp; sp = sp->next) {
       sockname_temp.len = sizeof(struct sockaddr_storage);
-      if (0 == getsockname(sp->fd, (struct sockaddr *)sockname_temp.addr,
+      if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp.addr,
                            (socklen_t *)&sockname_temp.len)) {
-        port = grpc_sockaddr_get_port(&sockname_temp);
-        if (port > 0) {
-          allocated_addr = gpr_malloc(sizeof(grpc_resolved_address));
-          memcpy(allocated_addr, addr, addr->len);
-          grpc_sockaddr_set_port(allocated_addr, port);
-          addr = allocated_addr;
+        int used_port = grpc_sockaddr_get_port(&sockname_temp);
+        if (used_port > 0) {
+          memcpy(&sockname_temp, addr, sizeof(grpc_resolved_address));
+          grpc_sockaddr_set_port(&sockname_temp, used_port);
+          requested_port = used_port;
+          addr = &sockname_temp;
           break;
         }
       }
     }
   }
-
-  sp = NULL;
-
+  if (grpc_sockaddr_is_wildcard(addr, &requested_port)) {
+    return add_wildcard_addrs_to_server(s, port_index, requested_port,
+                                        out_port);
+  }
   if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
     addr = &addr6_v4mapped;
   }
-
-  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
-  if (grpc_sockaddr_is_wildcard(addr, &port)) {
-    grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
-
-    /* Try listening on IPv6 first. */
-    addr = &wild6;
-    errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
-    if (errs[0] == GRPC_ERROR_NONE) {
-      errs[0] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
-      if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
-        goto done;
-      }
-      if (sp != NULL) {
-        ++fd_index;
-      }
-      /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
-      if (port == 0 && sp != NULL) {
-        grpc_sockaddr_set_port(&wild4, sp->port);
-      }
-    }
-    addr = &wild4;
-  }
-
-  errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
-  if (errs[1] == GRPC_ERROR_NONE) {
-    if (dsmode == GRPC_DSMODE_IPV4 &&
-        grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
-      addr = &addr4_copy;
-    }
-    sp2 = sp;
-    errs[1] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
-    if (sp2 != NULL && sp != NULL) {
-      sp2->sibling = sp;
-      sp->is_sibling = 1;
-    }
-  }
-
-done:
-  gpr_free(allocated_addr);
-  if (sp != NULL) {
+  if ((err = add_addr_to_server(s, addr, port_index, 0, &dsmode, &sp)) ==
+      GRPC_ERROR_NONE) {
     *out_port = sp->port;
-    GRPC_ERROR_UNREF(errs[0]);
-    GRPC_ERROR_UNREF(errs[1]);
-    return GRPC_ERROR_NONE;
-  } else {
-    *out_port = -1;
-    char *addr_str = grpc_sockaddr_to_uri(addr);
-    grpc_error *err = grpc_error_set_str(
-        GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", errs,
-                                      GPR_ARRAY_SIZE(errs)),
-        GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
-    GRPC_ERROR_UNREF(errs[0]);
-    GRPC_ERROR_UNREF(errs[1]);
-    gpr_free(addr_str);
-    return err;
   }
+  return err;
 }
 
 /* Return listener at port_index or NULL. Should only be called with s->mu
@@ -773,7 +945,8 @@
   if (s->active_ports) {
     grpc_tcp_listener *sp;
     for (sp = s->head; sp; sp = sp->next) {
-      grpc_fd_shutdown(exec_ctx, sp->emfd);
+      grpc_fd_shutdown(exec_ctx, sp->emfd,
+                       GRPC_ERROR_CREATE("Server shutdown"));
     }
   }
   gpr_mu_unlock(&s->mu);
diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c
index dafe851..bd4b9b2 100644
--- a/src/core/lib/iomgr/tcp_server_windows.c
+++ b/src/core/lib/iomgr/tcp_server_windows.c
@@ -343,7 +343,7 @@
   if (error != GRPC_ERROR_NONE) {
     const char *msg = grpc_error_string(error);
     gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg);
-    grpc_error_free_string(msg);
+
     gpr_mu_unlock(&sp->server->mu);
     return;
   }
diff --git a/src/core/lib/iomgr/tcp_uv.c b/src/core/lib/iomgr/tcp_uv.c
index 7295563..5541c62 100644
--- a/src/core/lib/iomgr/tcp_uv.c
+++ b/src/core/lib/iomgr/tcp_uv.c
@@ -162,7 +162,7 @@
       size_t i;
       const char *str = grpc_error_string(error);
       gpr_log(GPR_DEBUG, "read: error=%s", str);
-      grpc_error_free_string(str);
+
       for (i = 0; i < tcp->read_slices->count; i++) {
         char *dump = grpc_dump_slice(tcp->read_slices->slices[i],
                                      GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -303,13 +303,15 @@
 
 static void shutdown_callback(uv_shutdown_t *req, int status) {}
 
-static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                 grpc_error *why) {
   grpc_tcp *tcp = (grpc_tcp *)ep;
   if (!tcp->shutting_down) {
     tcp->shutting_down = true;
     uv_shutdown_t *req = &tcp->shutdown_req;
     uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback);
   }
+  GRPC_ERROR_UNREF(why);
 }
 
 static void uv_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
diff --git a/src/core/lib/iomgr/tcp_windows.c b/src/core/lib/iomgr/tcp_windows.c
index 84f791b..6c41397 100644
--- a/src/core/lib/iomgr/tcp_windows.c
+++ b/src/core/lib/iomgr/tcp_windows.c
@@ -116,6 +116,7 @@
      to protect ourselves when requesting a shutdown. */
   gpr_mu mu;
   int shutting_down;
+  grpc_error *shutdown_error;
 
   char *peer_string;
 } grpc_tcp;
@@ -125,6 +126,7 @@
   gpr_mu_destroy(&tcp->mu);
   gpr_free(tcp->peer_string);
   grpc_resource_user_unref(exec_ctx, tcp->resource_user);
+  if (tcp->shutting_down) GRPC_ERROR_UNREF(tcp->shutdown_error);
   gpr_free(tcp);
 }
 
@@ -182,7 +184,10 @@
         grpc_slice_buffer_add(tcp->read_slices, sub);
       } else {
         grpc_slice_unref_internal(exec_ctx, tcp->read_slice);
-        error = GRPC_ERROR_CREATE("End of TCP stream");
+        error = tcp->shutting_down
+                    ? GRPC_ERROR_CREATE_REFERENCING("TCP stream shutting down",
+                                                    &tcp->shutdown_error, 1)
+                    : GRPC_ERROR_CREATE("End of TCP stream");
       }
     }
   }
@@ -203,8 +208,9 @@
   WSABUF buffer;
 
   if (tcp->shutting_down) {
-    grpc_closure_sched(exec_ctx, cb,
-                       GRPC_ERROR_CREATE("TCP socket is shutting down"));
+    grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_CREATE_REFERENCING(
+                                         "TCP socket is shutting down",
+                                         &tcp->shutdown_error, 1));
     return;
   }
 
@@ -291,8 +297,9 @@
   size_t len;
 
   if (tcp->shutting_down) {
-    grpc_closure_sched(exec_ctx, cb,
-                       GRPC_ERROR_CREATE("TCP socket is shutting down"));
+    grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_CREATE_REFERENCING(
+                                         "TCP socket is shutting down",
+                                         &tcp->shutdown_error, 1));
     return;
   }
 
@@ -373,12 +380,18 @@
    we're not going to protect against these. However the IO Completion Port
    callback will happen from another thread, so we need to protect against
    concurrent access of the data structure in that regard. */
-static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                         grpc_error *why) {
   grpc_tcp *tcp = (grpc_tcp *)ep;
   gpr_mu_lock(&tcp->mu);
   /* At that point, what may happen is that we're already inside the IOCP
      callback. See the comments in on_read and on_write. */
-  tcp->shutting_down = 1;
+  if (!tcp->shutting_down) {
+    tcp->shutting_down = 1;
+    tcp->shutdown_error = why;
+  } else {
+    GRPC_ERROR_UNREF(why);
+  }
   grpc_winsocket_shutdown(tcp->socket);
   gpr_mu_unlock(&tcp->mu);
   grpc_resource_user_shutdown(exec_ctx, tcp->resource_user);
diff --git a/src/core/lib/iomgr/timer_generic.c b/src/core/lib/iomgr/timer_generic.c
index 40c8351..d4df96c 100644
--- a/src/core/lib/iomgr/timer_generic.c
+++ b/src/core/lib/iomgr/timer_generic.c
@@ -42,6 +42,7 @@
 #include <grpc/support/useful.h>
 #include "src/core/lib/iomgr/time_averaged_stats.h"
 #include "src/core/lib/iomgr/timer_heap.h"
+#include "src/core/lib/support/spinlock.h"
 
 #define INVALID_HEAP_INDEX 0xffffffffu
 
@@ -69,7 +70,7 @@
 /* Protects g_shard_queue */
 static gpr_mu g_mu;
 /* Allow only one run_some_expired_timers at once */
-static gpr_mu g_checker_mu;
+static gpr_spinlock g_checker_mu = GPR_SPINLOCK_STATIC_INITIALIZER;
 static gpr_clock_type g_clock_type;
 static shard_type g_shards[NUM_SHARDS];
 /* Protected by g_mu */
@@ -90,7 +91,6 @@
 
   g_initialized = true;
   gpr_mu_init(&g_mu);
-  gpr_mu_init(&g_checker_mu);
   g_clock_type = now.clock_type;
 
   for (i = 0; i < NUM_SHARDS; i++) {
@@ -117,16 +117,9 @@
     grpc_timer_heap_destroy(&shard->heap);
   }
   gpr_mu_destroy(&g_mu);
-  gpr_mu_destroy(&g_checker_mu);
   g_initialized = false;
 }
 
-/* This is a cheap, but good enough, pointer hash for sharding the tasks: */
-static size_t shard_idx(const grpc_timer *info) {
-  size_t x = (size_t)info;
-  return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (NUM_SHARDS - 1);
-}
-
 static double ts_to_dbl(gpr_timespec ts) {
   return (double)ts.tv_sec + 1e-9 * ts.tv_nsec;
 }
@@ -181,30 +174,30 @@
                      gpr_timespec deadline, grpc_closure *closure,
                      gpr_timespec now) {
   int is_first_timer = 0;
-  shard_type *shard = &g_shards[shard_idx(timer)];
+  shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
   GPR_ASSERT(deadline.clock_type == g_clock_type);
   GPR_ASSERT(now.clock_type == g_clock_type);
   timer->closure = closure;
   timer->deadline = deadline;
-  timer->triggered = 0;
 
   if (!g_initialized) {
-    timer->triggered = 1;
+    timer->pending = false;
     grpc_closure_sched(
         exec_ctx, timer->closure,
         GRPC_ERROR_CREATE("Attempt to create timer before initialization"));
     return;
   }
 
+  gpr_mu_lock(&shard->mu);
+  timer->pending = true;
   if (gpr_time_cmp(deadline, now) <= 0) {
-    timer->triggered = 1;
+    timer->pending = false;
     grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
+    gpr_mu_unlock(&shard->mu);
+    /* early out */
     return;
   }
 
-  /* TODO(ctiller): check deadline expired */
-
-  gpr_mu_lock(&shard->mu);
   grpc_time_averaged_stats_add_sample(&shard->stats,
                                       ts_to_dbl(gpr_time_sub(deadline, now)));
   if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) {
@@ -247,11 +240,11 @@
     return;
   }
 
-  shard_type *shard = &g_shards[shard_idx(timer)];
+  shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
   gpr_mu_lock(&shard->mu);
-  if (!timer->triggered) {
+  if (timer->pending) {
     grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
-    timer->triggered = 1;
+    timer->pending = false;
     if (timer->heap_index == INVALID_HEAP_INDEX) {
       list_remove(timer);
     } else {
@@ -302,7 +295,7 @@
     }
     timer = grpc_timer_heap_top(&shard->heap);
     if (gpr_time_cmp(timer->deadline, now) > 0) return NULL;
-    timer->triggered = 1;
+    timer->pending = false;
     grpc_timer_heap_pop(&shard->heap);
     return timer;
   }
@@ -330,7 +323,7 @@
 
   /* TODO(ctiller): verify that there are any timers (atomically) here */
 
-  if (gpr_mu_trylock(&g_checker_mu)) {
+  if (gpr_spinlock_trylock(&g_checker_mu)) {
     gpr_mu_lock(&g_mu);
 
     while (gpr_time_cmp(g_shard_queue[0]->min_deadline, now) < 0) {
@@ -356,7 +349,7 @@
     }
 
     gpr_mu_unlock(&g_mu);
-    gpr_mu_unlock(&g_checker_mu);
+    gpr_spinlock_unlock(&g_checker_mu);
   } else if (next != NULL) {
     /* TODO(ctiller): this forces calling code to do an short poll, and
        then retry the timer check (because this time through the timer list was
diff --git a/src/core/lib/iomgr/timer_generic.h b/src/core/lib/iomgr/timer_generic.h
index 9d901c7..1608dce 100644
--- a/src/core/lib/iomgr/timer_generic.h
+++ b/src/core/lib/iomgr/timer_generic.h
@@ -40,7 +40,7 @@
 struct grpc_timer {
   gpr_timespec deadline;
   uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */
-  int triggered;
+  bool pending;
   struct grpc_timer *next;
   struct grpc_timer *prev;
   grpc_closure *closure;
diff --git a/src/core/lib/iomgr/timer_uv.c b/src/core/lib/iomgr/timer_uv.c
index fa2cdee..f28a144 100644
--- a/src/core/lib/iomgr/timer_uv.c
+++ b/src/core/lib/iomgr/timer_uv.c
@@ -53,8 +53,8 @@
 void run_expired_timer(uv_timer_t *handle) {
   grpc_timer *timer = (grpc_timer *)handle->data;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GPR_ASSERT(!timer->triggered);
-  timer->triggered = 1;
+  GPR_ASSERT(timer->pending);
+  timer->pending = 0;
   grpc_closure_sched(&exec_ctx, timer->closure, GRPC_ERROR_NONE);
   stop_uv_timer(handle);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -67,11 +67,11 @@
   uv_timer_t *uv_timer;
   timer->closure = closure;
   if (gpr_time_cmp(deadline, now) <= 0) {
-    timer->triggered = 1;
+    timer->pending = 0;
     grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
     return;
   }
-  timer->triggered = 0;
+  timer->pending = 1;
   timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now));
   uv_timer = gpr_malloc(sizeof(uv_timer_t));
   uv_timer_init(uv_default_loop(), uv_timer);
@@ -81,8 +81,8 @@
 }
 
 void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
-  if (!timer->triggered) {
-    timer->triggered = 1;
+  if (timer->pending) {
+    timer->pending = 0;
     grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
     stop_uv_timer((uv_timer_t *)timer->uv_timer);
   }
diff --git a/src/core/lib/iomgr/timer_uv.h b/src/core/lib/iomgr/timer_uv.h
index 13cf8bd..9870cd4 100644
--- a/src/core/lib/iomgr/timer_uv.h
+++ b/src/core/lib/iomgr/timer_uv.h
@@ -41,7 +41,7 @@
   /* This is actually a uv_timer_t*, but we want to keep platform-specific
      types out of headers */
   void *uv_timer;
-  int triggered;
+  int pending;
 };
 
 #endif /* GRPC_CORE_LIB_IOMGR_TIMER_UV_H */
diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c
index dfbd295..2a1c8d3 100644
--- a/src/core/lib/iomgr/udp_server.c
+++ b/src/core/lib/iomgr/udp_server.c
@@ -76,8 +76,10 @@
   grpc_udp_server *server;
   grpc_resolved_address addr;
   grpc_closure read_closure;
+  grpc_closure write_closure;
   grpc_closure destroyed_closure;
   grpc_udp_server_read_cb read_cb;
+  grpc_udp_server_write_cb write_cb;
   grpc_udp_server_orphan_cb orphan_cb;
 
   struct grpc_udp_listener *next;
@@ -176,7 +178,7 @@
       /* Call the orphan_cb to signal that the FD is about to be closed and
        * should no longer be used. */
       GPR_ASSERT(sp->orphan_cb);
-      sp->orphan_cb(sp->emfd);
+      sp->orphan_cb(exec_ctx, sp->emfd);
 
       grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
                      "udp_listener_shutdown");
@@ -202,8 +204,9 @@
   if (s->active_ports) {
     for (sp = s->head; sp; sp = sp->next) {
       GPR_ASSERT(sp->orphan_cb);
-      sp->orphan_cb(sp->emfd);
-      grpc_fd_shutdown(exec_ctx, sp->emfd);
+      sp->orphan_cb(exec_ctx, sp->emfd);
+      grpc_fd_shutdown(exec_ctx, sp->emfd,
+                       GRPC_ERROR_CREATE("Server destroyed"));
     }
     gpr_mu_unlock(&s->mu);
   } else {
@@ -303,9 +306,33 @@
   gpr_mu_unlock(&sp->server->mu);
 }
 
+static void on_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
+  grpc_udp_listener *sp = arg;
+
+  gpr_mu_lock(&(sp->server->mu));
+  if (error != GRPC_ERROR_NONE) {
+    if (0 == --sp->server->active_ports) {
+      gpr_mu_unlock(&sp->server->mu);
+      deactivated_all_ports(exec_ctx, sp->server);
+    } else {
+      gpr_mu_unlock(&sp->server->mu);
+    }
+    return;
+  }
+
+  /* Tell the registered callback that the socket is writeable. */
+  GPR_ASSERT(sp->write_cb);
+  sp->write_cb(exec_ctx, sp->emfd);
+
+  /* Re-arm the notification event so we get another chance to write. */
+  grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure);
+  gpr_mu_unlock(&sp->server->mu);
+}
+
 static int add_socket_to_server(grpc_udp_server *s, int fd,
                                 const grpc_resolved_address *addr,
                                 grpc_udp_server_read_cb read_cb,
+                                grpc_udp_server_write_cb write_cb,
                                 grpc_udp_server_orphan_cb orphan_cb) {
   grpc_udp_listener *sp;
   int port;
@@ -332,6 +359,7 @@
     sp->emfd = grpc_fd_create(fd, name);
     memcpy(&sp->addr, addr, sizeof(grpc_resolved_address));
     sp->read_cb = read_cb;
+    sp->write_cb = write_cb;
     sp->orphan_cb = orphan_cb;
     GPR_ASSERT(sp->emfd);
     gpr_mu_unlock(&s->mu);
@@ -344,6 +372,7 @@
 int grpc_udp_server_add_port(grpc_udp_server *s,
                              const grpc_resolved_address *addr,
                              grpc_udp_server_read_cb read_cb,
+                             grpc_udp_server_write_cb write_cb,
                              grpc_udp_server_orphan_cb orphan_cb) {
   grpc_udp_listener *sp;
   int allocated_port1 = -1;
@@ -390,7 +419,8 @@
     // TODO(rjshade): Test and propagate the returned grpc_error*:
     GRPC_ERROR_UNREF(grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP,
                                                   &dsmode, &fd));
-    allocated_port1 = add_socket_to_server(s, fd, addr, read_cb, orphan_cb);
+    allocated_port1 =
+        add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb);
     if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
       goto done;
     }
@@ -412,7 +442,8 @@
       grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
     addr = &addr4_copy;
   }
-  allocated_port2 = add_socket_to_server(s, fd, addr, read_cb, orphan_cb);
+  allocated_port2 =
+      add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb);
 
 done:
   gpr_free(allocated_addr);
@@ -450,6 +481,10 @@
                       grpc_schedule_on_exec_ctx);
     grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
 
+    grpc_closure_init(&sp->write_closure, on_write, sp,
+                      grpc_schedule_on_exec_ctx);
+    grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure);
+
     s->active_ports++;
     sp = sp->next;
   }
diff --git a/src/core/lib/iomgr/udp_server.h b/src/core/lib/iomgr/udp_server.h
index f3c466a..ed63fa7 100644
--- a/src/core/lib/iomgr/udp_server.h
+++ b/src/core/lib/iomgr/udp_server.h
@@ -49,8 +49,13 @@
 typedef void (*grpc_udp_server_read_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
                                         struct grpc_server *server);
 
+/* Called when the socket is writeable. */
+typedef void (*grpc_udp_server_write_cb)(grpc_exec_ctx *exec_ctx,
+                                         grpc_fd *emfd);
+
 /* Called when the grpc_fd is about to be orphaned (and the FD closed). */
-typedef void (*grpc_udp_server_orphan_cb)(grpc_fd *emfd);
+typedef void (*grpc_udp_server_orphan_cb)(grpc_exec_ctx *exec_ctx,
+                                          grpc_fd *emfd);
 
 /* Create a server, initially not bound to any ports */
 grpc_udp_server *grpc_udp_server_create(void);
@@ -75,6 +80,7 @@
 int grpc_udp_server_add_port(grpc_udp_server *s,
                              const grpc_resolved_address *addr,
                              grpc_udp_server_read_cb read_cb,
+                             grpc_udp_server_write_cb write_cb,
                              grpc_udp_server_orphan_cb orphan_cb);
 
 void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server,
diff --git a/src/core/lib/iomgr/unix_sockets_posix.c b/src/core/lib/iomgr/unix_sockets_posix.c
index 030acd9..1233cec 100644
--- a/src/core/lib/iomgr/unix_sockets_posix.c
+++ b/src/core/lib/iomgr/unix_sockets_posix.c
@@ -45,6 +45,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/useful.h>
 
 void grpc_create_socketpair_if_unix(int sv[2]) {
   GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0);
@@ -53,7 +54,16 @@
 grpc_error *grpc_resolve_unix_domain_address(const char *name,
                                              grpc_resolved_addresses **addrs) {
   struct sockaddr_un *un;
-
+  if (strlen(name) > GPR_ARRAY_SIZE(((struct sockaddr_un *)0)->sun_path) - 1) {
+    char *err_msg;
+    grpc_error *err;
+    gpr_asprintf(&err_msg,
+                 "Path name should not have more than %" PRIuPTR " characters.",
+                 GPR_ARRAY_SIZE(un->sun_path) - 1);
+    err = GRPC_ERROR_CREATE(err_msg);
+    gpr_free(err_msg);
+    return err;
+  }
   *addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
   (*addrs)->naddrs = 1;
   (*addrs)->addrs = gpr_malloc(sizeof(grpc_resolved_address));
diff --git a/src/core/lib/json/json.c b/src/core/lib/json/json.c
index 48b1368..5f7e4ec 100644
--- a/src/core/lib/json/json.c
+++ b/src/core/lib/json/json.c
@@ -38,8 +38,7 @@
 #include "src/core/lib/json/json.h"
 
 grpc_json* grpc_json_create(grpc_json_type type) {
-  grpc_json* json = gpr_malloc(sizeof(*json));
-  memset(json, 0, sizeof(*json));
+  grpc_json* json = gpr_zalloc(sizeof(*json));
   json->type = type;
 
   return json;
diff --git a/src/core/lib/profiling/basic_timers.c b/src/core/lib/profiling/basic_timers.c
index bdf9af2..1f1987f 100644
--- a/src/core/lib/profiling/basic_timers.c
+++ b/src/core/lib/profiling/basic_timers.c
@@ -43,6 +43,9 @@
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 #include <stdio.h>
+#include <string.h>
+
+#include "src/core/lib/support/env.h"
 
 typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
 
@@ -74,7 +77,7 @@
 static __thread gpr_timer_log *g_thread_log;
 static gpr_once g_once_init = GPR_ONCE_INIT;
 static FILE *output_file;
-static const char *output_filename = "latency_trace.txt";
+static const char *output_filename_or_null = NULL;
 static pthread_mutex_t g_mu;
 static pthread_cond_t g_cv;
 static gpr_timer_log_list g_in_progress_logs;
@@ -85,6 +88,17 @@
 static int g_next_thread_id;
 static int g_writing_enabled = 1;
 
+static const char *output_filename() {
+  if (output_filename_or_null == NULL) {
+    output_filename_or_null = gpr_getenv("LATENCY_TRACE");
+    if (output_filename_or_null == NULL ||
+        strlen(output_filename_or_null) == 0) {
+      output_filename_or_null = "latency_trace.txt";
+    }
+  }
+  return output_filename_or_null;
+}
+
 static int timer_log_push_back(gpr_timer_log_list *list, gpr_timer_log *log) {
   if (list->head == NULL) {
     list->head = list->tail = log;
@@ -134,7 +148,7 @@
 static void write_log(gpr_timer_log *log) {
   size_t i;
   if (output_file == NULL) {
-    output_file = fopen(output_filename, "w");
+    output_file = fopen(output_filename(), "w");
   }
   for (i = 0; i < log->num_entries; i++) {
     gpr_timer_entry *entry = &(log->log[i]);
@@ -198,7 +212,7 @@
 }
 
 void gpr_timers_set_log_filename(const char *filename) {
-  output_filename = filename;
+  output_filename_or_null = filename;
 }
 
 static void init_output() {
diff --git a/src/core/lib/security/context/security_context.c b/src/core/lib/security/context/security_context.c
index fe82fab..d29fc55 100644
--- a/src/core/lib/security/context/security_context.c
+++ b/src/core/lib/security/context/security_context.c
@@ -91,10 +91,7 @@
 /* --- grpc_client_security_context --- */
 
 grpc_client_security_context *grpc_client_security_context_create(void) {
-  grpc_client_security_context *ctx =
-      gpr_malloc(sizeof(grpc_client_security_context));
-  memset(ctx, 0, sizeof(grpc_client_security_context));
-  return ctx;
+  return gpr_zalloc(sizeof(grpc_client_security_context));
 }
 
 void grpc_client_security_context_destroy(void *ctx) {
@@ -112,10 +109,7 @@
 /* --- grpc_server_security_context --- */
 
 grpc_server_security_context *grpc_server_security_context_create(void) {
-  grpc_server_security_context *ctx =
-      gpr_malloc(sizeof(grpc_server_security_context));
-  memset(ctx, 0, sizeof(grpc_server_security_context));
-  return ctx;
+  return gpr_zalloc(sizeof(grpc_server_security_context));
 }
 
 void grpc_server_security_context_destroy(void *ctx) {
@@ -132,8 +126,7 @@
 static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL};
 
 grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) {
-  grpc_auth_context *ctx = gpr_malloc(sizeof(grpc_auth_context));
-  memset(ctx, 0, sizeof(grpc_auth_context));
+  grpc_auth_context *ctx = gpr_zalloc(sizeof(grpc_auth_context));
   gpr_ref_init(&ctx->refcount, 1);
   if (chained != NULL) {
     ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained");
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.c b/src/core/lib/security/credentials/composite/composite_credentials.c
index be1588d..e497b9f 100644
--- a/src/core/lib/security/credentials/composite/composite_credentials.c
+++ b/src/core/lib/security/credentials/composite/composite_credentials.c
@@ -115,8 +115,7 @@
   grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
   grpc_composite_call_credentials_metadata_context *ctx;
 
-  ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
-  memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
+  ctx = gpr_zalloc(sizeof(grpc_composite_call_credentials_metadata_context));
   ctx->auth_md_context = auth_md_context;
   ctx->user_data = user_data;
   ctx->cb = cb;
@@ -158,8 +157,7 @@
   GPR_ASSERT(reserved == NULL);
   GPR_ASSERT(creds1 != NULL);
   GPR_ASSERT(creds2 != NULL);
-  c = gpr_malloc(sizeof(grpc_composite_call_credentials));
-  memset(c, 0, sizeof(grpc_composite_call_credentials));
+  c = gpr_zalloc(sizeof(grpc_composite_call_credentials));
   c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
   c->base.vtable = &composite_call_credentials_vtable;
   gpr_ref_init(&c->base.refcount, 1);
@@ -167,8 +165,7 @@
   creds2_array = get_creds_array(&creds2);
   c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
   creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
-  c->inner.creds_array = gpr_malloc(creds_array_byte_size);
-  memset(c->inner.creds_array, 0, creds_array_byte_size);
+  c->inner.creds_array = gpr_zalloc(creds_array_byte_size);
   for (i = 0; i < creds1_array.num_creds; i++) {
     grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
     c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
@@ -262,8 +259,7 @@
 grpc_channel_credentials *grpc_composite_channel_credentials_create(
     grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
     void *reserved) {
-  grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
+  grpc_composite_channel_credentials *c = gpr_zalloc(sizeof(*c));
   GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
   GRPC_API_TRACE(
       "grpc_composite_channel_credentials_create(channel_creds=%p, "
diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c
index 9781a22..52b8014 100644
--- a/src/core/lib/security/credentials/credentials.c
+++ b/src/core/lib/security/credentials/credentials.c
@@ -57,8 +57,7 @@
     grpc_call_credentials *creds, grpc_credentials_metadata_cb cb,
     void *user_data) {
   grpc_credentials_metadata_request *r =
-      gpr_malloc(sizeof(grpc_credentials_metadata_request));
-  memset(&r->response, 0, sizeof(r->response));
+      gpr_zalloc(sizeof(grpc_credentials_metadata_request));
   r->creds = grpc_call_credentials_ref(creds);
   r->cb = cb;
   r->user_data = user_data;
@@ -160,6 +159,53 @@
   }
 }
 
+static void credentials_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) {
+  grpc_channel_credentials_unref(exec_ctx, p);
+}
+
+static void *credentials_pointer_arg_copy(void *p) {
+  return grpc_channel_credentials_ref(p);
+}
+
+static int credentials_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
+
+static const grpc_arg_pointer_vtable credentials_pointer_vtable = {
+    credentials_pointer_arg_copy, credentials_pointer_arg_destroy,
+    credentials_pointer_cmp};
+
+grpc_arg grpc_channel_credentials_to_arg(
+    grpc_channel_credentials *credentials) {
+  grpc_arg result;
+  result.type = GRPC_ARG_POINTER;
+  result.key = GRPC_ARG_CHANNEL_CREDENTIALS;
+  result.value.pointer.vtable = &credentials_pointer_vtable;
+  result.value.pointer.p = credentials;
+  return result;
+}
+
+grpc_channel_credentials *grpc_channel_credentials_from_arg(
+    const grpc_arg *arg) {
+  if (strcmp(arg->key, GRPC_ARG_CHANNEL_CREDENTIALS)) return NULL;
+  if (arg->type != GRPC_ARG_POINTER) {
+    gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
+            GRPC_ARG_CHANNEL_CREDENTIALS);
+    return NULL;
+  }
+  return arg->value.pointer.p;
+}
+
+grpc_channel_credentials *grpc_channel_credentials_find_in_args(
+    const grpc_channel_args *args) {
+  size_t i;
+  if (args == NULL) return NULL;
+  for (i = 0; i < args->num_args; i++) {
+    grpc_channel_credentials *credentials =
+        grpc_channel_credentials_from_arg(&args->args[i]);
+    if (credentials != NULL) return credentials;
+  }
+  return NULL;
+}
+
 grpc_server_credentials *grpc_server_credentials_ref(
     grpc_server_credentials *creds) {
   if (creds == NULL) return NULL;
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index 3011df6..510b795 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -100,6 +100,8 @@
 
 /* --- grpc_channel_credentials. --- */
 
+#define GRPC_ARG_CHANNEL_CREDENTIALS "grpc.channel_credentials"
+
 typedef struct {
   void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c);
 
@@ -140,6 +142,17 @@
 grpc_channel_credentials_duplicate_without_call_credentials(
     grpc_channel_credentials *creds);
 
+/* Util to encapsulate the channel credentials in a channel arg. */
+grpc_arg grpc_channel_credentials_to_arg(grpc_channel_credentials *credentials);
+
+/* Util to get the channel credentials from a channel arg. */
+grpc_channel_credentials *grpc_channel_credentials_from_arg(
+    const grpc_arg *arg);
+
+/* Util to find the channel credentials from channel args. */
+grpc_channel_credentials *grpc_channel_credentials_find_in_args(
+    const grpc_channel_args *args);
+
 /* --- grpc_credentials_md. --- */
 
 typedef struct {
diff --git a/src/core/lib/security/credentials/credentials_metadata.c b/src/core/lib/security/credentials/credentials_metadata.c
index 68da5fb..f11cc58 100644
--- a/src/core/lib/security/credentials/credentials_metadata.c
+++ b/src/core/lib/security/credentials/credentials_metadata.c
@@ -50,8 +50,7 @@
 grpc_credentials_md_store *grpc_credentials_md_store_create(
     size_t initial_capacity) {
   grpc_credentials_md_store *store =
-      gpr_malloc(sizeof(grpc_credentials_md_store));
-  memset(store, 0, sizeof(grpc_credentials_md_store));
+      gpr_zalloc(sizeof(grpc_credentials_md_store));
   if (initial_capacity > 0) {
     store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md));
     store->allocated = initial_capacity;
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c
index a8679d0..68636ba 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.c
+++ b/src/core/lib/security/credentials/fake/fake_credentials.c
@@ -35,13 +35,13 @@
 
 #include <string.h>
 
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/iomgr/executor.h"
-
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/support/string.h"
+
 /* -- Fake transport security credentials. -- */
 
 static grpc_security_status fake_transport_security_create_security_connector(
@@ -49,7 +49,7 @@
     grpc_call_credentials *call_creds, const char *target,
     const grpc_channel_args *args, grpc_channel_security_connector **sc,
     grpc_channel_args **new_args) {
-  *sc = grpc_fake_channel_security_connector_create(call_creds);
+  *sc = grpc_fake_channel_security_connector_create(call_creds, target, args);
   return GRPC_SECURITY_OK;
 }
 
@@ -71,8 +71,7 @@
 
 grpc_channel_credentials *grpc_fake_transport_security_credentials_create(
     void) {
-  grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials));
-  memset(c, 0, sizeof(grpc_channel_credentials));
+  grpc_channel_credentials *c = gpr_zalloc(sizeof(grpc_channel_credentials));
   c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
   c->vtable = &fake_transport_security_credentials_vtable;
   gpr_ref_init(&c->refcount, 1);
@@ -131,8 +130,7 @@
 grpc_call_credentials *grpc_md_only_test_credentials_create(
     const char *md_key, const char *md_value, int is_async) {
   grpc_md_only_test_credentials *c =
-      gpr_malloc(sizeof(grpc_md_only_test_credentials));
-  memset(c, 0, sizeof(grpc_md_only_test_credentials));
+      gpr_zalloc(sizeof(grpc_md_only_test_credentials));
   c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
   c->base.vtable = &md_only_test_vtable;
   gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h
index 9cf3808..0fe9841 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.h
+++ b/src/core/lib/security/credentials/fake/fake_credentials.h
@@ -38,6 +38,21 @@
 
 /* -- Fake transport security credentials. -- */
 
+/* Used to verify the target names given to the fake transport security
+ * connector.
+ *
+ * Its syntax by example:
+ * For LB channels:
+ *     "backend_target_1,backend_target_2,...;lb_target_1,lb_target_2,..."
+ * For regular channels:
+ *     "backend_taget_1,backend_target_2,..."
+ *
+ * That is to say, LB channels have a heading list of LB targets separated from
+ * the list of backend targets by a semicolon. For non-LB channels, only the
+ * latter is present. */
+#define GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS \
+  "grpc.test_only.fake_security.expected_target"
+
 /* Creates a fake transport security credentials object for testing. */
 grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void);
 
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c
index d6e1fe3..dd44621 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.c
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c
@@ -112,7 +112,7 @@
      on compute engine. */
   gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN);
 
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &g_polling_mu);
   detector.pollent = grpc_polling_entity_create_from_pollset(pollset);
   detector.is_done = 0;
@@ -154,7 +154,7 @@
   }
   gpr_mu_unlock(g_polling_mu);
 
-  grpc_httpcli_context_destroy(&context);
+  grpc_httpcli_context_destroy(exec_ctx, &context);
   grpc_closure_init(&destroy_closure, destroy_pollset,
                     grpc_polling_entity_pollset(&detector.pollent),
                     grpc_schedule_on_exec_ctx);
@@ -177,7 +177,7 @@
   grpc_auth_json_key key;
   grpc_auth_refresh_token token;
   grpc_call_credentials *result = NULL;
-  grpc_slice creds_data = gpr_empty_slice();
+  grpc_slice creds_data = grpc_empty_slice();
   grpc_error *error = GRPC_ERROR_NONE;
   if (creds_path == NULL) {
     error = GRPC_ERROR_CREATE("creds_path unset");
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.c b/src/core/lib/security/credentials/iam/iam_credentials.c
index abd69a9..393a433 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.c
+++ b/src/core/lib/security/credentials/iam/iam_credentials.c
@@ -72,8 +72,7 @@
   GPR_ASSERT(reserved == NULL);
   GPR_ASSERT(token != NULL);
   GPR_ASSERT(authority_selector != NULL);
-  c = gpr_malloc(sizeof(grpc_google_iam_credentials));
-  memset(c, 0, sizeof(grpc_google_iam_credentials));
+  c = gpr_zalloc(sizeof(grpc_google_iam_credentials));
   c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
   c->base.vtable = &iam_vtable;
   gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c
index 616be64..178ce89 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.c
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c
@@ -135,8 +135,7 @@
     gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
     return NULL;
   }
-  c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
-  memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
+  c = gpr_zalloc(sizeof(grpc_service_account_jwt_access_credentials));
   c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT;
   gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &jwt_vtable;
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
index 2270be8..5c59cf0 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.c
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -144,8 +144,7 @@
 static jose_header *jose_header_from_json(grpc_exec_ctx *exec_ctx,
                                           grpc_json *json, grpc_slice buffer) {
   grpc_json *cur;
-  jose_header *h = gpr_malloc(sizeof(jose_header));
-  memset(h, 0, sizeof(jose_header));
+  jose_header *h = gpr_zalloc(sizeof(jose_header));
   h->buffer = buffer;
   for (cur = json->child; cur != NULL; cur = cur->next) {
     if (strcmp(cur->key, "alg") == 0) {
@@ -363,8 +362,7 @@
     const char *signed_jwt, size_t signed_jwt_len, void *user_data,
     grpc_jwt_verification_done_cb cb) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
-  memset(ctx, 0, sizeof(verifier_cb_ctx));
+  verifier_cb_ctx *ctx = gpr_zalloc(sizeof(verifier_cb_ctx));
   ctx->verifier = verifier;
   ctx->pollent = grpc_polling_entity_create_from_pollset(pollset);
   ctx->header = header;
@@ -878,8 +876,7 @@
 grpc_jwt_verifier *grpc_jwt_verifier_create(
     const grpc_jwt_verifier_email_domain_key_url_mapping *mappings,
     size_t num_mappings) {
-  grpc_jwt_verifier *v = gpr_malloc(sizeof(grpc_jwt_verifier));
-  memset(v, 0, sizeof(grpc_jwt_verifier));
+  grpc_jwt_verifier *v = gpr_zalloc(sizeof(grpc_jwt_verifier));
   grpc_httpcli_context_init(&v->http_ctx);
 
   /* We know at least of one mapping. */
@@ -898,10 +895,10 @@
   return v;
 }
 
-void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) {
+void grpc_jwt_verifier_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *v) {
   size_t i;
   if (v == NULL) return;
-  grpc_httpcli_context_destroy(&v->http_ctx);
+  grpc_httpcli_context_destroy(exec_ctx, &v->http_ctx);
   if (v->mappings != NULL) {
     for (i = 0; i < v->num_mappings; i++) {
       gpr_free(v->mappings[i].email_domain);
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.h b/src/core/lib/security/credentials/jwt/jwt_verifier.h
index 4fa320a..5c3d2a7 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.h
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.h
@@ -109,7 +109,8 @@
     size_t num_mappings);
 
 /*The verifier must not be destroyed if there are still outstanding callbacks.*/
-void grpc_jwt_verifier_destroy(grpc_jwt_verifier *verifier);
+void grpc_jwt_verifier_destroy(grpc_exec_ctx *exec_ctx,
+                               grpc_jwt_verifier *verifier);
 
 /* User provided callback that will be called when the verification of the JWT
    is done (maybe in another thread).
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
index 1b0e43a..ccfb356 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -124,7 +124,7 @@
       (grpc_oauth2_token_fetcher_credentials *)creds;
   grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
   gpr_mu_destroy(&c->mu);
-  grpc_httpcli_context_destroy(&c->httpcli_context);
+  grpc_httpcli_context_destroy(exec_ctx, &c->httpcli_context);
 }
 
 grpc_credentials_status
@@ -389,8 +389,7 @@
     gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
     return NULL;
   }
-  c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
-  memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
+  c = gpr_zalloc(sizeof(grpc_google_refresh_token_credentials));
   init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
   c->base.base.vtable = &refresh_token_vtable;
   c->refresh_token = refresh_token;
@@ -450,14 +449,13 @@
 grpc_call_credentials *grpc_access_token_credentials_create(
     const char *access_token, void *reserved) {
   grpc_access_token_credentials *c =
-      gpr_malloc(sizeof(grpc_access_token_credentials));
+      gpr_zalloc(sizeof(grpc_access_token_credentials));
   char *token_md_value;
   GRPC_API_TRACE(
       "grpc_access_token_credentials_create(access_token=<redacted>, "
       "reserved=%p)",
       1, (reserved));
   GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_access_token_credentials));
   c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
   c->base.vtable = &access_token_vtable;
   gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c
index f90d7dc..8416bfa 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.c
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c
@@ -42,7 +42,9 @@
 #include <grpc/support/sync.h>
 
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/surface/validate_metadata.h"
 
 typedef struct {
   void *user_data;
@@ -63,7 +65,9 @@
                                              grpc_status_code status,
                                              const char *error_details) {
   /* called from application code */
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INITIALIZER(
+      GRPC_EXEC_CTX_FLAG_IS_FINISHED | GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP,
+      NULL, NULL);
   grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
   if (status != GRPC_STATUS_OK) {
     if (error_details != NULL) {
@@ -77,13 +81,14 @@
     bool seen_illegal_header = false;
     grpc_credentials_md *md_array = NULL;
     for (i = 0; i < num_md; i++) {
-      if (!grpc_header_key_is_legal(md[i].key, strlen(md[i].key))) {
-        gpr_log(GPR_ERROR, "Plugin added invalid metadata key: %s", md[i].key);
+      if (!GRPC_LOG_IF_ERROR("validate_metadata_from_plugin",
+                             grpc_validate_header_key_is_legal(md[i].key))) {
         seen_illegal_header = true;
         break;
-      } else if (!grpc_is_binary_header(md[i].key, strlen(md[i].key)) &&
-                 !grpc_header_nonbin_value_is_legal(md[i].value,
-                                                    md[i].value_length)) {
+      } else if (!grpc_is_binary_header(md[i].key) &&
+                 !GRPC_LOG_IF_ERROR(
+                     "validate_metadata_from_plugin",
+                     grpc_validate_header_nonbin_value_is_legal(md[i].value))) {
         gpr_log(GPR_ERROR, "Plugin added invalid metadata value.");
         seen_illegal_header = true;
         break;
@@ -95,9 +100,8 @@
     } else if (num_md > 0) {
       md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
       for (i = 0; i < num_md; i++) {
-        md_array[i].key = grpc_slice_from_copied_string(md[i].key);
-        md_array[i].value =
-            grpc_slice_from_copied_buffer(md[i].value, md[i].value_length);
+        md_array[i].key = grpc_slice_ref_internal(md[i].key);
+        md_array[i].value = grpc_slice_ref_internal(md[i].value);
       }
       r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK,
             NULL);
@@ -122,8 +126,7 @@
                                         void *user_data) {
   grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
   if (c->plugin.get_metadata != NULL) {
-    grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
-    memset(request, 0, sizeof(*request));
+    grpc_metadata_plugin_request *request = gpr_zalloc(sizeof(*request));
     request->user_data = user_data;
     request->cb = cb;
     c->plugin.get_metadata(c->plugin.state, context,
@@ -138,11 +141,10 @@
 
 grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
     grpc_metadata_credentials_plugin plugin, void *reserved) {
-  grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
+  grpc_plugin_credentials *c = gpr_zalloc(sizeof(*c));
   GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
                  (reserved));
   GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(*c));
   c->base.type = plugin.type;
   c->base.vtable = &plugin_vtable;
   gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.c b/src/core/lib/security/credentials/ssl/ssl_credentials.c
index 4eebb7d..4b17ac8 100644
--- a/src/core/lib/security/credentials/ssl/ssl_credentials.c
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.c
@@ -121,14 +121,13 @@
 grpc_channel_credentials *grpc_ssl_credentials_create(
     const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
     void *reserved) {
-  grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
+  grpc_ssl_credentials *c = gpr_zalloc(sizeof(grpc_ssl_credentials));
   GRPC_API_TRACE(
       "grpc_ssl_credentials_create(pem_root_certs=%s, "
       "pem_key_cert_pair=%p, "
       "reserved=%p)",
       3, (pem_root_certs, pem_key_cert_pair, reserved));
   GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_ssl_credentials));
   c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
   c->base.vtable = &ssl_vtable;
   gpr_ref_init(&c->base.refcount, 1);
@@ -225,7 +224,7 @@
     grpc_ssl_client_certificate_request_type client_certificate_request,
     void *reserved) {
   grpc_ssl_server_credentials *c =
-      gpr_malloc(sizeof(grpc_ssl_server_credentials));
+      gpr_zalloc(sizeof(grpc_ssl_server_credentials));
   GRPC_API_TRACE(
       "grpc_ssl_server_credentials_create_ex("
       "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
@@ -233,7 +232,6 @@
       5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
           client_certificate_request, reserved));
   GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_ssl_server_credentials));
   c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
   gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &ssl_server_vtable;
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index b7f6fd2..a23082a 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -45,6 +45,7 @@
 #include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/security/transport/security_connector.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/transport/static_metadata.h"
@@ -54,8 +55,10 @@
 /* We can have a per-call credentials. */
 typedef struct {
   grpc_call_credentials *creds;
-  grpc_mdstr *host;
-  grpc_mdstr *method;
+  bool have_host;
+  bool have_method;
+  grpc_slice host;
+  grpc_slice method;
   /* pollset{_set} bound to this call; if we need to make external
      network requests, they should be done under a pollset added to this
      pollset_set so that work can progress when this call wants work to progress
@@ -89,14 +92,12 @@
   auth_md_context->channel_auth_context = NULL;
 }
 
-static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                            grpc_status_code status, const char *error_msg) {
-  call_data *calld = elem->call_data;
-  gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg);
-  grpc_slice error_slice = grpc_slice_from_copied_string(error_msg);
-  grpc_transport_stream_op_add_close(exec_ctx, &calld->op, status,
-                                     &error_slice);
-  grpc_call_next_op(exec_ctx, elem, &calld->op);
+static void add_error(grpc_error **combined, grpc_error *error) {
+  if (error == GRPC_ERROR_NONE) return;
+  if (*combined == GRPC_ERROR_NONE) {
+    *combined = GRPC_ERROR_CREATE("Client auth metadata plugin error");
+  }
+  *combined = grpc_error_add_child(*combined, error);
 }
 
 static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -110,30 +111,37 @@
   grpc_metadata_batch *mdb;
   size_t i;
   reset_auth_metadata_context(&calld->auth_md_context);
+  grpc_error *error = GRPC_ERROR_NONE;
   if (status != GRPC_CREDENTIALS_OK) {
-    bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
-                    (error_details != NULL && strlen(error_details) > 0)
-                        ? error_details
-                        : "Credentials failed to get metadata.");
-    return;
+    error = grpc_error_set_int(
+        GRPC_ERROR_CREATE(error_details != NULL && strlen(error_details) > 0
+                              ? error_details
+                              : "Credentials failed to get metadata."),
+        GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED);
+  } else {
+    GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
+    GPR_ASSERT(op->send_initial_metadata != NULL);
+    mdb = op->send_initial_metadata;
+    for (i = 0; i < num_md; i++) {
+      add_error(&error,
+                grpc_metadata_batch_add_tail(
+                    exec_ctx, mdb, &calld->md_links[i],
+                    grpc_mdelem_from_slices(
+                        exec_ctx, grpc_slice_ref_internal(md_elems[i].key),
+                        grpc_slice_ref_internal(md_elems[i].value))));
+    }
   }
-  GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
-  GPR_ASSERT(op->send_initial_metadata != NULL);
-  mdb = op->send_initial_metadata;
-  for (i = 0; i < num_md; i++) {
-    grpc_metadata_batch_add_tail(
-        mdb, &calld->md_links[i],
-        grpc_mdelem_from_slices(exec_ctx,
-                                grpc_slice_ref_internal(md_elems[i].key),
-                                grpc_slice_ref_internal(md_elems[i].value)));
+  if (error == GRPC_ERROR_NONE) {
+    grpc_call_next_op(exec_ctx, elem, op);
+  } else {
+    grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
   }
-  grpc_call_next_op(exec_ctx, elem, op);
 }
 
 void build_auth_metadata_context(grpc_security_connector *sc,
                                  grpc_auth_context *auth_context,
                                  call_data *calld) {
-  char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
+  char *service = grpc_slice_to_c_string(calld->method);
   char *last_slash = strrchr(service, '/');
   char *method_name = NULL;
   char *service_url = NULL;
@@ -149,14 +157,15 @@
     method_name = gpr_strdup(last_slash + 1);
   }
   if (method_name == NULL) method_name = gpr_strdup("");
+  char *host = grpc_slice_to_c_string(calld->host);
   gpr_asprintf(&service_url, "%s://%s%s",
-               sc->url_scheme == NULL ? "" : sc->url_scheme,
-               grpc_mdstr_as_c_string(calld->host), service);
+               sc->url_scheme == NULL ? "" : sc->url_scheme, host, service);
   calld->auth_md_context.service_url = service_url;
   calld->auth_md_context.method_name = method_name;
   calld->auth_md_context.channel_auth_context =
       GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context");
   gpr_free(service);
+  gpr_free(host);
 }
 
 static void send_security_metadata(grpc_exec_ctx *exec_ctx,
@@ -180,8 +189,12 @@
     calld->creds = grpc_composite_call_credentials_create(channel_call_creds,
                                                           ctx->creds, NULL);
     if (calld->creds == NULL) {
-      bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
-                      "Incompatible credentials set on channel and call.");
+      grpc_transport_stream_op_finish_with_failure(
+          exec_ctx, op,
+          grpc_error_set_int(
+              GRPC_ERROR_CREATE(
+                  "Incompatible credentials set on channel and call."),
+              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED));
       return;
     }
   } else {
@@ -207,9 +220,14 @@
     send_security_metadata(exec_ctx, elem, &calld->op);
   } else {
     char *error_msg;
+    char *host = grpc_slice_to_c_string(calld->host);
     gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.",
-                 grpc_mdstr_as_c_string(calld->host));
-    bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, error_msg);
+                 host);
+    gpr_free(host);
+    grpc_call_element_signal_error(
+        exec_ctx, elem, grpc_error_set_int(GRPC_ERROR_CREATE(error_msg),
+                                           GRPC_ERROR_INT_GRPC_STATUS,
+                                           GRPC_STATUS_UNAUTHENTICATED));
     gpr_free(error_msg);
   }
 }
@@ -247,23 +265,30 @@
 
   if (op->send_initial_metadata != NULL) {
     for (l = op->send_initial_metadata->list.head; l != NULL; l = l->next) {
-      grpc_mdelem *md = l->md;
+      grpc_mdelem md = l->md;
       /* Pointer comparison is OK for md_elems created from the same context.
        */
-      if (md->key == GRPC_MDSTR_AUTHORITY) {
-        if (calld->host != NULL) GRPC_MDSTR_UNREF(exec_ctx, calld->host);
-        calld->host = GRPC_MDSTR_REF(md->value);
-      } else if (md->key == GRPC_MDSTR_PATH) {
-        if (calld->method != NULL) GRPC_MDSTR_UNREF(exec_ctx, calld->method);
-        calld->method = GRPC_MDSTR_REF(md->value);
+      if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_AUTHORITY)) {
+        if (calld->have_host) {
+          grpc_slice_unref_internal(exec_ctx, calld->host);
+        }
+        calld->host = grpc_slice_ref_internal(GRPC_MDVALUE(md));
+        calld->have_host = true;
+      } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) {
+        if (calld->have_method) {
+          grpc_slice_unref_internal(exec_ctx, calld->method);
+        }
+        calld->method = grpc_slice_ref_internal(GRPC_MDVALUE(md));
+        calld->have_method = true;
       }
     }
-    if (calld->host != NULL) {
-      const char *call_host = grpc_mdstr_as_c_string(calld->host);
+    if (calld->have_host) {
+      char *call_host = grpc_slice_to_c_string(calld->host);
       calld->op = *op; /* Copy op (originates from the caller's stack). */
       grpc_channel_security_connector_check_call_host(
           exec_ctx, chand->security_connector, call_host, chand->auth_context,
           on_host_checked, elem);
+      gpr_free(call_host);
       GPR_TIMER_END("auth_start_transport_op", 0);
       return; /* early exit */
     }
@@ -277,7 +302,7 @@
 /* Constructor for call_data */
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   memset(calld, 0, sizeof(*calld));
   return GRPC_ERROR_NONE;
@@ -296,11 +321,11 @@
                               void *ignored) {
   call_data *calld = elem->call_data;
   grpc_call_credentials_unref(exec_ctx, calld->creds);
-  if (calld->host != NULL) {
-    GRPC_MDSTR_UNREF(exec_ctx, calld->host);
+  if (calld->have_host) {
+    grpc_slice_unref_internal(exec_ctx, calld->host);
   }
-  if (calld->method != NULL) {
-    GRPC_MDSTR_UNREF(exec_ctx, calld->method);
+  if (calld->have_method) {
+    grpc_slice_unref_internal(exec_ctx, calld->method);
   }
   reset_auth_metadata_context(&calld->auth_md_context);
 }
@@ -310,7 +335,7 @@
                                      grpc_channel_element *elem,
                                      grpc_channel_element_args *args) {
   grpc_security_connector *sc =
-      grpc_find_security_connector_in_args(args->channel_args);
+      grpc_security_connector_find_in_args(args->channel_args);
   grpc_auth_context *auth_context =
       grpc_find_auth_context_in_args(args->channel_args);
 
diff --git a/src/core/lib/security/transport/lb_targets_info.c b/src/core/lib/security/transport/lb_targets_info.c
new file mode 100644
index 0000000..e73483c
--- /dev/null
+++ b/src/core/lib/security/transport/lb_targets_info.c
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/security/transport/lb_targets_info.h"
+
+/* Channel arg key for the mapping of LB server addresses to their names for
+ * secure naming purposes. */
+#define GRPC_ARG_LB_SECURE_NAMING_MAP "grpc.lb_secure_naming_map"
+
+static void *targets_info_copy(void *p) { return grpc_slice_hash_table_ref(p); }
+static void targets_info_destroy(grpc_exec_ctx *exec_ctx, void *p) {
+  grpc_slice_hash_table_unref(exec_ctx, p);
+}
+static int targets_info_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
+static const grpc_arg_pointer_vtable server_to_balancer_names_vtable = {
+    targets_info_copy, targets_info_destroy, targets_info_cmp};
+
+grpc_arg grpc_lb_targets_info_create_channel_arg(
+    grpc_slice_hash_table *targets_info) {
+  grpc_arg arg;
+  arg.type = GRPC_ARG_POINTER;
+  arg.key = GRPC_ARG_LB_SECURE_NAMING_MAP;
+  arg.value.pointer.p = targets_info;
+  arg.value.pointer.vtable = &server_to_balancer_names_vtable;
+  return arg;
+}
+
+grpc_slice_hash_table *grpc_lb_targets_info_find_in_args(
+    const grpc_channel_args *args) {
+  const grpc_arg *targets_info_arg =
+      grpc_channel_args_find(args, GRPC_ARG_LB_SECURE_NAMING_MAP);
+  if (targets_info_arg != NULL) {
+    GPR_ASSERT(targets_info_arg->type == GRPC_ARG_POINTER);
+    return targets_info_arg->value.pointer.p;
+  }
+  return NULL;
+}
diff --git a/src/core/lib/security/transport/lb_targets_info.h b/src/core/lib/security/transport/lb_targets_info.h
new file mode 100644
index 0000000..5e6cacc
--- /dev/null
+++ b/src/core/lib/security/transport/lb_targets_info.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H
+#define GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H
+
+#include "src/core/lib/slice/slice_hash_table.h"
+
+/** Return a channel argument containing \a targets_info. */
+grpc_arg grpc_lb_targets_info_create_channel_arg(
+    grpc_slice_hash_table *targets_info);
+
+/** Return the instance of targets info in \a args or NULL */
+grpc_slice_hash_table *grpc_lb_targets_info_find_in_args(
+    const grpc_channel_args *args);
+
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H */
diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c
index 18a7a6f..7d58843 100644
--- a/src/core/lib/security/transport/secure_endpoint.c
+++ b/src/core/lib/security/transport/secure_endpoint.c
@@ -341,10 +341,10 @@
   GPR_TIMER_END("secure_endpoint.endpoint_write", 0);
 }
 
-static void endpoint_shutdown(grpc_exec_ctx *exec_ctx,
-                              grpc_endpoint *secure_ep) {
+static void endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep,
+                              grpc_error *why) {
   secure_endpoint *ep = (secure_endpoint *)secure_ep;
-  grpc_endpoint_shutdown(exec_ctx, ep->wrapped_ep);
+  grpc_endpoint_shutdown(exec_ctx, ep->wrapped_ep, why);
 }
 
 static void endpoint_destroy(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index 5aa26e0..ad083a7 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -43,10 +43,13 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/transport/chttp2/alpn/alpn.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/handshaker.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
+#include "src/core/lib/security/transport/lb_targets_info.h"
 #include "src/core/lib/security/transport/secure_endpoint.h"
 #include "src/core/lib/security/transport/security_handshaker.h"
 #include "src/core/lib/support/env.h"
@@ -205,23 +208,23 @@
 grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) {
   grpc_arg result;
   result.type = GRPC_ARG_POINTER;
-  result.key = GRPC_SECURITY_CONNECTOR_ARG;
+  result.key = GRPC_ARG_SECURITY_CONNECTOR;
   result.value.pointer.vtable = &connector_pointer_vtable;
   result.value.pointer.p = sc;
   return result;
 }
 
 grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) {
-  if (strcmp(arg->key, GRPC_SECURITY_CONNECTOR_ARG)) return NULL;
+  if (strcmp(arg->key, GRPC_ARG_SECURITY_CONNECTOR)) return NULL;
   if (arg->type != GRPC_ARG_POINTER) {
     gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
-            GRPC_SECURITY_CONNECTOR_ARG);
+            GRPC_ARG_SECURITY_CONNECTOR);
     return NULL;
   }
   return arg->value.pointer.p;
 }
 
-grpc_security_connector *grpc_find_security_connector_in_args(
+grpc_security_connector *grpc_security_connector_find_in_args(
     const grpc_channel_args *args) {
   size_t i;
   if (args == NULL) return NULL;
@@ -235,11 +238,21 @@
 
 /* -- Fake implementation. -- */
 
+typedef struct {
+  grpc_channel_security_connector base;
+  char *target;
+  char *expected_targets;
+  bool is_lb_channel;
+} grpc_fake_channel_security_connector;
+
 static void fake_channel_destroy(grpc_exec_ctx *exec_ctx,
                                  grpc_security_connector *sc) {
-  grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc;
-  grpc_call_credentials_unref(exec_ctx, c->request_metadata_creds);
-  gpr_free(sc);
+  grpc_fake_channel_security_connector *c =
+      (grpc_fake_channel_security_connector *)sc;
+  grpc_call_credentials_unref(exec_ctx, c->base.request_metadata_creds);
+  gpr_free(c->target);
+  gpr_free(c->expected_targets);
+  gpr_free(c);
 }
 
 static void fake_server_destroy(grpc_exec_ctx *exec_ctx,
@@ -247,6 +260,68 @@
   gpr_free(sc);
 }
 
+static bool fake_check_target(const char *target_type, const char *target,
+                              const char *set_str) {
+  GPR_ASSERT(target_type != NULL);
+  GPR_ASSERT(target != NULL);
+  char **set = NULL;
+  size_t set_size = 0;
+  gpr_string_split(set_str, ",", &set, &set_size);
+  bool found = false;
+  for (size_t i = 0; i < set_size; ++i) {
+    if (set[i] != NULL && strcmp(target, set[i]) == 0) found = true;
+  }
+  for (size_t i = 0; i < set_size; ++i) {
+    gpr_free(set[i]);
+  }
+  gpr_free(set);
+  return found;
+}
+
+static void fake_secure_name_check(const char *target,
+                                   const char *expected_targets,
+                                   bool is_lb_channel) {
+  if (expected_targets == NULL) return;
+  char **lbs_and_backends = NULL;
+  size_t lbs_and_backends_size = 0;
+  bool success = false;
+  gpr_string_split(expected_targets, ";", &lbs_and_backends,
+                   &lbs_and_backends_size);
+  if (lbs_and_backends_size > 2 || lbs_and_backends_size == 0) {
+    gpr_log(GPR_ERROR, "Invalid expected targets arg value: '%s'",
+            expected_targets);
+    goto done;
+  }
+  if (is_lb_channel) {
+    if (lbs_and_backends_size != 2) {
+      gpr_log(GPR_ERROR,
+              "Invalid expected targets arg value: '%s'. Expectations for LB "
+              "channels must be of the form 'be1,be2,be3,...;lb1,lb2,...",
+              expected_targets);
+      goto done;
+    }
+    if (!fake_check_target("LB", target, lbs_and_backends[1])) {
+      gpr_log(GPR_ERROR, "LB target '%s' not found in expected set '%s'",
+              target, lbs_and_backends[1]);
+      goto done;
+    }
+    success = true;
+  } else {
+    if (!fake_check_target("Backend", target, lbs_and_backends[0])) {
+      gpr_log(GPR_ERROR, "Backend target '%s' not found in expected set '%s'",
+              target, lbs_and_backends[0]);
+      goto done;
+    }
+    success = true;
+  }
+done:
+  for (size_t i = 0; i < lbs_and_backends_size; ++i) {
+    gpr_free(lbs_and_backends[i]);
+  }
+  gpr_free(lbs_and_backends);
+  if (!success) abort();
+}
+
 static void fake_check_peer(grpc_exec_ctx *exec_ctx,
                             grpc_security_connector *sc, tsi_peer peer,
                             grpc_auth_context **auth_context,
@@ -277,12 +352,28 @@
   grpc_auth_context_add_cstring_property(
       *auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
       GRPC_FAKE_TRANSPORT_SECURITY_TYPE);
-
 end:
   grpc_closure_sched(exec_ctx, on_peer_checked, error);
   tsi_peer_destruct(&peer);
 }
 
+static void fake_channel_check_peer(grpc_exec_ctx *exec_ctx,
+                                    grpc_security_connector *sc, tsi_peer peer,
+                                    grpc_auth_context **auth_context,
+                                    grpc_closure *on_peer_checked) {
+  fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked);
+  grpc_fake_channel_security_connector *c =
+      (grpc_fake_channel_security_connector *)sc;
+  fake_secure_name_check(c->target, c->expected_targets, c->is_lb_channel);
+}
+
+static void fake_server_check_peer(grpc_exec_ctx *exec_ctx,
+                                   grpc_security_connector *sc, tsi_peer peer,
+                                   grpc_auth_context **auth_context,
+                                   grpc_closure *on_peer_checked) {
+  fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked);
+}
+
 static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
                                          grpc_channel_security_connector *sc,
                                          const char *host,
@@ -313,29 +404,37 @@
 }
 
 static grpc_security_connector_vtable fake_channel_vtable = {
-    fake_channel_destroy, fake_check_peer};
+    fake_channel_destroy, fake_channel_check_peer};
 
-static grpc_security_connector_vtable fake_server_vtable = {fake_server_destroy,
-                                                            fake_check_peer};
+static grpc_security_connector_vtable fake_server_vtable = {
+    fake_server_destroy, fake_server_check_peer};
 
 grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
-    grpc_call_credentials *request_metadata_creds) {
-  grpc_channel_security_connector *c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
-  gpr_ref_init(&c->base.refcount, 1);
-  c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
-  c->base.vtable = &fake_channel_vtable;
-  c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds);
-  c->check_call_host = fake_channel_check_call_host;
-  c->add_handshakers = fake_channel_add_handshakers;
-  return c;
+    grpc_call_credentials *request_metadata_creds, const char *target,
+    const grpc_channel_args *args) {
+  grpc_fake_channel_security_connector *c = gpr_zalloc(sizeof(*c));
+  gpr_ref_init(&c->base.base.refcount, 1);
+  c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
+  c->base.base.vtable = &fake_channel_vtable;
+  c->base.request_metadata_creds =
+      grpc_call_credentials_ref(request_metadata_creds);
+  c->base.check_call_host = fake_channel_check_call_host;
+  c->base.add_handshakers = fake_channel_add_handshakers;
+  c->target = gpr_strdup(target);
+  const grpc_arg *expected_target_arg =
+      grpc_channel_args_find(args, GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS);
+  if (expected_target_arg != NULL) {
+    GPR_ASSERT(expected_target_arg->type == GRPC_ARG_STRING);
+    c->expected_targets = gpr_strdup(expected_target_arg->value.string);
+  }
+  c->is_lb_channel = (grpc_lb_targets_info_find_in_args(args) != NULL);
+  return &c->base;
 }
 
 grpc_server_security_connector *grpc_fake_server_security_connector_create(
     void) {
   grpc_server_security_connector *c =
-      gpr_malloc(sizeof(grpc_server_security_connector));
-  memset(c, 0, sizeof(*c));
+      gpr_zalloc(sizeof(grpc_server_security_connector));
   gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &fake_server_vtable;
   c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
@@ -601,7 +700,7 @@
     ssl_server_destroy, ssl_server_check_peer};
 
 static grpc_slice compute_default_pem_root_certs_once(void) {
-  grpc_slice result = gpr_empty_slice();
+  grpc_slice result = grpc_empty_slice();
 
   /* First try to load the roots from the environment. */
   char *default_root_certs_path =
@@ -714,8 +813,7 @@
     pem_root_certs_size = config->pem_root_certs_size;
   }
 
-  c = gpr_malloc(sizeof(grpc_ssl_channel_security_connector));
-  memset(c, 0, sizeof(grpc_ssl_channel_security_connector));
+  c = gpr_zalloc(sizeof(grpc_ssl_channel_security_connector));
 
   gpr_ref_init(&c->base.base.refcount, 1);
   c->base.base.vtable = &ssl_channel_vtable;
@@ -776,8 +874,7 @@
     gpr_log(GPR_ERROR, "An SSL server needs a key and a cert.");
     goto error;
   }
-  c = gpr_malloc(sizeof(grpc_ssl_server_security_connector));
-  memset(c, 0, sizeof(grpc_ssl_server_security_connector));
+  c = gpr_zalloc(sizeof(grpc_ssl_server_security_connector));
 
   gpr_ref_init(&c->base.base.refcount, 1);
   c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h
index eba4e6d..3df2fec 100644
--- a/src/core/lib/security/transport/security_connector.h
+++ b/src/core/lib/security/transport/security_connector.h
@@ -57,7 +57,7 @@
 
 typedef struct grpc_security_connector grpc_security_connector;
 
-#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector"
+#define GRPC_ARG_SECURITY_CONNECTOR "grpc.security_connector"
 
 typedef struct {
   void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc);
@@ -115,7 +115,7 @@
 grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg);
 
 /* Util to find the connector from channel args. */
-grpc_security_connector *grpc_find_security_connector_in_args(
+grpc_security_connector *grpc_security_connector_find_in_args(
     const grpc_channel_args *args);
 
 /* --- channel_security_connector object. ---
@@ -175,7 +175,8 @@
 /* For TESTING ONLY!
    Creates a fake connector that emulates real channel security.  */
 grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
-    grpc_call_credentials *request_metadata_creds);
+    grpc_call_credentials *request_metadata_creds, const char *target,
+    const grpc_channel_args *args);
 
 /* For TESTING ONLY!
    Creates a fake connector that emulates real server security.  */
diff --git a/src/core/lib/security/transport/security_handshaker.c b/src/core/lib/security/transport/security_handshaker.c
index 5e75856..7065d26 100644
--- a/src/core/lib/security/transport/security_handshaker.c
+++ b/src/core/lib/security/transport/security_handshaker.c
@@ -124,13 +124,13 @@
   }
   const char *msg = grpc_error_string(error);
   gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg);
-  grpc_error_free_string(msg);
+
   if (!h->shutdown) {
     // TODO(ctiller): It is currently necessary to shutdown endpoints
     // before destroying them, even if we know that there are no
     // pending read/write callbacks.  This should be fixed, at which
     // point this can be removed.
-    grpc_endpoint_shutdown(exec_ctx, h->args->endpoint);
+    grpc_endpoint_shutdown(exec_ctx, h->args->endpoint, GRPC_ERROR_REF(error));
     // Not shutting down, so the write failed.  Clean up before
     // invoking the callback.
     cleanup_args_for_failure_locked(exec_ctx, h);
@@ -347,15 +347,17 @@
 }
 
 static void security_handshaker_shutdown(grpc_exec_ctx *exec_ctx,
-                                         grpc_handshaker *handshaker) {
+                                         grpc_handshaker *handshaker,
+                                         grpc_error *why) {
   security_handshaker *h = (security_handshaker *)handshaker;
   gpr_mu_lock(&h->mu);
   if (!h->shutdown) {
     h->shutdown = true;
-    grpc_endpoint_shutdown(exec_ctx, h->args->endpoint);
+    grpc_endpoint_shutdown(exec_ctx, h->args->endpoint, GRPC_ERROR_REF(why));
     cleanup_args_for_failure_locked(exec_ctx, h);
   }
   gpr_mu_unlock(&h->mu);
+  GRPC_ERROR_UNREF(why);
 }
 
 static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
@@ -385,8 +387,7 @@
 static grpc_handshaker *security_handshaker_create(
     grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
     grpc_security_connector *connector) {
-  security_handshaker *h = gpr_malloc(sizeof(security_handshaker));
-  memset(h, 0, sizeof(security_handshaker));
+  security_handshaker *h = gpr_zalloc(sizeof(security_handshaker));
   grpc_handshaker_init(&security_handshaker_vtable, &h->base);
   h->handshaker = handshaker;
   h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
@@ -417,7 +418,10 @@
 }
 
 static void fail_handshaker_shutdown(grpc_exec_ctx *exec_ctx,
-                                     grpc_handshaker *handshaker) {}
+                                     grpc_handshaker *handshaker,
+                                     grpc_error *why) {
+  GRPC_ERROR_UNREF(why);
+}
 
 static void fail_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
                                          grpc_handshaker *handshaker,
@@ -446,7 +450,7 @@
     grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory,
     const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
   grpc_channel_security_connector *security_connector =
-      (grpc_channel_security_connector *)grpc_find_security_connector_in_args(
+      (grpc_channel_security_connector *)grpc_security_connector_find_in_args(
           args);
   grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector,
                                                   handshake_mgr);
@@ -456,7 +460,7 @@
     grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf,
     const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
   grpc_server_security_connector *security_connector =
-      (grpc_server_security_connector *)grpc_find_security_connector_in_args(
+      (grpc_server_security_connector *)grpc_security_connector_find_in_args(
           args);
   grpc_server_security_connector_add_handshakers(exec_ctx, security_connector,
                                                  handshake_mgr);
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index 5e98ba8..14619d9 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -33,12 +33,13 @@
 
 #include <string.h>
 
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
 #include "src/core/lib/security/context/security_context.h"
 #include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/security/transport/auth_filters.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
+#include "src/core/lib/slice/slice_internal.h"
 
 typedef struct call_data {
   grpc_metadata_batch *recv_initial_metadata;
@@ -67,48 +68,34 @@
   grpc_metadata_array_init(&result);
   for (l = batch->list.head; l != NULL; l = l->next) {
     grpc_metadata *usr_md = NULL;
-    grpc_mdelem *md = l->md;
-    grpc_mdstr *key = md->key;
-    grpc_mdstr *value = md->value;
+    grpc_mdelem md = l->md;
+    grpc_slice key = GRPC_MDKEY(md);
+    grpc_slice value = GRPC_MDVALUE(md);
     if (result.count == result.capacity) {
       result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2);
       result.metadata =
           gpr_realloc(result.metadata, result.capacity * sizeof(grpc_metadata));
     }
     usr_md = &result.metadata[result.count++];
-    usr_md->key = grpc_mdstr_as_c_string(key);
-    usr_md->value = grpc_mdstr_as_c_string(value);
-    usr_md->value_length = GRPC_SLICE_LENGTH(value->slice);
+    usr_md->key = grpc_slice_ref_internal(key);
+    usr_md->value = grpc_slice_ref_internal(value);
   }
   return result;
 }
 
-static grpc_mdelem *remove_consumed_md(grpc_exec_ctx *exec_ctx, void *user_data,
-                                       grpc_mdelem *md) {
+static grpc_filtered_mdelem remove_consumed_md(grpc_exec_ctx *exec_ctx,
+                                               void *user_data,
+                                               grpc_mdelem md) {
   grpc_call_element *elem = user_data;
   call_data *calld = elem->call_data;
   size_t i;
   for (i = 0; i < calld->num_consumed_md; i++) {
     const grpc_metadata *consumed_md = &calld->consumed_md[i];
-    /* Maybe we could do a pointer comparison but we do not have any guarantee
-       that the metadata processor used the same pointers for consumed_md in the
-       callback. */
-    if (GRPC_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) ||
-        GRPC_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) {
-      continue;
-    }
-    if (memcmp(GRPC_SLICE_START_PTR(md->key->slice), consumed_md->key,
-               GRPC_SLICE_LENGTH(md->key->slice)) == 0 &&
-        memcmp(GRPC_SLICE_START_PTR(md->value->slice), consumed_md->value,
-               GRPC_SLICE_LENGTH(md->value->slice)) == 0) {
-      return NULL; /* Delete. */
-    }
+    if (grpc_slice_eq(GRPC_MDKEY(md), consumed_md->key) &&
+        grpc_slice_eq(GRPC_MDVALUE(md), consumed_md->value))
+      return GRPC_FILTERED_REMOVE();
   }
-  return md;
-}
-
-static void destroy_op(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
-  gpr_free(arg);
+  return GRPC_FILTERED_MDELEM(md);
 }
 
 /* called from application code */
@@ -130,29 +117,33 @@
   if (status == GRPC_STATUS_OK) {
     calld->consumed_md = consumed_md;
     calld->num_consumed_md = num_consumed_md;
-    grpc_metadata_batch_filter(&exec_ctx, calld->recv_initial_metadata,
-                               remove_consumed_md, elem);
+    /* TODO(ctiller): propagate error */
+    GRPC_LOG_IF_ERROR(
+        "grpc_metadata_batch_filter",
+        grpc_metadata_batch_filter(&exec_ctx, calld->recv_initial_metadata,
+                                   remove_consumed_md, elem,
+                                   "Response metadata filtering error"));
+    for (size_t i = 0; i < calld->md.count; i++) {
+      grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].key);
+      grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].value);
+    }
     grpc_metadata_array_destroy(&calld->md);
     grpc_closure_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE);
   } else {
-    grpc_slice message;
-    grpc_transport_stream_op *close_op = gpr_malloc(sizeof(*close_op));
-    memset(close_op, 0, sizeof(*close_op));
+    for (size_t i = 0; i < calld->md.count; i++) {
+      grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].key);
+      grpc_slice_unref_internal(&exec_ctx, calld->md.metadata[i].value);
+    }
     grpc_metadata_array_destroy(&calld->md);
     error_details = error_details != NULL
                         ? error_details
                         : "Authentication metadata processing failed.";
-    message = grpc_slice_from_copied_string(error_details);
     calld->transport_op->send_initial_metadata = NULL;
     if (calld->transport_op->send_message != NULL) {
       grpc_byte_stream_destroy(&exec_ctx, calld->transport_op->send_message);
       calld->transport_op->send_message = NULL;
     }
     calld->transport_op->send_trailing_metadata = NULL;
-    close_op->on_complete =
-        grpc_closure_create(destroy_op, close_op, grpc_schedule_on_exec_ctx);
-    grpc_transport_stream_op_add_close(&exec_ctx, close_op, status, &message);
-    grpc_call_next_op(&exec_ctx, elem, close_op);
     grpc_closure_sched(&exec_ctx, calld->on_done_recv,
                        grpc_error_set_int(GRPC_ERROR_CREATE(error_details),
                                           GRPC_ERROR_INT_GRPC_STATUS, status));
@@ -206,7 +197,7 @@
 /* Constructor for call_data */
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   /* grab pointers to our data from the call element */
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
diff --git a/src/core/lib/security/util/b64.c b/src/core/lib/security/util/b64.c
index bbd7e33..09c8213 100644
--- a/src/core/lib/security/util/b64.c
+++ b/src/core/lib/security/util/b64.c
@@ -232,5 +232,5 @@
 
 fail:
   grpc_slice_unref_internal(exec_ctx, result);
-  return gpr_empty_slice();
+  return grpc_empty_slice();
 }
diff --git a/src/core/lib/slice/slice.c b/src/core/lib/slice/slice.c
index 7611810..1cddf06 100644
--- a/src/core/lib/slice/slice.c
+++ b/src/core/lib/slice/slice.c
@@ -41,23 +41,30 @@
 
 #include "src/core/lib/iomgr/exec_ctx.h"
 
-grpc_slice gpr_empty_slice(void) {
+char *grpc_slice_to_c_string(grpc_slice slice) {
+  char *out = gpr_malloc(GRPC_SLICE_LENGTH(slice) + 1);
+  memcpy(out, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice));
+  out[GRPC_SLICE_LENGTH(slice)] = 0;
+  return out;
+}
+
+grpc_slice grpc_empty_slice(void) {
   grpc_slice out;
-  out.refcount = 0;
+  out.refcount = NULL;
   out.data.inlined.length = 0;
   return out;
 }
 
 grpc_slice grpc_slice_ref_internal(grpc_slice slice) {
   if (slice.refcount) {
-    slice.refcount->ref(slice.refcount);
+    slice.refcount->vtable->ref(slice.refcount);
   }
   return slice;
 }
 
 void grpc_slice_unref_internal(grpc_exec_ctx *exec_ctx, grpc_slice slice) {
   if (slice.refcount) {
-    slice.refcount->unref(exec_ctx, slice.refcount);
+    slice.refcount->vtable->unref(exec_ctx, slice.refcount);
   }
 }
 
@@ -78,16 +85,24 @@
 static void noop_ref(void *unused) {}
 static void noop_unref(grpc_exec_ctx *exec_ctx, void *unused) {}
 
-static grpc_slice_refcount noop_refcount = {noop_ref, noop_unref};
+static const grpc_slice_refcount_vtable noop_refcount_vtable = {
+    noop_ref, noop_unref, grpc_slice_default_eq_impl,
+    grpc_slice_default_hash_impl};
+static grpc_slice_refcount noop_refcount = {&noop_refcount_vtable,
+                                            &noop_refcount};
 
-grpc_slice grpc_slice_from_static_string(const char *s) {
+grpc_slice grpc_slice_from_static_buffer(const void *s, size_t len) {
   grpc_slice slice;
   slice.refcount = &noop_refcount;
   slice.data.refcounted.bytes = (uint8_t *)s;
-  slice.data.refcounted.length = strlen(s);
+  slice.data.refcounted.length = len;
   return slice;
 }
 
+grpc_slice grpc_slice_from_static_string(const char *s) {
+  return grpc_slice_from_static_buffer(s, strlen(s));
+}
+
 /* grpc_slice_new support structures - we create a refcount object extended
    with the user provided data pointer & destroy function */
 typedef struct new_slice_refcount {
@@ -110,14 +125,18 @@
   }
 }
 
+static const grpc_slice_refcount_vtable new_slice_vtable = {
+    new_slice_ref, new_slice_unref, grpc_slice_default_eq_impl,
+    grpc_slice_default_hash_impl};
+
 grpc_slice grpc_slice_new_with_user_data(void *p, size_t len,
                                          void (*destroy)(void *),
                                          void *user_data) {
   grpc_slice slice;
   new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount));
   gpr_ref_init(&rc->refs, 1);
-  rc->rc.ref = new_slice_ref;
-  rc->rc.unref = new_slice_unref;
+  rc->rc.vtable = &new_slice_vtable;
+  rc->rc.sub_refcount = &rc->rc;
   rc->user_destroy = destroy;
   rc->user_data = user_data;
 
@@ -155,14 +174,18 @@
   }
 }
 
+static const grpc_slice_refcount_vtable new_with_len_vtable = {
+    new_with_len_ref, new_with_len_unref, grpc_slice_default_eq_impl,
+    grpc_slice_default_hash_impl};
+
 grpc_slice grpc_slice_new_with_len(void *p, size_t len,
                                    void (*destroy)(void *, size_t)) {
   grpc_slice slice;
   new_with_len_slice_refcount *rc =
       gpr_malloc(sizeof(new_with_len_slice_refcount));
   gpr_ref_init(&rc->refs, 1);
-  rc->rc.ref = new_with_len_ref;
-  rc->rc.unref = new_with_len_unref;
+  rc->rc.vtable = &new_with_len_vtable;
+  rc->rc.sub_refcount = &rc->rc;
   rc->user_destroy = destroy;
   rc->user_data = p;
   rc->user_length = len;
@@ -200,6 +223,10 @@
   }
 }
 
+static const grpc_slice_refcount_vtable malloc_vtable = {
+    malloc_ref, malloc_unref, grpc_slice_default_eq_impl,
+    grpc_slice_default_hash_impl};
+
 grpc_slice grpc_slice_malloc(size_t length) {
   grpc_slice slice;
 
@@ -219,8 +246,8 @@
        this reference. */
     gpr_ref_init(&rc->refs, 1);
 
-    rc->base.ref = malloc_ref;
-    rc->base.unref = malloc_unref;
+    rc->base.vtable = &malloc_vtable;
+    rc->base.sub_refcount = &rc->base;
 
     /* Build up the slice to be returned. */
     /* The slices refcount points back to the allocated block. */
@@ -247,7 +274,7 @@
     GPR_ASSERT(source.data.refcounted.length >= end);
 
     /* Build the result */
-    subset.refcount = source.refcount;
+    subset.refcount = source.refcount->sub_refcount;
     /* Point into the source array */
     subset.data.refcounted.bytes = source.data.refcounted.bytes + begin;
     subset.data.refcounted.length = end - begin;
@@ -273,7 +300,7 @@
   } else {
     subset = grpc_slice_sub_no_ref(source, begin, end);
     /* Bump the refcount */
-    subset.refcount->ref(subset.refcount);
+    subset.refcount->vtable->ref(subset.refcount);
   }
   return subset;
 }
@@ -300,13 +327,14 @@
              tail_length);
     } else {
       /* Build the result */
-      tail.refcount = source->refcount;
+      tail.refcount = source->refcount->sub_refcount;
       /* Bump the refcount */
-      tail.refcount->ref(tail.refcount);
+      tail.refcount->vtable->ref(tail.refcount);
       /* Point into the source array */
       tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
       tail.data.refcounted.length = tail_length;
     }
+    source->refcount = source->refcount->sub_refcount;
     source->data.refcounted.length = split;
   }
 
@@ -332,18 +360,20 @@
     head.refcount = NULL;
     head.data.inlined.length = (uint8_t)split;
     memcpy(head.data.inlined.bytes, source->data.refcounted.bytes, split);
+    source->refcount = source->refcount->sub_refcount;
     source->data.refcounted.bytes += split;
     source->data.refcounted.length -= split;
   } else {
     GPR_ASSERT(source->data.refcounted.length >= split);
 
     /* Build the result */
-    head.refcount = source->refcount;
+    head.refcount = source->refcount->sub_refcount;
     /* Bump the refcount */
-    head.refcount->ref(head.refcount);
+    head.refcount->vtable->ref(head.refcount);
     /* Point into the source array */
     head.data.refcounted.bytes = source->data.refcounted.bytes;
     head.data.refcounted.length = split;
+    source->refcount = source->refcount->sub_refcount;
     source->data.refcounted.bytes += split;
     source->data.refcounted.length -= split;
   }
@@ -351,6 +381,19 @@
   return head;
 }
 
+int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b) {
+  return GRPC_SLICE_LENGTH(a) == GRPC_SLICE_LENGTH(b) &&
+         0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b),
+                     GRPC_SLICE_LENGTH(a));
+}
+
+int grpc_slice_eq(grpc_slice a, grpc_slice b) {
+  if (a.refcount && b.refcount && a.refcount->vtable == b.refcount->vtable) {
+    return a.refcount->vtable->eq(a, b);
+  }
+  return grpc_slice_default_eq_impl(a, b);
+}
+
 int grpc_slice_cmp(grpc_slice a, grpc_slice b) {
   int d = (int)(GRPC_SLICE_LENGTH(a) - GRPC_SLICE_LENGTH(b));
   if (d != 0) return d;
@@ -367,8 +410,55 @@
 
 int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b) {
   if (a.refcount == NULL || b.refcount == NULL) {
-    return grpc_slice_cmp(a, b) == 0;
+    return grpc_slice_eq(a, b);
   }
   return a.data.refcounted.length == b.data.refcounted.length &&
          a.data.refcounted.bytes == b.data.refcounted.bytes;
 }
+
+int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t len) {
+  if (GRPC_SLICE_LENGTH(a) < len) return 0;
+  return 0 == memcmp(GRPC_SLICE_START_PTR(a), b, len);
+}
+
+int grpc_slice_rchr(grpc_slice s, char c) {
+  const char *b = (const char *)GRPC_SLICE_START_PTR(s);
+  int i;
+  for (i = (int)GRPC_SLICE_LENGTH(s) - 1; i != -1 && b[i] != c; i--)
+    ;
+  return i;
+}
+
+int grpc_slice_chr(grpc_slice s, char c) {
+  const char *b = (const char *)GRPC_SLICE_START_PTR(s);
+  const char *p = memchr(b, c, GRPC_SLICE_LENGTH(s));
+  return p == NULL ? -1 : (int)(p - b);
+}
+
+int grpc_slice_slice(grpc_slice haystack, grpc_slice needle) {
+  size_t haystack_len = GRPC_SLICE_LENGTH(haystack);
+  const uint8_t *haystack_bytes = GRPC_SLICE_START_PTR(haystack);
+  size_t needle_len = GRPC_SLICE_LENGTH(needle);
+  const uint8_t *needle_bytes = GRPC_SLICE_START_PTR(needle);
+
+  if (haystack_len == 0 || needle_len == 0) return -1;
+  if (haystack_len < needle_len) return -1;
+  if (haystack_len == needle_len)
+    return grpc_slice_eq(haystack, needle) ? 0 : -1;
+  if (needle_len == 1) return grpc_slice_chr(haystack, (char)*needle_bytes);
+
+  const uint8_t *last = haystack_bytes + haystack_len - needle_len;
+  for (const uint8_t *cur = haystack_bytes; cur != last; ++cur) {
+    if (0 == memcmp(cur, needle_bytes, needle_len)) {
+      return (int)(cur - haystack_bytes);
+    }
+  }
+  return -1;
+}
+
+grpc_slice grpc_slice_dup(grpc_slice a) {
+  grpc_slice copy = grpc_slice_malloc(GRPC_SLICE_LENGTH(a));
+  memcpy(GRPC_SLICE_START_PTR(copy), GRPC_SLICE_START_PTR(a),
+         GRPC_SLICE_LENGTH(a));
+  return copy;
+}
diff --git a/src/core/lib/slice/slice_buffer.c b/src/core/lib/slice/slice_buffer.c
index 08eaf49..9176dc8 100644
--- a/src/core/lib/slice/slice_buffer.c
+++ b/src/core/lib/slice/slice_buffer.c
@@ -46,15 +46,27 @@
 #define GROW(x) (3 * (x) / 2)
 
 static void maybe_embiggen(grpc_slice_buffer *sb) {
-  if (sb->count == sb->capacity) {
+  if (sb->base_slices != sb->slices) {
+    memmove(sb->base_slices, sb->slices, sb->count * sizeof(grpc_slice));
+    sb->slices = sb->base_slices;
+  }
+
+  /* How far away from sb->base_slices is sb->slices pointer */
+  size_t slice_offset = (size_t)(sb->slices - sb->base_slices);
+  size_t slice_count = sb->count + slice_offset;
+
+  if (slice_count == sb->capacity) {
     sb->capacity = GROW(sb->capacity);
-    GPR_ASSERT(sb->capacity > sb->count);
-    if (sb->slices == sb->inlined) {
-      sb->slices = gpr_malloc(sb->capacity * sizeof(grpc_slice));
-      memcpy(sb->slices, sb->inlined, sb->count * sizeof(grpc_slice));
+    GPR_ASSERT(sb->capacity > slice_count);
+    if (sb->base_slices == sb->inlined) {
+      sb->base_slices = gpr_malloc(sb->capacity * sizeof(grpc_slice));
+      memcpy(sb->base_slices, sb->inlined, slice_count * sizeof(grpc_slice));
     } else {
-      sb->slices = gpr_realloc(sb->slices, sb->capacity * sizeof(grpc_slice));
+      sb->base_slices =
+          gpr_realloc(sb->base_slices, sb->capacity * sizeof(grpc_slice));
     }
+
+    sb->slices = sb->base_slices + slice_offset;
   }
 }
 
@@ -62,14 +74,14 @@
   sb->count = 0;
   sb->length = 0;
   sb->capacity = GRPC_SLICE_BUFFER_INLINE_ELEMENTS;
-  sb->slices = sb->inlined;
+  sb->base_slices = sb->slices = sb->inlined;
 }
 
 void grpc_slice_buffer_destroy_internal(grpc_exec_ctx *exec_ctx,
                                         grpc_slice_buffer *sb) {
   grpc_slice_buffer_reset_and_unref_internal(exec_ctx, sb);
-  if (sb->slices != sb->inlined) {
-    gpr_free(sb->slices);
+  if (sb->base_slices != sb->inlined) {
+    gpr_free(sb->base_slices);
   }
 }
 
@@ -166,7 +178,6 @@
 void grpc_slice_buffer_reset_and_unref_internal(grpc_exec_ctx *exec_ctx,
                                                 grpc_slice_buffer *sb) {
   size_t i;
-
   for (i = 0; i < sb->count; i++) {
     grpc_slice_unref_internal(exec_ctx, sb->slices[i]);
   }
@@ -182,32 +193,45 @@
 }
 
 void grpc_slice_buffer_swap(grpc_slice_buffer *a, grpc_slice_buffer *b) {
+  size_t a_offset = (size_t)(a->slices - a->base_slices);
+  size_t b_offset = (size_t)(b->slices - b->base_slices);
+
+  size_t a_count = a->count + a_offset;
+  size_t b_count = b->count + b_offset;
+
+  if (a->base_slices == a->inlined) {
+    if (b->base_slices == b->inlined) {
+      /* swap contents of inlined buffer */
+      grpc_slice temp[GRPC_SLICE_BUFFER_INLINE_ELEMENTS];
+      memcpy(temp, a->base_slices, a_count * sizeof(grpc_slice));
+      memcpy(a->base_slices, b->base_slices, b_count * sizeof(grpc_slice));
+      memcpy(b->base_slices, temp, a_count * sizeof(grpc_slice));
+    } else {
+      /* a is inlined, b is not - copy a inlined into b, fix pointers */
+      a->base_slices = b->base_slices;
+      b->base_slices = b->inlined;
+      memcpy(b->base_slices, a->inlined, a_count * sizeof(grpc_slice));
+    }
+  } else if (b->base_slices == b->inlined) {
+    /* b is inlined, a is not - copy b inlined int a, fix pointers */
+    b->base_slices = a->base_slices;
+    a->base_slices = a->inlined;
+    memcpy(a->base_slices, b->inlined, b_count * sizeof(grpc_slice));
+  } else {
+    /* no inlining: easy swap */
+    GPR_SWAP(grpc_slice *, a->base_slices, b->base_slices);
+  }
+
+  /* Update the slices pointers (cannot do a GPR_SWAP on slices fields here).
+   * Also note that since the base_slices pointers are already swapped we need
+   * use 'b_offset' for 'a->base_slices' and vice versa */
+  a->slices = a->base_slices + b_offset;
+  b->slices = b->base_slices + a_offset;
+
+  /* base_slices and slices fields are correctly set. Swap all other fields */
   GPR_SWAP(size_t, a->count, b->count);
   GPR_SWAP(size_t, a->capacity, b->capacity);
   GPR_SWAP(size_t, a->length, b->length);
-
-  if (a->slices == a->inlined) {
-    if (b->slices == b->inlined) {
-      /* swap contents of inlined buffer */
-      grpc_slice temp[GRPC_SLICE_BUFFER_INLINE_ELEMENTS];
-      memcpy(temp, a->slices, b->count * sizeof(grpc_slice));
-      memcpy(a->slices, b->slices, a->count * sizeof(grpc_slice));
-      memcpy(b->slices, temp, b->count * sizeof(grpc_slice));
-    } else {
-      /* a is inlined, b is not - copy a inlined into b, fix pointers */
-      a->slices = b->slices;
-      b->slices = b->inlined;
-      memcpy(b->slices, a->inlined, b->count * sizeof(grpc_slice));
-    }
-  } else if (b->slices == b->inlined) {
-    /* b is inlined, a is not - copy b inlined int a, fix pointers */
-    b->slices = a->slices;
-    a->slices = a->inlined;
-    memcpy(a->slices, b->inlined, a->count * sizeof(grpc_slice));
-  } else {
-    /* no inlining: easy swap */
-    GPR_SWAP(grpc_slice *, a->slices, b->slices);
-  }
 }
 
 void grpc_slice_buffer_move_into(grpc_slice_buffer *src,
@@ -229,7 +253,6 @@
 
 void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
                                   grpc_slice_buffer *dst) {
-  size_t src_idx;
   size_t output_len = dst->length + n;
   size_t new_input_len = src->length - n;
   GPR_ASSERT(src->length >= n);
@@ -237,34 +260,55 @@
     grpc_slice_buffer_move_into(src, dst);
     return;
   }
-  src_idx = 0;
-  while (src_idx < src->capacity) {
-    grpc_slice slice = src->slices[src_idx];
+
+  while (src->count > 0) {
+    grpc_slice slice = grpc_slice_buffer_take_first(src);
     size_t slice_len = GRPC_SLICE_LENGTH(slice);
     if (n > slice_len) {
       grpc_slice_buffer_add(dst, slice);
       n -= slice_len;
-      src_idx++;
     } else if (n == slice_len) {
       grpc_slice_buffer_add(dst, slice);
-      src_idx++;
       break;
     } else { /* n < slice_len */
-      src->slices[src_idx] = grpc_slice_split_tail(&slice, n);
+      grpc_slice_buffer_undo_take_first(src, grpc_slice_split_tail(&slice, n));
       GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n);
-      GPR_ASSERT(GRPC_SLICE_LENGTH(src->slices[src_idx]) == slice_len - n);
       grpc_slice_buffer_add(dst, slice);
       break;
     }
   }
   GPR_ASSERT(dst->length == output_len);
-  memmove(src->slices, src->slices + src_idx,
-          sizeof(grpc_slice) * (src->count - src_idx));
-  src->count -= src_idx;
-  src->length = new_input_len;
+  GPR_ASSERT(src->length == new_input_len);
   GPR_ASSERT(src->count > 0);
 }
 
+void grpc_slice_buffer_move_first_into_buffer(grpc_exec_ctx *exec_ctx,
+                                              grpc_slice_buffer *src, size_t n,
+                                              void *dst) {
+  char *dstp = dst;
+  GPR_ASSERT(src->length >= n);
+
+  while (n > 0) {
+    grpc_slice slice = grpc_slice_buffer_take_first(src);
+    size_t slice_len = GRPC_SLICE_LENGTH(slice);
+    if (slice_len > n) {
+      memcpy(dstp, GRPC_SLICE_START_PTR(slice), n);
+      grpc_slice_buffer_undo_take_first(
+          src, grpc_slice_sub_no_ref(slice, n, slice_len));
+      n = 0;
+    } else if (slice_len == n) {
+      memcpy(dstp, GRPC_SLICE_START_PTR(slice), n);
+      grpc_slice_unref_internal(exec_ctx, slice);
+      n = 0;
+    } else {
+      memcpy(dstp, GRPC_SLICE_START_PTR(slice), slice_len);
+      dstp += slice_len;
+      n -= slice_len;
+      grpc_slice_unref_internal(exec_ctx, slice);
+    }
+  }
+}
+
 void grpc_slice_buffer_trim_end(grpc_slice_buffer *sb, size_t n,
                                 grpc_slice_buffer *garbage) {
   GPR_ASSERT(n <= sb->length);
@@ -293,8 +337,17 @@
   grpc_slice slice;
   GPR_ASSERT(sb->count > 0);
   slice = sb->slices[0];
-  memmove(&sb->slices[0], &sb->slices[1], (sb->count - 1) * sizeof(grpc_slice));
+  sb->slices++;
   sb->count--;
   sb->length -= GRPC_SLICE_LENGTH(slice);
+
   return slice;
 }
+
+void grpc_slice_buffer_undo_take_first(grpc_slice_buffer *sb,
+                                       grpc_slice slice) {
+  sb->slices--;
+  sb->slices[0] = slice;
+  sb->count++;
+  sb->length += GRPC_SLICE_LENGTH(slice);
+}
diff --git a/src/core/lib/slice/slice_hash_table.c b/src/core/lib/slice/slice_hash_table.c
new file mode 100644
index 0000000..219567f
--- /dev/null
+++ b/src/core/lib/slice/slice_hash_table.c
@@ -0,0 +1,125 @@
+//
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "src/core/lib/slice/slice_hash_table.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/metadata.h"
+
+struct grpc_slice_hash_table {
+  gpr_refcount refs;
+  size_t size;
+  grpc_slice_hash_table_entry* entries;
+};
+
+static bool is_empty(grpc_slice_hash_table_entry* entry) {
+  return entry->vtable == NULL;
+}
+
+// Helper function for insert and get operations that performs quadratic
+// probing (https://en.wikipedia.org/wiki/Quadratic_probing).
+static size_t grpc_slice_hash_table_find_index(
+    const grpc_slice_hash_table* table, const grpc_slice key, bool find_empty) {
+  size_t hash = grpc_slice_hash(key);
+  for (size_t i = 0; i < table->size; ++i) {
+    const size_t idx = (hash + i * i) % table->size;
+    if (is_empty(&table->entries[idx])) {
+      return find_empty ? idx : table->size;
+    }
+    if (grpc_slice_eq(table->entries[idx].key, key)) {
+      return idx;
+    }
+  }
+  return table->size;  // Not found.
+}
+
+static void grpc_slice_hash_table_add(
+    grpc_slice_hash_table* table, grpc_slice key, void* value,
+    const grpc_slice_hash_table_vtable* vtable) {
+  GPR_ASSERT(value != NULL);
+  const size_t idx =
+      grpc_slice_hash_table_find_index(table, key, true /* find_empty */);
+  GPR_ASSERT(idx != table->size);  // Table should never be full.
+  grpc_slice_hash_table_entry* entry = &table->entries[idx];
+  entry->key = grpc_slice_ref_internal(key);
+  entry->value = vtable->copy_value(value);
+  entry->vtable = vtable;
+}
+
+grpc_slice_hash_table* grpc_slice_hash_table_create(
+    size_t num_entries, grpc_slice_hash_table_entry* entries) {
+  grpc_slice_hash_table* table = gpr_zalloc(sizeof(*table));
+  gpr_ref_init(&table->refs, 1);
+  // Quadratic probing gets best performance when the table is no more
+  // than half full.
+  table->size = num_entries * 2;
+  const size_t entry_size = sizeof(grpc_slice_hash_table_entry) * table->size;
+  table->entries = gpr_zalloc(entry_size);
+  for (size_t i = 0; i < num_entries; ++i) {
+    grpc_slice_hash_table_entry* entry = &entries[i];
+    grpc_slice_hash_table_add(table, entry->key, entry->value, entry->vtable);
+  }
+  return table;
+}
+
+grpc_slice_hash_table* grpc_slice_hash_table_ref(grpc_slice_hash_table* table) {
+  if (table != NULL) gpr_ref(&table->refs);
+  return table;
+}
+
+void grpc_slice_hash_table_unref(grpc_exec_ctx* exec_ctx,
+                                 grpc_slice_hash_table* table) {
+  if (table != NULL && gpr_unref(&table->refs)) {
+    for (size_t i = 0; i < table->size; ++i) {
+      grpc_slice_hash_table_entry* entry = &table->entries[i];
+      if (!is_empty(entry)) {
+        grpc_slice_unref_internal(exec_ctx, entry->key);
+        entry->vtable->destroy_value(exec_ctx, entry->value);
+      }
+    }
+    gpr_free(table->entries);
+    gpr_free(table);
+  }
+}
+
+void* grpc_slice_hash_table_get(const grpc_slice_hash_table* table,
+                                const grpc_slice key) {
+  const size_t idx =
+      grpc_slice_hash_table_find_index(table, key, false /* find_empty */);
+  if (idx == table->size) return NULL;  // Not found.
+  return table->entries[idx].value;
+}
diff --git a/src/core/lib/slice/slice_hash_table.h b/src/core/lib/slice/slice_hash_table.h
new file mode 100644
index 0000000..d0c2712
--- /dev/null
+++ b/src/core/lib/slice/slice_hash_table.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GRPC_CORE_LIB_SLICE_SLICE_HASH_TABLE_H
+#define GRPC_CORE_LIB_SLICE_SLICE_HASH_TABLE_H
+
+#include "src/core/lib/transport/metadata.h"
+
+/** Hash table implementation.
+ *
+ * This implementation uses open addressing
+ * (https://en.wikipedia.org/wiki/Open_addressing) with quadratic
+ * probing (https://en.wikipedia.org/wiki/Quadratic_probing).
+ *
+ * The keys are \a grpc_slice objects.  The values are arbitrary pointers
+ * with a common vtable.
+ *
+ * Hash tables are intentionally immutable, to avoid the need for locking.
+ */
+
+typedef struct grpc_slice_hash_table grpc_slice_hash_table;
+
+typedef struct grpc_slice_hash_table_vtable {
+  void (*destroy_value)(grpc_exec_ctx *exec_ctx, void *value);
+  void *(*copy_value)(void *value);
+} grpc_slice_hash_table_vtable;
+
+typedef struct grpc_slice_hash_table_entry {
+  grpc_slice key;
+  void *value; /* Must not be NULL. */
+  const grpc_slice_hash_table_vtable *vtable;
+} grpc_slice_hash_table_entry;
+
+/** Creates a new hash table of containing \a entries, which is an array
+    of length \a num_entries.
+    Creates its own copy of all keys and values from \a entries. */
+grpc_slice_hash_table *grpc_slice_hash_table_create(
+    size_t num_entries, grpc_slice_hash_table_entry *entries);
+
+grpc_slice_hash_table *grpc_slice_hash_table_ref(grpc_slice_hash_table *table);
+void grpc_slice_hash_table_unref(grpc_exec_ctx *exec_ctx,
+                                 grpc_slice_hash_table *table);
+
+/** Returns the value from \a table associated with \a key.
+    Returns NULL if \a key is not found. */
+void *grpc_slice_hash_table_get(const grpc_slice_hash_table *table,
+                                const grpc_slice key);
+
+#endif /* GRPC_CORE_LIB_SLICE_SLICE_HASH_TABLE_H */
diff --git a/src/core/lib/slice/slice_intern.c b/src/core/lib/slice/slice_intern.c
new file mode 100644
index 0000000..1c00a2d
--- /dev/null
+++ b/src/core/lib/slice/slice_intern.c
@@ -0,0 +1,346 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/slice/slice_internal.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/iomgr/iomgr_internal.h" /* for iomgr_abort_on_leaks() */
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
+#include "src/core/lib/support/murmur_hash.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+#define LOG2_SHARD_COUNT 5
+#define SHARD_COUNT (1 << LOG2_SHARD_COUNT)
+#define INITIAL_SHARD_CAPACITY 8
+
+#define TABLE_IDX(hash, capacity) (((hash) >> LOG2_SHARD_COUNT) % (capacity))
+#define SHARD_IDX(hash) ((hash) & ((1 << LOG2_SHARD_COUNT) - 1))
+
+typedef struct interned_slice_refcount {
+  grpc_slice_refcount base;
+  grpc_slice_refcount sub;
+  size_t length;
+  gpr_atm refcnt;
+  uint32_t hash;
+  struct interned_slice_refcount *bucket_next;
+} interned_slice_refcount;
+
+typedef struct slice_shard {
+  gpr_mu mu;
+  interned_slice_refcount **strs;
+  size_t count;
+  size_t capacity;
+} slice_shard;
+
+/* hash seed: decided at initialization time */
+static uint32_t g_hash_seed;
+static int g_forced_hash_seed = 0;
+
+static slice_shard g_shards[SHARD_COUNT];
+
+typedef struct {
+  uint32_t hash;
+  uint32_t idx;
+} static_metadata_hash_ent;
+
+static static_metadata_hash_ent
+    static_metadata_hash[4 * GRPC_STATIC_MDSTR_COUNT];
+static uint32_t max_static_metadata_hash_probe;
+static uint32_t static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT];
+
+static void interned_slice_ref(void *p) {
+  interned_slice_refcount *s = p;
+  GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&s->refcnt, 1) > 0);
+}
+
+static void interned_slice_destroy(interned_slice_refcount *s) {
+  slice_shard *shard = &g_shards[SHARD_IDX(s->hash)];
+  gpr_mu_lock(&shard->mu);
+  GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt));
+  interned_slice_refcount **prev_next;
+  interned_slice_refcount *cur;
+  for (prev_next = &shard->strs[TABLE_IDX(s->hash, shard->capacity)],
+      cur = *prev_next;
+       cur != s; prev_next = &cur->bucket_next, cur = cur->bucket_next)
+    ;
+  *prev_next = cur->bucket_next;
+  shard->count--;
+  gpr_free(s);
+  gpr_mu_unlock(&shard->mu);
+}
+
+static void interned_slice_unref(grpc_exec_ctx *exec_ctx, void *p) {
+  interned_slice_refcount *s = p;
+  if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) {
+    interned_slice_destroy(s);
+  }
+}
+
+static void interned_slice_sub_ref(void *p) {
+  interned_slice_ref(((char *)p) - offsetof(interned_slice_refcount, sub));
+}
+
+static void interned_slice_sub_unref(grpc_exec_ctx *exec_ctx, void *p) {
+  interned_slice_unref(exec_ctx,
+                       ((char *)p) - offsetof(interned_slice_refcount, sub));
+}
+
+static uint32_t interned_slice_hash(grpc_slice slice) {
+  interned_slice_refcount *s = (interned_slice_refcount *)slice.refcount;
+  return s->hash;
+}
+
+static int interned_slice_eq(grpc_slice a, grpc_slice b) {
+  return a.refcount == b.refcount;
+}
+
+static const grpc_slice_refcount_vtable interned_slice_vtable = {
+    interned_slice_ref, interned_slice_unref, interned_slice_eq,
+    interned_slice_hash};
+static const grpc_slice_refcount_vtable interned_slice_sub_vtable = {
+    interned_slice_sub_ref, interned_slice_sub_unref,
+    grpc_slice_default_eq_impl, grpc_slice_default_hash_impl};
+
+static void grow_shard(slice_shard *shard) {
+  size_t capacity = shard->capacity * 2;
+  size_t i;
+  interned_slice_refcount **strtab;
+  interned_slice_refcount *s, *next;
+
+  GPR_TIMER_BEGIN("grow_strtab", 0);
+
+  strtab = gpr_zalloc(sizeof(interned_slice_refcount *) * capacity);
+
+  for (i = 0; i < shard->capacity; i++) {
+    for (s = shard->strs[i]; s; s = next) {
+      size_t idx = TABLE_IDX(s->hash, capacity);
+      next = s->bucket_next;
+      s->bucket_next = strtab[idx];
+      strtab[idx] = s;
+    }
+  }
+
+  gpr_free(shard->strs);
+  shard->strs = strtab;
+  shard->capacity = capacity;
+
+  GPR_TIMER_END("grow_strtab", 0);
+}
+
+static grpc_slice materialize(interned_slice_refcount *s) {
+  grpc_slice slice;
+  slice.refcount = &s->base;
+  slice.data.refcounted.bytes = (uint8_t *)(s + 1);
+  slice.data.refcounted.length = s->length;
+  return slice;
+}
+
+uint32_t grpc_slice_default_hash_impl(grpc_slice s) {
+  return gpr_murmur_hash3(GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s),
+                          g_hash_seed);
+}
+
+uint32_t grpc_static_slice_hash(grpc_slice s) {
+  return static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX(s)];
+}
+
+int grpc_static_slice_eq(grpc_slice a, grpc_slice b) {
+  return GRPC_STATIC_METADATA_INDEX(a) == GRPC_STATIC_METADATA_INDEX(b);
+}
+
+uint32_t grpc_slice_hash(grpc_slice s) {
+  return s.refcount == NULL ? grpc_slice_default_hash_impl(s)
+                            : s.refcount->vtable->hash(s);
+}
+
+grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice,
+                                          bool *returned_slice_is_different) {
+  if (GRPC_IS_STATIC_METADATA_STRING(slice)) {
+    return slice;
+  }
+
+  uint32_t hash = grpc_slice_hash(slice);
+  for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) {
+    static_metadata_hash_ent ent =
+        static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)];
+    if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT &&
+        grpc_slice_eq(grpc_static_slice_table[ent.idx], slice)) {
+      *returned_slice_is_different = true;
+      return grpc_static_slice_table[ent.idx];
+    }
+  }
+
+  return slice;
+}
+
+bool grpc_slice_is_interned(grpc_slice slice) {
+  return (slice.refcount && slice.refcount->vtable == &interned_slice_vtable) ||
+         GRPC_IS_STATIC_METADATA_STRING(slice);
+}
+
+grpc_slice grpc_slice_intern(grpc_slice slice) {
+  GPR_TIMER_BEGIN("grpc_slice_intern", 0);
+  if (GRPC_IS_STATIC_METADATA_STRING(slice)) {
+    GPR_TIMER_END("grpc_slice_intern", 0);
+    return slice;
+  }
+
+  uint32_t hash = grpc_slice_hash(slice);
+  for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) {
+    static_metadata_hash_ent ent =
+        static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)];
+    if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT &&
+        grpc_slice_eq(grpc_static_slice_table[ent.idx], slice)) {
+      GPR_TIMER_END("grpc_slice_intern", 0);
+      return grpc_static_slice_table[ent.idx];
+    }
+  }
+
+  interned_slice_refcount *s;
+  slice_shard *shard = &g_shards[SHARD_IDX(hash)];
+
+  gpr_mu_lock(&shard->mu);
+
+  /* search for an existing string */
+  size_t idx = TABLE_IDX(hash, shard->capacity);
+  for (s = shard->strs[idx]; s; s = s->bucket_next) {
+    if (s->hash == hash && grpc_slice_eq(slice, materialize(s))) {
+      if (gpr_atm_no_barrier_fetch_add(&s->refcnt, 1) == 0) {
+        /* If we get here, we've added a ref to something that was about to
+         * die - drop it immediately.
+         * The *only* possible path here (given the shard mutex) should be to
+         * drop from one ref back to zero - assert that with a CAS */
+        GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0));
+        /* and treat this as if we were never here... sshhh */
+      } else {
+        gpr_mu_unlock(&shard->mu);
+        GPR_TIMER_END("grpc_slice_intern", 0);
+        return materialize(s);
+      }
+    }
+  }
+
+  /* not found: create a new string */
+  /* string data goes after the internal_string header */
+  s = gpr_malloc(sizeof(*s) + GRPC_SLICE_LENGTH(slice));
+  gpr_atm_rel_store(&s->refcnt, 1);
+  s->length = GRPC_SLICE_LENGTH(slice);
+  s->hash = hash;
+  s->base.vtable = &interned_slice_vtable;
+  s->base.sub_refcount = &s->sub;
+  s->sub.vtable = &interned_slice_sub_vtable;
+  s->sub.sub_refcount = &s->sub;
+  s->bucket_next = shard->strs[idx];
+  shard->strs[idx] = s;
+  memcpy(s + 1, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice));
+
+  shard->count++;
+
+  if (shard->count > shard->capacity * 2) {
+    grow_shard(shard);
+  }
+
+  gpr_mu_unlock(&shard->mu);
+
+  GPR_TIMER_END("grpc_slice_intern", 0);
+  return materialize(s);
+}
+
+void grpc_test_only_set_slice_hash_seed(uint32_t seed) {
+  g_hash_seed = seed;
+  g_forced_hash_seed = 1;
+}
+
+void grpc_slice_intern_init(void) {
+  if (!g_forced_hash_seed) {
+    g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
+  }
+  for (size_t i = 0; i < SHARD_COUNT; i++) {
+    slice_shard *shard = &g_shards[i];
+    gpr_mu_init(&shard->mu);
+    shard->count = 0;
+    shard->capacity = INITIAL_SHARD_CAPACITY;
+    shard->strs = gpr_zalloc(sizeof(*shard->strs) * shard->capacity);
+  }
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(static_metadata_hash); i++) {
+    static_metadata_hash[i].hash = 0;
+    static_metadata_hash[i].idx = GRPC_STATIC_MDSTR_COUNT;
+  }
+  max_static_metadata_hash_probe = 0;
+  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
+    static_metadata_hash_values[i] =
+        grpc_slice_default_hash_impl(grpc_static_slice_table[i]);
+    for (size_t j = 0; j < GPR_ARRAY_SIZE(static_metadata_hash); j++) {
+      size_t slot = (static_metadata_hash_values[i] + j) %
+                    GPR_ARRAY_SIZE(static_metadata_hash);
+      if (static_metadata_hash[slot].idx == GRPC_STATIC_MDSTR_COUNT) {
+        static_metadata_hash[slot].hash = static_metadata_hash_values[i];
+        static_metadata_hash[slot].idx = (uint32_t)i;
+        if (j > max_static_metadata_hash_probe) {
+          max_static_metadata_hash_probe = (uint32_t)j;
+        }
+        break;
+      }
+    }
+  }
+}
+
+void grpc_slice_intern_shutdown(void) {
+  for (size_t i = 0; i < SHARD_COUNT; i++) {
+    slice_shard *shard = &g_shards[i];
+    gpr_mu_destroy(&shard->mu);
+    /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
+    if (shard->count != 0) {
+      gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata strings were leaked",
+              shard->count);
+      for (size_t j = 0; j < shard->capacity; j++) {
+        for (interned_slice_refcount *s = shard->strs[j]; s;
+             s = s->bucket_next) {
+          char *text =
+              grpc_dump_slice(materialize(s), GPR_DUMP_HEX | GPR_DUMP_ASCII);
+          gpr_log(GPR_DEBUG, "LEAKED: %s", text);
+          gpr_free(text);
+        }
+      }
+      if (grpc_iomgr_abort_on_leaks()) {
+        abort();
+      }
+    }
+    gpr_free(shard->strs);
+  }
+}
diff --git a/src/core/lib/slice/slice_internal.h b/src/core/lib/slice/slice_internal.h
index 6185333..6467b0a 100644
--- a/src/core/lib/slice/slice_internal.h
+++ b/src/core/lib/slice/slice_internal.h
@@ -46,4 +46,19 @@
 void grpc_slice_buffer_destroy_internal(grpc_exec_ctx *exec_ctx,
                                         grpc_slice_buffer *sb);
 
+/* Check if a slice is interned */
+bool grpc_slice_is_interned(grpc_slice slice);
+
+void grpc_slice_intern_init(void);
+void grpc_slice_intern_shutdown(void);
+void grpc_test_only_set_slice_hash_seed(uint32_t key);
+// if slice matches a static slice, returns the static slice
+// otherwise returns the passed in slice (without reffing it)
+// used for surface boundaries where we might receive an un-interned static
+// string
+grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice,
+                                          bool *returned_slice_is_different);
+uint32_t grpc_static_slice_hash(grpc_slice s);
+int grpc_static_slice_eq(grpc_slice a, grpc_slice b);
+
 #endif /* GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H */
diff --git a/src/core/lib/slice/slice_string_helpers.c b/src/core/lib/slice/slice_string_helpers.c
index 839c366..9969500 100644
--- a/src/core/lib/slice/slice_string_helpers.c
+++ b/src/core/lib/slice/slice_string_helpers.c
@@ -88,3 +88,8 @@
     grpc_slice_buffer_add_indexed(dst, grpc_slice_ref_internal(str));
   }
 }
+
+bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result) {
+  return gpr_parse_bytes_to_uint32((const char *)GRPC_SLICE_START_PTR(str),
+                                   GRPC_SLICE_LENGTH(str), result) != 0;
+}
diff --git a/src/core/lib/slice/slice_string_helpers.h b/src/core/lib/slice/slice_string_helpers.h
index 151c720..4a4deec 100644
--- a/src/core/lib/slice/slice_string_helpers.h
+++ b/src/core/lib/slice/slice_string_helpers.h
@@ -34,12 +34,15 @@
 #ifndef GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H
 #define GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H
 
+#include <stdbool.h>
 #include <stddef.h>
 
 #include <grpc/slice.h>
 #include <grpc/slice_buffer.h>
 #include <grpc/support/port_platform.h>
 
+#include "src/core/lib/support/string.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -51,6 +54,8 @@
  * should be a properly initialized instance. */
 void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst);
 
+bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/core/lib/slice/slice_traits.h b/src/core/lib/slice/slice_traits.h
new file mode 100644
index 0000000..8a283dc
--- /dev/null
+++ b/src/core/lib/slice/slice_traits.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SLICE_SLICE_TRAITS_H
+#define GRPC_CORE_LIB_SLICE_SLICE_TRAITS_H
+
+#include <grpc/slice.h>
+#include <stdbool.h>
+
+bool grpc_slice_is_legal_header(grpc_slice s);
+bool grpc_slice_is_legal_nonbin_header(grpc_slice s);
+bool grpc_slice_is_bin_suffixed(grpc_slice s);
+
+#endif /* GRPC_CORE_LIB_SLICE_SLICE_TRAITS_H */
diff --git a/src/core/lib/support/alloc.c b/src/core/lib/support/alloc.c
index 618c3f6..9973166 100644
--- a/src/core/lib/support/alloc.c
+++ b/src/core/lib/support/alloc.c
@@ -36,9 +36,19 @@
 #include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
 #include <stdlib.h>
+#include <string.h>
 #include "src/core/lib/profiling/timers.h"
 
-static gpr_allocation_functions g_alloc_functions = {malloc, realloc, free};
+static void *zalloc_with_calloc(size_t sz) { return calloc(sz, 1); }
+
+static void *zalloc_with_gpr_malloc(size_t sz) {
+  void *p = gpr_malloc(sz);
+  memset(p, 0, sz);
+  return p;
+}
+
+static gpr_allocation_functions g_alloc_functions = {malloc, zalloc_with_calloc,
+                                                     realloc, free};
 
 gpr_allocation_functions gpr_get_allocation_functions() {
   return g_alloc_functions;
@@ -48,6 +58,9 @@
   GPR_ASSERT(functions.malloc_fn != NULL);
   GPR_ASSERT(functions.realloc_fn != NULL);
   GPR_ASSERT(functions.free_fn != NULL);
+  if (functions.zalloc_fn == NULL) {
+    functions.zalloc_fn = zalloc_with_gpr_malloc;
+  }
   g_alloc_functions = functions;
 }
 
@@ -63,6 +76,18 @@
   return p;
 }
 
+void *gpr_zalloc(size_t size) {
+  void *p;
+  if (size == 0) return NULL;
+  GPR_TIMER_BEGIN("gpr_zalloc", 0);
+  p = g_alloc_functions.zalloc_fn(size);
+  if (!p) {
+    abort();
+  }
+  GPR_TIMER_END("gpr_zalloc", 0);
+  return p;
+}
+
 void gpr_free(void *p) {
   GPR_TIMER_BEGIN("gpr_free", 0);
   g_alloc_functions.free_fn(p);
diff --git a/src/core/lib/support/cmdline.c b/src/core/lib/support/cmdline.c
index d474986..88a65a8 100644
--- a/src/core/lib/support/cmdline.c
+++ b/src/core/lib/support/cmdline.c
@@ -71,8 +71,7 @@
 static int normal_state(gpr_cmdline *cl, char *arg);
 
 gpr_cmdline *gpr_cmdline_create(const char *description) {
-  gpr_cmdline *cl = gpr_malloc(sizeof(gpr_cmdline));
-  memset(cl, 0, sizeof(gpr_cmdline));
+  gpr_cmdline *cl = gpr_zalloc(sizeof(gpr_cmdline));
 
   cl->description = description;
   cl->state = normal_state;
@@ -101,8 +100,7 @@
     GPR_ASSERT(0 != strcmp(a->name, name));
   }
 
-  a = gpr_malloc(sizeof(arg));
-  memset(a, 0, sizeof(arg));
+  a = gpr_zalloc(sizeof(arg));
   a->name = name;
   a->help = help;
   a->type = type;
diff --git a/src/core/lib/support/cpu_posix.c b/src/core/lib/support/cpu_posix.c
index 667bde7..245f12f 100644
--- a/src/core/lib/support/cpu_posix.c
+++ b/src/core/lib/support/cpu_posix.c
@@ -41,6 +41,7 @@
 
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
 
 static __thread char magic_thread_local;
 
@@ -60,18 +61,12 @@
   return (unsigned)ncpus;
 }
 
-/* This is a cheap, but good enough, pointer hash for sharding things: */
-static size_t shard_ptr(const void *info) {
-  size_t x = (size_t)info;
-  return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) % gpr_cpu_num_cores();
-}
-
 unsigned gpr_cpu_current_cpu(void) {
   /* NOTE: there's no way I know to return the actual cpu index portably...
      most code that's using this is using it to shard across work queues though,
      so here we use thread identity instead to achieve a similar though not
      identical effect */
-  return (unsigned)shard_ptr(&magic_thread_local);
+  return (unsigned)GPR_HASH_POINTER(&magic_thread_local, gpr_cpu_num_cores());
 }
 
 #endif /* GPR_CPU_POSIX */
diff --git a/src/core/lib/support/histogram.c b/src/core/lib/support/histogram.c
index 7b016bb..ba8176b 100644
--- a/src/core/lib/support/histogram.c
+++ b/src/core/lib/support/histogram.c
@@ -102,8 +102,7 @@
   h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
   GPR_ASSERT(h->num_buckets > 1);
   GPR_ASSERT(h->num_buckets < 100000000);
-  h->buckets = gpr_malloc(sizeof(uint32_t) * h->num_buckets);
-  memset(h->buckets, 0, sizeof(uint32_t) * h->num_buckets);
+  h->buckets = gpr_zalloc(sizeof(uint32_t) * h->num_buckets);
   return h;
 }
 
diff --git a/src/core/lib/support/log_posix.c b/src/core/lib/support/log_posix.c
index f972da0..79458dd 100644
--- a/src/core/lib/support/log_posix.c
+++ b/src/core/lib/support/log_posix.c
@@ -37,6 +37,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 #include <pthread.h>
 #include <stdarg.h>
@@ -93,10 +94,13 @@
     strcpy(time_buffer, "error:strftime");
   }
 
-  fprintf(stderr, "%s%s.%09d %7tu %s:%d] %s\n",
-          gpr_log_severity_string(args->severity), time_buffer,
-          (int)(now.tv_nsec), gettid(), display_file, args->line,
-          args->message);
+  char *prefix;
+  gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]",
+               gpr_log_severity_string(args->severity), time_buffer,
+               (int)(now.tv_nsec), gettid(), display_file, args->line);
+
+  fprintf(stderr, "%-70s %s\n", prefix, args->message);
+  gpr_free(prefix);
 }
 
 #endif /* defined(GPR_POSIX_LOG) */
diff --git a/src/core/lib/support/spinlock.h b/src/core/lib/support/spinlock.h
new file mode 100644
index 0000000..d8c7c5f
--- /dev/null
+++ b/src/core/lib/support/spinlock.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SUPPORT_SPINLOCK_H
+#define GRPC_CORE_LIB_SUPPORT_SPINLOCK_H
+
+#include <grpc/support/atm.h>
+
+/* Simple spinlock. No backoff strategy, gpr_spinlock_lock is almost always
+   a concurrency code smell. */
+typedef struct { gpr_atm atm; } gpr_spinlock;
+
+#define GPR_SPINLOCK_INITIALIZER ((gpr_spinlock){0})
+#define GPR_SPINLOCK_STATIC_INITIALIZER \
+  { 0 }
+#define gpr_spinlock_trylock(lock) (gpr_atm_acq_cas(&(lock)->atm, 0, 1))
+#define gpr_spinlock_unlock(lock) (gpr_atm_rel_store(&(lock)->atm, 0))
+#define gpr_spinlock_lock(lock) \
+  do {                          \
+  } while (!gpr_spinlock_trylock((lock)))
+
+#endif /* GRPC_CORE_LIB_SUPPORT_SPINLOCK_H */
diff --git a/src/core/lib/support/subprocess_posix.c b/src/core/lib/support/subprocess_posix.c
index 4247a1c..ed653b9 100644
--- a/src/core/lib/support/subprocess_posix.c
+++ b/src/core/lib/support/subprocess_posix.c
@@ -76,8 +76,7 @@
     _exit(1);
     return NULL;
   } else {
-    r = gpr_malloc(sizeof(gpr_subprocess));
-    memset(r, 0, sizeof(*r));
+    r = gpr_zalloc(sizeof(gpr_subprocess));
     r->pid = pid;
     return r;
   }
diff --git a/src/core/lib/support/sync_posix.c b/src/core/lib/support/sync_posix.c
index dcb0969..16e7d6e 100644
--- a/src/core/lib/support/sync_posix.c
+++ b/src/core/lib/support/sync_posix.c
@@ -42,11 +42,20 @@
 #include <time.h>
 #include "src/core/lib/profiling/timers.h"
 
+#ifdef GPR_LOW_LEVEL_COUNTERS
+gpr_atm gpr_mu_locks = 0;
+gpr_atm gpr_counter_atm_cas = 0;
+gpr_atm gpr_counter_atm_add = 0;
+#endif
+
 void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); }
 
 void gpr_mu_destroy(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_destroy(mu) == 0); }
 
 void gpr_mu_lock(gpr_mu* mu) {
+#ifdef GPR_LOW_LEVEL_COUNTERS
+  GPR_ATM_INC_COUNTER(gpr_mu_locks);
+#endif
   GPR_TIMER_BEGIN("gpr_mu_lock", 0);
   GPR_ASSERT(pthread_mutex_lock(mu) == 0);
   GPR_TIMER_END("gpr_mu_lock", 0);
diff --git a/src/core/lib/support/time_windows.c b/src/core/lib/support/time_windows.c
index 6459732..7b94a5b 100644
--- a/src/core/lib/support/time_windows.c
+++ b/src/core/lib/support/time_windows.c
@@ -56,7 +56,7 @@
   g_time_scale = 1.0 / (double)frequency.QuadPart;
 }
 
-gpr_timespec gpr_now(gpr_clock_type clock) {
+static gpr_timespec now_impl(gpr_clock_type clock) {
   gpr_timespec now_tv;
   LONGLONG diff;
   struct _timeb now_tb;
@@ -84,6 +84,12 @@
   return now_tv;
 }
 
+gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl;
+
+gpr_timespec gpr_now(gpr_clock_type clock_type) {
+  return gpr_now_impl(clock_type);
+}
+
 void gpr_sleep_until(gpr_timespec until) {
   gpr_timespec now;
   gpr_timespec delta;
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index cac5737..cc57654 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -56,13 +56,15 @@
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/surface/validate_metadata.h"
+#include "src/core/lib/transport/error_utils.h"
 #include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "src/core/lib/transport/transport.h"
 
 /** The maximum number of concurrent batches possible.
     Based upon the maximum number of individually queueable ops in the batch
-   api:
+    api:
       - initial metadata send
       - message send
       - status/close send (depending on client/server)
@@ -84,26 +86,43 @@
   /* Status came from 'the wire' - or somewhere below the surface
      layer */
   STATUS_FROM_WIRE,
-  /* Status was created by some internal channel stack operation */
+  /* Status was created by some internal channel stack operation: must come via
+     add_batch_error */
   STATUS_FROM_CORE,
+  /* Status was created by some surface error */
+  STATUS_FROM_SURFACE,
   /* Status came from the server sending status */
   STATUS_FROM_SERVER_STATUS,
   STATUS_SOURCE_COUNT
 } status_source;
 
 typedef struct {
-  uint8_t is_set;
-  grpc_status_code code;
-  grpc_mdstr *details;
+  bool is_set;
+  grpc_error *error;
 } received_status;
 
+static gpr_atm pack_received_status(received_status r) {
+  return r.is_set ? (1 | (gpr_atm)r.error) : 0;
+}
+
+static received_status unpack_received_status(gpr_atm atm) {
+  return (atm & 1) == 0
+             ? (received_status){.is_set = false, .error = GRPC_ERROR_NONE}
+             : (received_status){.is_set = true,
+                                 .error = (grpc_error *)(atm & ~(gpr_atm)1)};
+}
+
+#define MAX_ERRORS_PER_BATCH 4
+
 typedef struct batch_control {
   grpc_call *call;
   grpc_cq_completion cq_completion;
   grpc_closure finish_batch;
   void *notify_tag;
   gpr_refcount steps_to_complete;
-  grpc_error *error;
+
+  grpc_error *errors[MAX_ERRORS_PER_BATCH];
+  gpr_atm num_errors;
 
   uint8_t send_initial_metadata;
   uint8_t send_message;
@@ -134,8 +153,6 @@
   bool destroy_called;
   /** flag indicating that cancellation is inherited */
   bool cancellation_is_inherited;
-  /** bitmask of live batches */
-  uint8_t used_batches;
   /** which ops are in-flight */
   bool sent_initial_metadata;
   bool sending_message;
@@ -157,8 +174,8 @@
      Element 0 is initial metadata, element 1 is trailing metadata. */
   grpc_metadata_array *buffered_metadata[2];
 
-  /* Received call statuses from various sources */
-  received_status status[STATUS_SOURCE_COUNT];
+  /* Packed received call statuses from various sources */
+  gpr_atm status[STATUS_SOURCE_COUNT];
 
   /* Call data useful used for reporting. Only valid after the call has
    * completed */
@@ -185,6 +202,7 @@
   grpc_call *sibling_prev;
 
   grpc_slice_buffer_stream sending_stream;
+
   grpc_byte_stream *receiving_stream;
   grpc_byte_buffer **receiving_buffer;
   grpc_slice receiving_slice;
@@ -196,8 +214,7 @@
   union {
     struct {
       grpc_status_code *status;
-      char **status_details;
-      size_t *status_details_capacity;
+      grpc_slice *status_details;
     } client;
     struct {
       int *cancelled;
@@ -207,6 +224,8 @@
   void *saved_receiving_stream_ready_bctlp;
 };
 
+int grpc_call_error_trace = 0;
+
 #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
 #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
 #define CALL_ELEM_FROM_CALL(call, idx) \
@@ -216,28 +235,45 @@
 
 static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
                        grpc_transport_stream_op *op);
-static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
-                                          grpc_status_code status,
-                                          const char *description);
-static grpc_call_error close_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
-                                         grpc_status_code status,
-                                         const char *description);
+static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
+                               status_source source, grpc_status_code status,
+                               const char *description);
+static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
+                              status_source source, grpc_error *error);
 static void destroy_call(grpc_exec_ctx *exec_ctx, void *call_stack,
                          grpc_error *error);
 static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
                                   grpc_error *error);
+static void get_final_status(grpc_call *call,
+                             void (*set_value)(grpc_status_code code,
+                                               void *user_data),
+                             void *set_value_user_data, grpc_slice *details);
+static void set_status_value_directly(grpc_status_code status, void *dest);
+static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                                  status_source source, grpc_error *error);
+static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl);
+static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl);
+static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
+                            grpc_error *error, bool has_cancelled);
+
+static void add_init_error(grpc_error **composite, grpc_error *new) {
+  if (new == GRPC_ERROR_NONE) return;
+  if (*composite == GRPC_ERROR_NONE)
+    *composite = GRPC_ERROR_CREATE("Call creation failed");
+  *composite = grpc_error_add_child(*composite, new);
+}
 
 grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
                              const grpc_call_create_args *args,
                              grpc_call **out_call) {
   size_t i, j;
+  grpc_error *error = GRPC_ERROR_NONE;
   grpc_channel_stack *channel_stack =
       grpc_channel_get_channel_stack(args->channel);
   grpc_call *call;
   GPR_TIMER_BEGIN("grpc_call_create", 0);
-  call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
+  call = gpr_zalloc(sizeof(grpc_call) + channel_stack->call_stack_size);
   *out_call = call;
-  memset(call, 0, sizeof(grpc_call));
   gpr_mu_init(&call->mu);
   call->channel = args->channel;
   call->cq = args->cq;
@@ -246,14 +282,16 @@
   /* Always support no compression */
   GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
   call->is_client = args->server_transport_data == NULL;
-  grpc_mdstr *path = NULL;
+  grpc_slice path = grpc_empty_slice();
   if (call->is_client) {
     GPR_ASSERT(args->add_initial_metadata_count <
                MAX_SEND_EXTRA_METADATA_COUNT);
     for (i = 0; i < args->add_initial_metadata_count; i++) {
       call->send_extra_metadata[i].md = args->add_initial_metadata[i];
-      if (args->add_initial_metadata[i]->key == GRPC_MDSTR_PATH) {
-        path = GRPC_MDSTR_REF(args->add_initial_metadata[i]->value);
+      if (grpc_slice_eq(GRPC_MDKEY(args->add_initial_metadata[i]),
+                        GRPC_MDSTR_PATH)) {
+        path = grpc_slice_ref_internal(
+            GRPC_MDVALUE(args->add_initial_metadata[i]));
       }
     }
     call->send_extra_metadata_count = (int)args->add_initial_metadata_count;
@@ -287,12 +325,18 @@
     /* TODO(ctiller): This should change to use the appropriate census start_op
      * call. */
     if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) {
-      GPR_ASSERT(args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT);
+      if (0 == (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT)) {
+        add_init_error(&error,
+                       GRPC_ERROR_CREATE("Census tracing propagation requested "
+                                         "without Census context propagation"));
+      }
       grpc_call_context_set(
           call, GRPC_CONTEXT_TRACING,
           args->parent_call->context[GRPC_CONTEXT_TRACING].value, NULL);
-    } else {
-      GPR_ASSERT(args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT);
+    } else if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT) {
+      add_init_error(&error,
+                     GRPC_ERROR_CREATE("Census context propagation requested "
+                                       "without Census tracing propagation"));
     }
     if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
       call->cancellation_is_inherited = 1;
@@ -315,15 +359,14 @@
 
   GRPC_CHANNEL_INTERNAL_REF(args->channel, "call");
   /* initial refcount dropped by grpc_call_destroy */
-  grpc_error *error = grpc_call_stack_init(
-      exec_ctx, channel_stack, 1, destroy_call, call, call->context,
-      args->server_transport_data, path, call->start_time, send_deadline,
-      CALL_STACK_FROM_CALL(call));
+  add_init_error(&error, grpc_call_stack_init(exec_ctx, channel_stack, 1,
+                                              destroy_call, call, call->context,
+                                              args->server_transport_data, path,
+                                              call->start_time, send_deadline,
+                                              CALL_STACK_FROM_CALL(call)));
   if (error != GRPC_ERROR_NONE) {
-    grpc_status_code status;
-    const char *error_str;
-    grpc_error_get_status(error, &status, &error_str);
-    close_with_status(exec_ctx, call, status, error_str);
+    cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
+                      GRPC_ERROR_REF(error));
   }
   if (args->cq != NULL) {
     GPR_ASSERT(
@@ -342,7 +385,7 @@
         exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent);
   }
 
-  if (path != NULL) GRPC_MDSTR_UNREF(exec_ctx, path);
+  grpc_slice_unref_internal(exec_ctx, path);
 
   GPR_TIMER_END("grpc_call_create", 0);
   return error;
@@ -377,24 +420,6 @@
   GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
 }
 
-static void get_final_status(grpc_call *call,
-                             void (*set_value)(grpc_status_code code,
-                                               void *user_data),
-                             void *set_value_user_data) {
-  int i;
-  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
-    if (call->status[i].is_set) {
-      set_value(call->status[i].code, set_value_user_data);
-      return;
-    }
-  }
-  if (call->is_client) {
-    set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
-  } else {
-    set_value(GRPC_STATUS_OK, set_value_user_data);
-  }
-}
-
 static void set_status_value_directly(grpc_status_code status, void *dest);
 static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
                          grpc_error *error) {
@@ -410,11 +435,6 @@
     grpc_byte_stream_destroy(exec_ctx, c->receiving_stream);
   }
   gpr_mu_destroy(&c->mu);
-  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
-    if (c->status[i].details) {
-      GRPC_MDSTR_UNREF(exec_ctx, c->status[i].details);
-    }
-  }
   for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
     GRPC_MDELEM_UNREF(exec_ctx, c->send_extra_metadata[ii].md);
   }
@@ -428,285 +448,21 @@
   }
   grpc_channel *channel = c->channel;
 
-  get_final_status(call, set_status_value_directly,
-                   &c->final_info.final_status);
+  get_final_status(call, set_status_value_directly, &c->final_info.final_status,
+                   NULL);
   c->final_info.stats.latency =
       gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
 
+  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+    GRPC_ERROR_UNREF(
+        unpack_received_status(gpr_atm_no_barrier_load(&c->status[i])).error);
+  }
+
   grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c);
   GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call");
   GPR_TIMER_END("destroy_call", 0);
 }
 
-static void set_status_code(grpc_call *call, status_source source,
-                            uint32_t status) {
-  if (call->status[source].is_set) return;
-
-  call->status[source].is_set = 1;
-  call->status[source].code = (grpc_status_code)status;
-}
-
-static void set_status_details(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                               status_source source, grpc_mdstr *status) {
-  if (call->status[source].details != NULL) {
-    GRPC_MDSTR_UNREF(exec_ctx, status);
-  } else {
-    call->status[source].details = status;
-  }
-}
-
-static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                                  status_source source, grpc_error *error) {
-  grpc_status_code status;
-  const char *msg;
-  grpc_error_get_status(error, &status, &msg);
-  set_status_code(call, source, (uint32_t)status);
-  set_status_details(exec_ctx, call, source, grpc_mdstr_from_string(msg));
-}
-
-static void set_incoming_compression_algorithm(
-    grpc_call *call, grpc_compression_algorithm algo) {
-  GPR_ASSERT(algo < GRPC_COMPRESS_ALGORITHMS_COUNT);
-  call->incoming_compression_algorithm = algo;
-}
-
-grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
-    grpc_call *call) {
-  grpc_compression_algorithm algorithm;
-  gpr_mu_lock(&call->mu);
-  algorithm = call->incoming_compression_algorithm;
-  gpr_mu_unlock(&call->mu);
-  return algorithm;
-}
-
-static grpc_compression_algorithm compression_algorithm_for_level_locked(
-    grpc_call *call, grpc_compression_level level) {
-  return grpc_compression_algorithm_for_level(level,
-                                              call->encodings_accepted_by_peer);
-}
-
-uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
-  uint32_t flags;
-  gpr_mu_lock(&call->mu);
-  flags = call->test_only_last_message_flags;
-  gpr_mu_unlock(&call->mu);
-  return flags;
-}
-
-static void destroy_encodings_accepted_by_peer(void *p) { return; }
-
-static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
-                                           grpc_call *call, grpc_mdelem *mdel) {
-  size_t i;
-  grpc_compression_algorithm algorithm;
-  grpc_slice_buffer accept_encoding_parts;
-  grpc_slice accept_encoding_slice;
-  void *accepted_user_data;
-
-  accepted_user_data =
-      grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
-  if (accepted_user_data != NULL) {
-    call->encodings_accepted_by_peer =
-        (uint32_t)(((uintptr_t)accepted_user_data) - 1);
-    return;
-  }
-
-  accept_encoding_slice = mdel->value->slice;
-  grpc_slice_buffer_init(&accept_encoding_parts);
-  grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
-
-  /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already
-   * zeroes the whole grpc_call */
-  /* Always support no compression */
-  GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
-  for (i = 0; i < accept_encoding_parts.count; i++) {
-    const grpc_slice *accept_encoding_entry_slice =
-        &accept_encoding_parts.slices[i];
-    if (grpc_compression_algorithm_parse(
-            (const char *)GRPC_SLICE_START_PTR(*accept_encoding_entry_slice),
-            GRPC_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
-      GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
-    } else {
-      char *accept_encoding_entry_str =
-          grpc_dump_slice(*accept_encoding_entry_slice, GPR_DUMP_ASCII);
-      gpr_log(GPR_ERROR,
-              "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
-              accept_encoding_entry_str);
-      gpr_free(accept_encoding_entry_str);
-    }
-  }
-
-  grpc_slice_buffer_destroy_internal(exec_ctx, &accept_encoding_parts);
-
-  grpc_mdelem_set_user_data(
-      mdel, destroy_encodings_accepted_by_peer,
-      (void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
-}
-
-uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
-  uint32_t encodings_accepted_by_peer;
-  gpr_mu_lock(&call->mu);
-  encodings_accepted_by_peer = call->encodings_accepted_by_peer;
-  gpr_mu_unlock(&call->mu);
-  return encodings_accepted_by_peer;
-}
-
-static void get_final_details(grpc_call *call, char **out_details,
-                              size_t *out_details_capacity) {
-  int i;
-  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
-    if (call->status[i].is_set) {
-      if (call->status[i].details) {
-        grpc_slice details = call->status[i].details->slice;
-        size_t len = GRPC_SLICE_LENGTH(details);
-        if (len + 1 > *out_details_capacity) {
-          *out_details_capacity =
-              GPR_MAX(len + 1, *out_details_capacity * 3 / 2);
-          *out_details = gpr_realloc(*out_details, *out_details_capacity);
-        }
-        memcpy(*out_details, GRPC_SLICE_START_PTR(details), len);
-        (*out_details)[len] = 0;
-      } else {
-        goto no_details;
-      }
-      return;
-    }
-  }
-
-no_details:
-  if (0 == *out_details_capacity) {
-    *out_details_capacity = 8;
-    *out_details = gpr_malloc(*out_details_capacity);
-  }
-  **out_details = 0;
-}
-
-static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
-  return (grpc_linked_mdelem *)&md->internal_data;
-}
-
-static grpc_metadata *get_md_elem(grpc_metadata *metadata,
-                                  grpc_metadata *additional_metadata, int i,
-                                  int count) {
-  grpc_metadata *res =
-      i < count ? &metadata[i] : &additional_metadata[i - count];
-  GPR_ASSERT(res);
-  return res;
-}
-
-static int prepare_application_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_call *call, int count,
-    grpc_metadata *metadata, int is_trailing, int prepend_extra_metadata,
-    grpc_metadata *additional_metadata, int additional_metadata_count) {
-  int total_count = count + additional_metadata_count;
-  int i;
-  grpc_metadata_batch *batch =
-      &call->metadata_batch[0 /* is_receiving */][is_trailing];
-  for (i = 0; i < total_count; i++) {
-    const grpc_metadata *md =
-        get_md_elem(metadata, additional_metadata, i, count);
-    grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
-    GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
-    l->md = grpc_mdelem_from_string_and_buffer(
-        exec_ctx, md->key, (const uint8_t *)md->value, md->value_length);
-    if (!grpc_header_key_is_legal(grpc_mdstr_as_c_string(l->md->key),
-                                  GRPC_MDSTR_LENGTH(l->md->key))) {
-      gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s",
-              grpc_mdstr_as_c_string(l->md->key));
-      break;
-    } else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key),
-                                      GRPC_MDSTR_LENGTH(l->md->key)) &&
-               !grpc_header_nonbin_value_is_legal(
-                   grpc_mdstr_as_c_string(l->md->value),
-                   GRPC_MDSTR_LENGTH(l->md->value))) {
-      gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
-      break;
-    }
-  }
-  if (i != total_count) {
-    for (int j = 0; j <= i; j++) {
-      const grpc_metadata *md =
-          get_md_elem(metadata, additional_metadata, j, count);
-      grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
-      GRPC_MDELEM_UNREF(exec_ctx, l->md);
-    }
-    return 0;
-  }
-  if (prepend_extra_metadata) {
-    if (call->send_extra_metadata_count == 0) {
-      prepend_extra_metadata = 0;
-    } else {
-      for (i = 1; i < call->send_extra_metadata_count; i++) {
-        call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1];
-      }
-      for (i = 0; i < call->send_extra_metadata_count - 1; i++) {
-        call->send_extra_metadata[i].next = &call->send_extra_metadata[i + 1];
-      }
-    }
-  }
-  for (i = 1; i < total_count; i++) {
-    grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count);
-    grpc_metadata *prev_md =
-        get_md_elem(metadata, additional_metadata, i - 1, count);
-    linked_from_md(md)->prev = linked_from_md(prev_md);
-  }
-  for (i = 0; i < total_count - 1; i++) {
-    grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count);
-    grpc_metadata *next_md =
-        get_md_elem(metadata, additional_metadata, i + 1, count);
-    linked_from_md(md)->next = linked_from_md(next_md);
-  }
-
-  switch (prepend_extra_metadata * 2 + (total_count != 0)) {
-    case 0:
-      /* no prepend, no metadata => nothing to do */
-      batch->list.head = batch->list.tail = NULL;
-      break;
-    case 1: {
-      /* metadata, but no prepend */
-      grpc_metadata *first_md =
-          get_md_elem(metadata, additional_metadata, 0, count);
-      grpc_metadata *last_md =
-          get_md_elem(metadata, additional_metadata, total_count - 1, count);
-      batch->list.head = linked_from_md(first_md);
-      batch->list.tail = linked_from_md(last_md);
-      batch->list.head->prev = NULL;
-      batch->list.tail->next = NULL;
-      break;
-    }
-    case 2:
-      /* prepend, but no md */
-      batch->list.head = &call->send_extra_metadata[0];
-      batch->list.tail =
-          &call->send_extra_metadata[call->send_extra_metadata_count - 1];
-      batch->list.head->prev = NULL;
-      batch->list.tail->next = NULL;
-      call->send_extra_metadata_count = 0;
-      break;
-    case 3: {
-      /* prepend AND md */
-      grpc_metadata *first_md =
-          get_md_elem(metadata, additional_metadata, 0, count);
-      grpc_metadata *last_md =
-          get_md_elem(metadata, additional_metadata, total_count - 1, count);
-      batch->list.head = &call->send_extra_metadata[0];
-      call->send_extra_metadata[call->send_extra_metadata_count - 1].next =
-          linked_from_md(first_md);
-      linked_from_md(first_md)->prev =
-          &call->send_extra_metadata[call->send_extra_metadata_count - 1];
-      batch->list.tail = linked_from_md(last_md);
-      batch->list.head->prev = NULL;
-      batch->list.tail->next = NULL;
-      call->send_extra_metadata_count = 0;
-      break;
-    }
-    default:
-      GPR_UNREACHABLE_CODE(return 0);
-  }
-
-  return 1;
-}
-
 void grpc_call_destroy(grpc_call *c) {
   int cancel;
   grpc_call *parent = c->parent;
@@ -734,7 +490,10 @@
   c->destroy_called = 1;
   cancel = !c->received_final_op;
   gpr_mu_unlock(&c->mu);
-  if (cancel) grpc_call_cancel(c, NULL);
+  if (cancel) {
+    cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
+                      GRPC_ERROR_CANCELLED);
+  }
   GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
   grpc_exec_ctx_finish(&exec_ctx);
   GPR_TIMER_END("grpc_call_destroy", 0);
@@ -743,121 +502,13 @@
 grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
   GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved));
   GPR_ASSERT(!reserved);
-  return grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, "Cancelled",
-                                      NULL);
-}
-
-grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
-                                             grpc_status_code status,
-                                             const char *description,
-                                             void *reserved) {
-  grpc_call_error r;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GRPC_API_TRACE(
-      "grpc_call_cancel_with_status("
-      "c=%p, status=%d, description=%s, reserved=%p)",
-      4, (c, (int)status, description, reserved));
-  GPR_ASSERT(reserved == NULL);
-  gpr_mu_lock(&c->mu);
-  r = cancel_with_status(&exec_ctx, c, status, description);
-  gpr_mu_unlock(&c->mu);
+  cancel_with_error(&exec_ctx, call, STATUS_FROM_API_OVERRIDE,
+                    GRPC_ERROR_CANCELLED);
   grpc_exec_ctx_finish(&exec_ctx);
-  return r;
-}
-
-typedef struct termination_closure {
-  grpc_closure closure;
-  grpc_call *call;
-  grpc_error *error;
-  enum { TC_CANCEL, TC_CLOSE } type;
-  grpc_transport_stream_op op;
-} termination_closure;
-
-static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp,
-                             grpc_error *error) {
-  termination_closure *tc = tcp;
-  switch (tc->type) {
-    case TC_CANCEL:
-      GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "cancel");
-      break;
-    case TC_CLOSE:
-      GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "close");
-      break;
-  }
-  GRPC_ERROR_UNREF(tc->error);
-  gpr_free(tc);
-}
-
-static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) {
-  termination_closure *tc = tcp;
-  memset(&tc->op, 0, sizeof(tc->op));
-  tc->op.cancel_error = tc->error;
-  /* reuse closure to catch completion */
-  grpc_closure_init(&tc->closure, done_termination, tc,
-                    grpc_schedule_on_exec_ctx);
-  tc->op.on_complete = &tc->closure;
-  execute_op(exec_ctx, tc->call, &tc->op);
-}
-
-static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) {
-  termination_closure *tc = tcp;
-  memset(&tc->op, 0, sizeof(tc->op));
-  tc->op.close_error = tc->error;
-  /* reuse closure to catch completion */
-  grpc_closure_init(&tc->closure, done_termination, tc,
-                    grpc_schedule_on_exec_ctx);
-  tc->op.on_complete = &tc->closure;
-  execute_op(exec_ctx, tc->call, &tc->op);
-}
-
-static grpc_call_error terminate_with_status(grpc_exec_ctx *exec_ctx,
-                                             termination_closure *tc) {
-  set_status_from_error(exec_ctx, tc->call, STATUS_FROM_API_OVERRIDE,
-                        tc->error);
-
-  if (tc->type == TC_CANCEL) {
-    grpc_closure_init(&tc->closure, send_cancel, tc, grpc_schedule_on_exec_ctx);
-    GRPC_CALL_INTERNAL_REF(tc->call, "cancel");
-  } else if (tc->type == TC_CLOSE) {
-    grpc_closure_init(&tc->closure, send_close, tc, grpc_schedule_on_exec_ctx);
-    GRPC_CALL_INTERNAL_REF(tc->call, "close");
-  }
-  grpc_closure_sched(exec_ctx, &tc->closure, GRPC_ERROR_NONE);
   return GRPC_CALL_OK;
 }
 
-static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
-                                          grpc_status_code status,
-                                          const char *description) {
-  GPR_ASSERT(status != GRPC_STATUS_OK);
-  termination_closure *tc = gpr_malloc(sizeof(*tc));
-  memset(tc, 0, sizeof(termination_closure));
-  tc->type = TC_CANCEL;
-  tc->call = c;
-  tc->error = grpc_error_set_int(
-      grpc_error_set_str(GRPC_ERROR_CREATE(description),
-                         GRPC_ERROR_STR_GRPC_MESSAGE, description),
-      GRPC_ERROR_INT_GRPC_STATUS, status);
-
-  return terminate_with_status(exec_ctx, tc);
-}
-
-static grpc_call_error close_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
-                                         grpc_status_code status,
-                                         const char *description) {
-  GPR_ASSERT(status != GRPC_STATUS_OK);
-  termination_closure *tc = gpr_malloc(sizeof(*tc));
-  memset(tc, 0, sizeof(termination_closure));
-  tc->type = TC_CLOSE;
-  tc->call = c;
-  tc->error = grpc_error_set_int(
-      grpc_error_set_str(GRPC_ERROR_CREATE(description),
-                         GRPC_ERROR_STR_GRPC_MESSAGE, description),
-      GRPC_ERROR_INT_GRPC_STATUS, status);
-
-  return terminate_with_status(exec_ctx, tc);
-}
-
 static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
                        grpc_transport_stream_op *op) {
   grpc_call_element *elem;
@@ -889,25 +540,341 @@
   return CALL_FROM_TOP_ELEM(elem);
 }
 
+/*******************************************************************************
+ * CANCELLATION
+ */
+
+grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
+                                             grpc_status_code status,
+                                             const char *description,
+                                             void *reserved) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GRPC_API_TRACE(
+      "grpc_call_cancel_with_status("
+      "c=%p, status=%d, description=%s, reserved=%p)",
+      4, (c, (int)status, description, reserved));
+  GPR_ASSERT(reserved == NULL);
+  gpr_mu_lock(&c->mu);
+  cancel_with_status(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, status,
+                     description);
+  gpr_mu_unlock(&c->mu);
+  grpc_exec_ctx_finish(&exec_ctx);
+  return GRPC_CALL_OK;
+}
+
+typedef struct termination_closure {
+  grpc_closure closure;
+  grpc_call *call;
+  grpc_transport_stream_op op;
+} termination_closure;
+
+static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp,
+                             grpc_error *error) {
+  termination_closure *tc = tcp;
+  GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "termination");
+  gpr_free(tc);
+}
+
+static void send_termination(grpc_exec_ctx *exec_ctx, void *tcp,
+                             grpc_error *error) {
+  termination_closure *tc = tcp;
+  memset(&tc->op, 0, sizeof(tc->op));
+  tc->op.cancel_error = GRPC_ERROR_REF(error);
+  /* reuse closure to catch completion */
+  tc->op.on_complete = grpc_closure_init(&tc->closure, done_termination, tc,
+                                         grpc_schedule_on_exec_ctx);
+  execute_op(exec_ctx, tc->call, &tc->op);
+}
+
+static void terminate_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
+                                 grpc_error *error) {
+  termination_closure *tc = gpr_malloc(sizeof(*tc));
+  memset(tc, 0, sizeof(*tc));
+  tc->call = c;
+  GRPC_CALL_INTERNAL_REF(tc->call, "termination");
+  grpc_closure_sched(exec_ctx, grpc_closure_init(&tc->closure, send_termination,
+                                                 tc, grpc_schedule_on_exec_ctx),
+                     error);
+}
+
+static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
+                              status_source source, grpc_error *error) {
+  set_status_from_error(exec_ctx, c, source, GRPC_ERROR_REF(error));
+  terminate_with_error(exec_ctx, c, error);
+}
+
+static grpc_error *error_from_status(grpc_status_code status,
+                                     const char *description) {
+  return grpc_error_set_int(
+      grpc_error_set_str(GRPC_ERROR_CREATE(description),
+                         GRPC_ERROR_STR_GRPC_MESSAGE, description),
+      GRPC_ERROR_INT_GRPC_STATUS, status);
+}
+
+static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
+                               status_source source, grpc_status_code status,
+                               const char *description) {
+  cancel_with_error(exec_ctx, c, source,
+                    error_from_status(status, description));
+}
+
+/*******************************************************************************
+ * FINAL STATUS CODE MANIPULATION
+ */
+
+static bool get_final_status_from(
+    grpc_call *call, grpc_error *error, bool allow_ok_status,
+    void (*set_value)(grpc_status_code code, void *user_data),
+    void *set_value_user_data, grpc_slice *details) {
+  grpc_status_code code;
+  const char *msg = NULL;
+  grpc_error_get_status(error, call->send_deadline, &code, &msg, NULL);
+  if (code == GRPC_STATUS_OK && !allow_ok_status) {
+    return false;
+  }
+
+  set_value(code, set_value_user_data);
+  if (details != NULL) {
+    *details =
+        msg == NULL ? grpc_empty_slice() : grpc_slice_from_copied_string(msg);
+  }
+  return true;
+}
+
+static void get_final_status(grpc_call *call,
+                             void (*set_value)(grpc_status_code code,
+                                               void *user_data),
+                             void *set_value_user_data, grpc_slice *details) {
+  int i;
+  received_status status[STATUS_SOURCE_COUNT];
+  for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+    status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
+  }
+  if (grpc_call_error_trace) {
+    gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
+    for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+      if (status[i].is_set) {
+        gpr_log(GPR_DEBUG, "  %d: %s", i, grpc_error_string(status[i].error));
+      }
+    }
+  }
+  /* first search through ignoring "OK" statuses: if something went wrong,
+   * ensure we report it */
+  for (int allow_ok_status = 0; allow_ok_status < 2; allow_ok_status++) {
+    /* search for the best status we can present: ideally the error we use has a
+       clearly defined grpc-status, and we'll prefer that. */
+    for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+      if (status[i].is_set &&
+          grpc_error_has_clear_grpc_status(status[i].error)) {
+        if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
+                                  set_value, set_value_user_data, details)) {
+          return;
+        }
+      }
+    }
+    /* If no clearly defined status exists, search for 'anything' */
+    for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+      if (status[i].is_set) {
+        if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
+                                  set_value, set_value_user_data, details)) {
+          return;
+        }
+      }
+    }
+  }
+  /* If nothing exists, set some default */
+  if (call->is_client) {
+    set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
+  } else {
+    set_value(GRPC_STATUS_OK, set_value_user_data);
+  }
+}
+
+static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                                  status_source source, grpc_error *error) {
+  if (!gpr_atm_rel_cas(&call->status[source],
+                       pack_received_status((received_status){
+                           .is_set = false, .error = GRPC_ERROR_NONE}),
+                       pack_received_status((received_status){
+                           .is_set = true, .error = error}))) {
+    GRPC_ERROR_UNREF(error);
+  }
+}
+
+/*******************************************************************************
+ * COMPRESSION
+ */
+
+static void set_incoming_compression_algorithm(
+    grpc_call *call, grpc_compression_algorithm algo) {
+  GPR_ASSERT(algo < GRPC_COMPRESS_ALGORITHMS_COUNT);
+  call->incoming_compression_algorithm = algo;
+}
+
+grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
+    grpc_call *call) {
+  grpc_compression_algorithm algorithm;
+  gpr_mu_lock(&call->mu);
+  algorithm = call->incoming_compression_algorithm;
+  gpr_mu_unlock(&call->mu);
+  return algorithm;
+}
+
+static grpc_compression_algorithm compression_algorithm_for_level_locked(
+    grpc_call *call, grpc_compression_level level) {
+  return grpc_compression_algorithm_for_level(level,
+                                              call->encodings_accepted_by_peer);
+}
+
+uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
+  uint32_t flags;
+  gpr_mu_lock(&call->mu);
+  flags = call->test_only_last_message_flags;
+  gpr_mu_unlock(&call->mu);
+  return flags;
+}
+
+static void destroy_encodings_accepted_by_peer(void *p) { return; }
+
+static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
+                                           grpc_call *call, grpc_mdelem mdel) {
+  size_t i;
+  grpc_compression_algorithm algorithm;
+  grpc_slice_buffer accept_encoding_parts;
+  grpc_slice accept_encoding_slice;
+  void *accepted_user_data;
+
+  accepted_user_data =
+      grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
+  if (accepted_user_data != NULL) {
+    call->encodings_accepted_by_peer =
+        (uint32_t)(((uintptr_t)accepted_user_data) - 1);
+    return;
+  }
+
+  accept_encoding_slice = GRPC_MDVALUE(mdel);
+  grpc_slice_buffer_init(&accept_encoding_parts);
+  grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
+
+  /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already
+   * zeroes the whole grpc_call */
+  /* Always support no compression */
+  GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
+  for (i = 0; i < accept_encoding_parts.count; i++) {
+    grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
+    if (grpc_compression_algorithm_parse(accept_encoding_entry_slice,
+                                         &algorithm)) {
+      GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
+    } else {
+      char *accept_encoding_entry_str =
+          grpc_slice_to_c_string(accept_encoding_entry_slice);
+      gpr_log(GPR_ERROR,
+              "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
+              accept_encoding_entry_str);
+      gpr_free(accept_encoding_entry_str);
+    }
+  }
+
+  grpc_slice_buffer_destroy_internal(exec_ctx, &accept_encoding_parts);
+
+  grpc_mdelem_set_user_data(
+      mdel, destroy_encodings_accepted_by_peer,
+      (void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
+}
+
+uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
+  uint32_t encodings_accepted_by_peer;
+  gpr_mu_lock(&call->mu);
+  encodings_accepted_by_peer = call->encodings_accepted_by_peer;
+  gpr_mu_unlock(&call->mu);
+  return encodings_accepted_by_peer;
+}
+
+static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
+  return (grpc_linked_mdelem *)&md->internal_data;
+}
+
+static grpc_metadata *get_md_elem(grpc_metadata *metadata,
+                                  grpc_metadata *additional_metadata, int i,
+                                  int count) {
+  grpc_metadata *res =
+      i < count ? &metadata[i] : &additional_metadata[i - count];
+  GPR_ASSERT(res);
+  return res;
+}
+
+static int prepare_application_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call *call, int count,
+    grpc_metadata *metadata, int is_trailing, int prepend_extra_metadata,
+    grpc_metadata *additional_metadata, int additional_metadata_count) {
+  int total_count = count + additional_metadata_count;
+  int i;
+  grpc_metadata_batch *batch =
+      &call->metadata_batch[0 /* is_receiving */][is_trailing];
+  for (i = 0; i < total_count; i++) {
+    const grpc_metadata *md =
+        get_md_elem(metadata, additional_metadata, i, count);
+    grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
+    GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
+    if (!GRPC_LOG_IF_ERROR("validate_metadata",
+                           grpc_validate_header_key_is_legal(md->key))) {
+      break;
+    } else if (!grpc_is_binary_header(md->key) &&
+               !GRPC_LOG_IF_ERROR(
+                   "validate_metadata",
+                   grpc_validate_header_nonbin_value_is_legal(md->value))) {
+      break;
+    }
+    l->md = grpc_mdelem_from_grpc_metadata(exec_ctx, (grpc_metadata *)md);
+  }
+  if (i != total_count) {
+    for (int j = 0; j < i; j++) {
+      const grpc_metadata *md =
+          get_md_elem(metadata, additional_metadata, j, count);
+      grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
+      GRPC_MDELEM_UNREF(exec_ctx, l->md);
+    }
+    return 0;
+  }
+  if (prepend_extra_metadata) {
+    if (call->send_extra_metadata_count == 0) {
+      prepend_extra_metadata = 0;
+    } else {
+      for (i = 0; i < call->send_extra_metadata_count; i++) {
+        GRPC_LOG_IF_ERROR("prepare_application_metadata",
+                          grpc_metadata_batch_link_tail(
+                              exec_ctx, batch, &call->send_extra_metadata[i]));
+      }
+    }
+  }
+  for (i = 0; i < total_count; i++) {
+    grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count);
+    GRPC_LOG_IF_ERROR(
+        "prepare_application_metadata",
+        grpc_metadata_batch_link_tail(exec_ctx, batch, linked_from_md(md)));
+  }
+  call->send_extra_metadata_count = 0;
+
+  return 1;
+}
+
 /* we offset status by a small amount when storing it into transport metadata
    as metadata cannot store a 0 value (which is used as OK for grpc_status_codes
    */
 #define STATUS_OFFSET 1
 static void destroy_status(void *ignored) {}
 
-static uint32_t decode_status(grpc_mdelem *md) {
+static uint32_t decode_status(grpc_mdelem md) {
   uint32_t status;
   void *user_data;
-  if (md == GRPC_MDELEM_GRPC_STATUS_0) return 0;
-  if (md == GRPC_MDELEM_GRPC_STATUS_1) return 1;
-  if (md == GRPC_MDELEM_GRPC_STATUS_2) return 2;
+  if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) return 0;
+  if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_1)) return 1;
+  if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_2)) return 2;
   user_data = grpc_mdelem_get_user_data(md, destroy_status);
   if (user_data != NULL) {
     status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET;
   } else {
-    if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value),
-                                   GRPC_SLICE_LENGTH(md->value->slice),
-                                   &status)) {
+    if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(md), &status)) {
       status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
     }
     grpc_mdelem_set_user_data(md, destroy_status,
@@ -916,93 +883,104 @@
   return status;
 }
 
-static grpc_compression_algorithm decode_compression(grpc_mdelem *md) {
+static grpc_compression_algorithm decode_compression(grpc_mdelem md) {
   grpc_compression_algorithm algorithm =
-      grpc_compression_algorithm_from_mdstr(md->value);
+      grpc_compression_algorithm_from_slice(GRPC_MDVALUE(md));
   if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
-    const char *md_c_str = grpc_mdstr_as_c_string(md->value);
+    char *md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
     gpr_log(GPR_ERROR,
             "Invalid incoming compression algorithm: '%s'. Interpreting "
             "incoming data as uncompressed.",
             md_c_str);
+    gpr_free(md_c_str);
     return GRPC_COMPRESS_NONE;
   }
   return algorithm;
 }
 
-static grpc_mdelem *recv_common_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
-                                       grpc_mdelem *elem) {
-  if (elem->key == GRPC_MDSTR_GRPC_STATUS) {
-    GPR_TIMER_BEGIN("status", 0);
-    set_status_code(call, STATUS_FROM_WIRE, decode_status(elem));
-    GPR_TIMER_END("status", 0);
-    return NULL;
-  } else if (elem->key == GRPC_MDSTR_GRPC_MESSAGE) {
-    GPR_TIMER_BEGIN("status-details", 0);
-    set_status_details(exec_ctx, call, STATUS_FROM_WIRE,
-                       GRPC_MDSTR_REF(elem->value));
-    GPR_TIMER_END("status-details", 0);
-    return NULL;
+static void recv_common_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                               grpc_metadata_batch *b) {
+  if (b->idx.named.grpc_status != NULL) {
+    uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
+    grpc_error *error =
+        status_code == GRPC_STATUS_OK
+            ? GRPC_ERROR_NONE
+            : grpc_error_set_int(GRPC_ERROR_CREATE("Error received from peer"),
+                                 GRPC_ERROR_INT_GRPC_STATUS,
+                                 (intptr_t)status_code);
+
+    if (b->idx.named.grpc_message != NULL) {
+      char *msg =
+          grpc_slice_to_c_string(GRPC_MDVALUE(b->idx.named.grpc_message->md));
+      error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, msg);
+      gpr_free(msg);
+      grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_message);
+    } else if (error != GRPC_ERROR_NONE) {
+      error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "");
+    }
+
+    set_status_from_error(exec_ctx, call, STATUS_FROM_WIRE, error);
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_status);
   }
-  return elem;
 }
 
-static grpc_mdelem *publish_app_metadata(grpc_call *call, grpc_mdelem *elem,
-                                         int is_trailing) {
+static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
+                                 int is_trailing) {
+  if (b->list.count == 0) return;
+  GPR_TIMER_BEGIN("publish_app_metadata", 0);
   grpc_metadata_array *dest;
   grpc_metadata *mdusr;
-  GPR_TIMER_BEGIN("publish_app_metadata", 0);
   dest = call->buffered_metadata[is_trailing];
-  if (dest->count == dest->capacity) {
-    dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2);
+  if (dest->count + b->list.count > dest->capacity) {
+    dest->capacity =
+        GPR_MAX(dest->capacity + b->list.count, dest->capacity * 3 / 2);
     dest->metadata =
         gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
   }
-  mdusr = &dest->metadata[dest->count++];
-  mdusr->key = grpc_mdstr_as_c_string(elem->key);
-  mdusr->value = grpc_mdstr_as_c_string(elem->value);
-  mdusr->value_length = GRPC_SLICE_LENGTH(elem->value->slice);
+  for (grpc_linked_mdelem *l = b->list.head; l != NULL; l = l->next) {
+    mdusr = &dest->metadata[dest->count++];
+    /* we pass back borrowed slices that are valid whilst the call is valid */
+    mdusr->key = GRPC_MDKEY(l->md);
+    mdusr->value = GRPC_MDVALUE(l->md);
+  }
   GPR_TIMER_END("publish_app_metadata", 0);
-  return elem;
 }
 
-static grpc_mdelem *recv_initial_filter(grpc_exec_ctx *exec_ctx, void *args,
-                                        grpc_mdelem *elem) {
-  grpc_call *call = args;
-  elem = recv_common_filter(exec_ctx, call, elem);
-  if (elem == NULL) {
-    return NULL;
-  } else if (elem->key == GRPC_MDSTR_GRPC_ENCODING) {
+static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
+                                grpc_metadata_batch *b) {
+  recv_common_filter(exec_ctx, call, b);
+
+  if (b->idx.named.grpc_encoding != NULL) {
     GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
-    set_incoming_compression_algorithm(call, decode_compression(elem));
+    set_incoming_compression_algorithm(
+        call, decode_compression(b->idx.named.grpc_encoding->md));
     GPR_TIMER_END("incoming_compression_algorithm", 0);
-    return NULL;
-  } else if (elem->key == GRPC_MDSTR_GRPC_ACCEPT_ENCODING) {
-    GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
-    set_encodings_accepted_by_peer(exec_ctx, call, elem);
-    GPR_TIMER_END("encodings_accepted_by_peer", 0);
-    return NULL;
-  } else {
-    return publish_app_metadata(call, elem, 0);
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding);
   }
+
+  if (b->idx.named.grpc_accept_encoding != NULL) {
+    GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
+    set_encodings_accepted_by_peer(exec_ctx, call,
+                                   b->idx.named.grpc_accept_encoding->md);
+    grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding);
+    GPR_TIMER_END("encodings_accepted_by_peer", 0);
+  }
+
+  publish_app_metadata(call, b, false);
 }
 
-static grpc_mdelem *recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args,
-                                         grpc_mdelem *elem) {
+static void recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args,
+                                 grpc_metadata_batch *b) {
   grpc_call *call = args;
-  elem = recv_common_filter(exec_ctx, call, elem);
-  if (elem == NULL) {
-    return NULL;
-  } else {
-    return publish_app_metadata(call, elem, 1);
-  }
+  recv_common_filter(exec_ctx, call, b);
+  publish_app_metadata(call, b, true);
 }
 
 grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) {
   return CALL_STACK_FROM_CALL(call);
 }
 
-/*
+/*******************************************************************************
  * BATCH API IMPLEMENTATION
  */
 
@@ -1031,44 +1009,132 @@
   return !(flags & invalid_positions);
 }
 
-static batch_control *allocate_batch_control(grpc_call *call) {
-  size_t i;
-  for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) {
-    if ((call->used_batches & (1 << i)) == 0) {
-      call->used_batches = (uint8_t)(call->used_batches | (uint8_t)(1 << i));
-      return &call->active_batches[i];
-    }
+static int batch_slot_for_op(grpc_op_type type) {
+  switch (type) {
+    case GRPC_OP_SEND_INITIAL_METADATA:
+      return 0;
+    case GRPC_OP_SEND_MESSAGE:
+      return 1;
+    case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+    case GRPC_OP_SEND_STATUS_FROM_SERVER:
+      return 2;
+    case GRPC_OP_RECV_INITIAL_METADATA:
+      return 3;
+    case GRPC_OP_RECV_MESSAGE:
+      return 4;
+    case GRPC_OP_RECV_CLOSE_ON_SERVER:
+    case GRPC_OP_RECV_STATUS_ON_CLIENT:
+      return 5;
   }
-  return NULL;
+  GPR_UNREACHABLE_CODE(return 123456789);
+}
+
+static batch_control *allocate_batch_control(grpc_call *call,
+                                             const grpc_op *ops,
+                                             size_t num_ops) {
+  int slot = batch_slot_for_op(ops[0].op);
+  for (size_t i = 1; i < num_ops; i++) {
+    int op_slot = batch_slot_for_op(ops[i].op);
+    slot = GPR_MIN(slot, op_slot);
+  }
+  batch_control *bctl = &call->active_batches[slot];
+  if (bctl->call != NULL) {
+    return NULL;
+  }
+  memset(bctl, 0, sizeof(*bctl));
+  bctl->call = call;
+  return bctl;
 }
 
 static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
                                     grpc_cq_completion *storage) {
   batch_control *bctl = user_data;
   grpc_call *call = bctl->call;
-  gpr_mu_lock(&call->mu);
-  call->used_batches = (uint8_t)(
-      call->used_batches & ~(uint8_t)(1 << (bctl - call->active_batches)));
-  gpr_mu_unlock(&call->mu);
+  bctl->call = NULL;
   GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
 }
 
+static grpc_error *consolidate_batch_errors(batch_control *bctl) {
+  size_t n = (size_t)gpr_atm_no_barrier_load(&bctl->num_errors);
+  if (n == 0) {
+    return GRPC_ERROR_NONE;
+  } else if (n == 1) {
+    /* Skip creating a composite error in the case that only one error was
+       logged */
+    grpc_error *e = bctl->errors[0];
+    bctl->errors[0] = NULL;
+    return e;
+  } else {
+    grpc_error *error =
+        GRPC_ERROR_CREATE_REFERENCING("Call batch failed", bctl->errors, n);
+    for (size_t i = 0; i < n; i++) {
+      GRPC_ERROR_UNREF(bctl->errors[i]);
+      bctl->errors[i] = NULL;
+    }
+    return error;
+  }
+}
+
 static void post_batch_completion(grpc_exec_ctx *exec_ctx,
                                   batch_control *bctl) {
+  grpc_call *child_call;
+  grpc_call *next_child_call;
   grpc_call *call = bctl->call;
-  grpc_error *error = bctl->error;
+  grpc_error *error = consolidate_batch_errors(bctl);
+
+  gpr_mu_lock(&call->mu);
+
+  if (bctl->send_initial_metadata) {
+    grpc_metadata_batch_destroy(
+        exec_ctx,
+        &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
+  }
+  if (bctl->send_message) {
+    call->sending_message = false;
+  }
+  if (bctl->send_final_op) {
+    grpc_metadata_batch_destroy(
+        exec_ctx,
+        &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
+  }
   if (bctl->recv_final_op) {
+    grpc_metadata_batch *md =
+        &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
+    recv_trailing_filter(exec_ctx, call, md);
+
+    call->received_final_op = true;
+    /* propagate cancellation to any interested children */
+    child_call = call->first_child;
+    if (child_call != NULL) {
+      do {
+        next_child_call = child_call->sibling_next;
+        if (child_call->cancellation_is_inherited) {
+          GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
+          grpc_call_cancel(child_call, NULL);
+          GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
+        }
+        child_call = next_child_call;
+      } while (child_call != call->first_child);
+    }
+
+    if (call->is_client) {
+      get_final_status(call, set_status_value_directly,
+                       call->final_op.client.status,
+                       call->final_op.client.status_details);
+    } else {
+      get_final_status(call, set_cancelled_value,
+                       call->final_op.server.cancelled, NULL);
+    }
+
     GRPC_ERROR_UNREF(error);
     error = GRPC_ERROR_NONE;
   }
+  gpr_mu_unlock(&call->mu);
+
   if (bctl->is_notify_tag_closure) {
     /* unrefs bctl->error */
+    bctl->call = NULL;
     grpc_closure_run(exec_ctx, bctl->notify_tag, error);
-    gpr_mu_lock(&call->mu);
-    bctl->call->used_batches =
-        (uint8_t)(bctl->call->used_batches &
-                  ~(uint8_t)(1 << (bctl - bctl->call->active_batches)));
-    gpr_mu_unlock(&call->mu);
     GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
   } else {
     /* unrefs bctl->error */
@@ -1077,6 +1143,12 @@
   }
 }
 
+static void finish_batch_step(grpc_exec_ctx *exec_ctx, batch_control *bctl) {
+  if (gpr_unref(&bctl->steps_to_complete)) {
+    post_batch_completion(exec_ctx, bctl);
+  }
+}
+
 static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
                                       batch_control *bctl) {
   grpc_call *call = bctl->call;
@@ -1087,9 +1159,7 @@
       call->receiving_message = 0;
       grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
       call->receiving_stream = NULL;
-      if (gpr_unref(&bctl->steps_to_complete)) {
-        post_batch_completion(exec_ctx, bctl);
-      }
+      finish_batch_step(exec_ctx, bctl);
       return;
     }
     if (grpc_byte_stream_next(exec_ctx, call->receiving_stream,
@@ -1120,9 +1190,7 @@
     call->receiving_stream = NULL;
     grpc_byte_buffer_destroy(*call->receiving_buffer);
     *call->receiving_buffer = NULL;
-    if (gpr_unref(&bctl->steps_to_complete)) {
-      post_batch_completion(exec_ctx, bctl);
-    }
+    finish_batch_step(exec_ctx, bctl);
   }
 }
 
@@ -1132,9 +1200,7 @@
   if (call->receiving_stream == NULL) {
     *call->receiving_buffer = NULL;
     call->receiving_message = 0;
-    if (gpr_unref(&bctl->steps_to_complete)) {
-      post_batch_completion(exec_ctx, bctl);
-    }
+    finish_batch_step(exec_ctx, bctl);
   } else {
     call->test_only_last_message_flags = call->receiving_stream->flags;
     if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) &&
@@ -1154,14 +1220,17 @@
                                    grpc_error *error) {
   batch_control *bctl = bctlp;
   grpc_call *call = bctl->call;
-  if (error != GRPC_ERROR_NONE) {
-    grpc_status_code status;
-    const char *msg;
-    grpc_error_get_status(error, &status, &msg);
-    close_with_status(exec_ctx, call, status, msg);
-  }
   gpr_mu_lock(&bctl->call->mu);
-  if (bctl->call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
+  if (error != GRPC_ERROR_NONE) {
+    if (call->receiving_stream != NULL) {
+      grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
+      call->receiving_stream = NULL;
+    }
+    add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), true);
+    cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
+                      GRPC_ERROR_REF(error));
+  }
+  if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
       call->receiving_stream == NULL) {
     gpr_mu_unlock(&bctl->call->mu);
     process_data_after_md(exec_ctx, bctlp);
@@ -1186,7 +1255,8 @@
       gpr_asprintf(&error_msg, "Invalid compression algorithm value '%d'.",
                    algo);
       gpr_log(GPR_ERROR, "%s", error_msg);
-      close_with_status(exec_ctx, call, GRPC_STATUS_UNIMPLEMENTED, error_msg);
+      cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
+                         GRPC_STATUS_UNIMPLEMENTED, error_msg);
     } else if (grpc_compression_options_is_algorithm_enabled(
                    &compression_options, algo) == 0) {
       /* check if algorithm is supported by current channel config */
@@ -1195,7 +1265,8 @@
       gpr_asprintf(&error_msg, "Compression algorithm '%s' is disabled.",
                    algo_name);
       gpr_log(GPR_ERROR, "%s", error_msg);
-      close_with_status(exec_ctx, call, GRPC_STATUS_UNIMPLEMENTED, error_msg);
+      cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
+                         GRPC_STATUS_UNIMPLEMENTED, error_msg);
     } else {
       call->incoming_compression_algorithm = algo;
     }
@@ -1221,12 +1292,15 @@
   }
 }
 
-static void add_batch_error(batch_control *bctl, grpc_error *error) {
+static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
+                            grpc_error *error, bool has_cancelled) {
   if (error == GRPC_ERROR_NONE) return;
-  if (bctl->error == GRPC_ERROR_NONE) {
-    bctl->error = GRPC_ERROR_CREATE("Call batch operation failed");
+  int idx = (int)gpr_atm_no_barrier_fetch_add(&bctl->num_errors, 1);
+  if (idx == 0 && !has_cancelled) {
+    cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE,
+                      GRPC_ERROR_REF(error));
   }
-  bctl->error = grpc_error_add_child(bctl->error, error);
+  bctl->errors[idx] = error;
 }
 
 static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
@@ -1236,12 +1310,13 @@
 
   gpr_mu_lock(&call->mu);
 
-  add_batch_error(bctl, GRPC_ERROR_REF(error));
+  add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
   if (error == GRPC_ERROR_NONE) {
     grpc_metadata_batch *md =
         &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
-    grpc_metadata_batch_filter(exec_ctx, md, recv_initial_filter, call);
+    recv_initial_filter(exec_ctx, call, md);
 
+    /* TODO(ctiller): this could be moved into recv_initial_filter now */
     GPR_TIMER_BEGIN("validate_filtered_metadata", 0);
     validate_filtered_metadata(exec_ctx, bctl);
     GPR_TIMER_END("validate_filtered_metadata", 0);
@@ -1260,90 +1335,25 @@
         receiving_stream_ready, call->saved_receiving_stream_ready_bctlp,
         grpc_schedule_on_exec_ctx);
     call->saved_receiving_stream_ready_bctlp = NULL;
-    grpc_closure_sched(exec_ctx, saved_rsr_closure, error);
+    grpc_closure_sched(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error));
   }
 
   gpr_mu_unlock(&call->mu);
 
-  if (gpr_unref(&bctl->steps_to_complete)) {
-    post_batch_completion(exec_ctx, bctl);
-  }
+  finish_batch_step(exec_ctx, bctl);
 }
 
 static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
                          grpc_error *error) {
   batch_control *bctl = bctlp;
-  grpc_call *call = bctl->call;
-  grpc_call *child_call;
-  grpc_call *next_child_call;
 
-  GRPC_ERROR_REF(error);
+  add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
+  finish_batch_step(exec_ctx, bctl);
+}
 
-  gpr_mu_lock(&call->mu);
-
-  // If the error has an associated status code, set the call's status.
-  intptr_t status;
-  if (error != GRPC_ERROR_NONE &&
-      grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &status)) {
-    set_status_from_error(exec_ctx, call, STATUS_FROM_CORE, error);
-  }
-
-  if (bctl->send_initial_metadata) {
-    if (error != GRPC_ERROR_NONE) {
-      set_status_from_error(exec_ctx, call, STATUS_FROM_CORE, error);
-    }
-    grpc_metadata_batch_destroy(
-        exec_ctx,
-        &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
-  }
-  if (bctl->send_message) {
-    call->sending_message = 0;
-  }
-  if (bctl->send_final_op) {
-    grpc_metadata_batch_destroy(
-        exec_ctx,
-        &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
-  }
-  if (bctl->recv_final_op) {
-    grpc_metadata_batch *md =
-        &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
-    grpc_metadata_batch_filter(exec_ctx, md, recv_trailing_filter, call);
-
-    call->received_final_op = true;
-    /* propagate cancellation to any interested children */
-    child_call = call->first_child;
-    if (child_call != NULL) {
-      do {
-        next_child_call = child_call->sibling_next;
-        if (child_call->cancellation_is_inherited) {
-          GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
-          grpc_call_cancel(child_call, NULL);
-          GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
-        }
-        child_call = next_child_call;
-      } while (child_call != call->first_child);
-    }
-
-    if (call->is_client) {
-      get_final_status(call, set_status_value_directly,
-                       call->final_op.client.status);
-      get_final_details(call, call->final_op.client.status_details,
-                        call->final_op.client.status_details_capacity);
-    } else {
-      get_final_status(call, set_cancelled_value,
-                       call->final_op.server.cancelled);
-    }
-
-    GRPC_ERROR_UNREF(error);
-    error = GRPC_ERROR_NONE;
-  }
-  add_batch_error(bctl, GRPC_ERROR_REF(error));
-  gpr_mu_unlock(&call->mu);
-  if (gpr_unref(&bctl->steps_to_complete)) {
-    post_batch_completion(exec_ctx, bctl);
-  }
-
-  GRPC_ERROR_UNREF(error);
+static void free_no_op_completion(grpc_exec_ctx *exec_ctx, void *p,
+                                  grpc_cq_completion *completion) {
+  gpr_free(completion);
 }
 
 static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
@@ -1360,33 +1370,33 @@
   grpc_metadata compression_md;
 
   GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
-
   GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
 
-  /* TODO(ctiller): this feels like it could be made lock-free */
-  gpr_mu_lock(&call->mu);
-  bctl = allocate_batch_control(call);
-  memset(bctl, 0, sizeof(*bctl));
-  bctl->call = call;
-  bctl->notify_tag = notify_tag;
-  bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
-
-  grpc_transport_stream_op *stream_op = &bctl->op;
-  memset(stream_op, 0, sizeof(*stream_op));
-  stream_op->covered_by_poller = true;
-
   if (nops == 0) {
-    GRPC_CALL_INTERNAL_REF(call, "completion");
-    bctl->error = GRPC_ERROR_NONE;
     if (!is_notify_tag_closure) {
       grpc_cq_begin_op(call->cq, notify_tag);
+      grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
+                     free_no_op_completion, NULL,
+                     gpr_malloc(sizeof(grpc_cq_completion)));
+    } else {
+      grpc_closure_sched(exec_ctx, notify_tag, GRPC_ERROR_NONE);
     }
-    gpr_mu_unlock(&call->mu);
-    post_batch_completion(exec_ctx, bctl);
     error = GRPC_CALL_OK;
     goto done;
   }
 
+  bctl = allocate_batch_control(call, ops, nops);
+  if (bctl == NULL) {
+    return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+  }
+  bctl->notify_tag = notify_tag;
+  bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
+
+  gpr_mu_lock(&call->mu);
+  grpc_transport_stream_op *stream_op = &bctl->op;
+  memset(stream_op, 0, sizeof(*stream_op));
+  stream_op->covered_by_poller = true;
+
   /* rewrite batch ops into a transport op */
   for (i = 0; i < nops; i++) {
     op = &ops[i];
@@ -1426,13 +1436,10 @@
           const grpc_compression_algorithm calgo =
               compression_algorithm_for_level_locked(
                   call, effective_compression_level);
-          char *calgo_name = NULL;
-          grpc_compression_algorithm_name(calgo, &calgo_name);
           // the following will be picked up by the compress filter and used as
           // the call's compression algorithm.
-          compression_md.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
-          compression_md.value = calgo_name;
-          compression_md.value_length = strlen(calgo_name);
+          compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
+          compression_md.value = grpc_compression_algorithm_slice(calgo);
           additional_metadata_count++;
         }
 
@@ -1524,28 +1531,39 @@
         }
         bctl->send_final_op = 1;
         call->sent_final_op = 1;
+        GPR_ASSERT(call->send_extra_metadata_count == 0);
         call->send_extra_metadata_count = 1;
         call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
             exec_ctx, call->channel, op->data.send_status_from_server.status);
-        if (op->data.send_status_from_server.status_details != NULL) {
-          call->send_extra_metadata[1].md = grpc_mdelem_from_metadata_strings(
-              exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
-              grpc_mdstr_from_string(
-                  op->data.send_status_from_server.status_details));
-          call->send_extra_metadata_count++;
-          set_status_details(
-              exec_ctx, call, STATUS_FROM_API_OVERRIDE,
-              GRPC_MDSTR_REF(call->send_extra_metadata[1].md->value));
-        }
-        if (op->data.send_status_from_server.status != GRPC_STATUS_OK) {
-          set_status_code(call, STATUS_FROM_API_OVERRIDE,
-                          (uint32_t)op->data.send_status_from_server.status);
+        {
+          grpc_error *override_error = GRPC_ERROR_NONE;
+          if (op->data.send_status_from_server.status != GRPC_STATUS_OK) {
+            override_error = GRPC_ERROR_CREATE("Error from server send status");
+          }
+          if (op->data.send_status_from_server.status_details != NULL) {
+            call->send_extra_metadata[1].md = grpc_mdelem_from_slices(
+                exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
+                grpc_slice_ref_internal(
+                    *op->data.send_status_from_server.status_details));
+            call->send_extra_metadata_count++;
+            char *msg = grpc_slice_to_c_string(
+                GRPC_MDVALUE(call->send_extra_metadata[1].md));
+            override_error = grpc_error_set_str(
+                override_error, GRPC_ERROR_STR_GRPC_MESSAGE, msg);
+            gpr_free(msg);
+          }
+          set_status_from_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE,
+                                override_error);
         }
         if (!prepare_application_metadata(
                 exec_ctx, call,
                 (int)op->data.send_status_from_server.trailing_metadata_count,
                 op->data.send_status_from_server.trailing_metadata, 1, 1, NULL,
                 0)) {
+          for (int n = 0; n < call->send_extra_metadata_count; n++) {
+            GRPC_MDELEM_UNREF(exec_ctx, call->send_extra_metadata[n].md);
+          }
+          call->send_extra_metadata_count = 0;
           error = GRPC_CALL_ERROR_INVALID_METADATA;
           goto done_with_error;
         }
@@ -1618,8 +1636,6 @@
         call->final_op.client.status = op->data.recv_status_on_client.status;
         call->final_op.client.status_details =
             op->data.recv_status_on_client.status_details;
-        call->final_op.client.status_details_capacity =
-            op->data.recv_status_on_client.status_details_capacity;
         bctl->recv_final_op = 1;
         stream_op->recv_trailing_metadata =
             &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h
index 233340c..7d4d0db 100644
--- a/src/core/lib/surface/call.h
+++ b/src/core/lib/surface/call.h
@@ -61,7 +61,7 @@
 
   const void *server_transport_data;
 
-  grpc_mdelem **add_initial_metadata;
+  grpc_mdelem *add_initial_metadata;
   size_t add_initial_metadata_count;
 
   gpr_timespec send_deadline;
@@ -110,6 +110,7 @@
 
 /* Set a context pointer.
    No thread safety guarantees are made wrt this value. */
+/* TODO(#9731): add exec_ctx to destroy */
 void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
                            void *value, void (*destroy)(void *value));
 /* Get a context pointer. */
@@ -125,6 +126,8 @@
 grpc_compression_algorithm grpc_call_compression_for_level(
     grpc_call *call, grpc_compression_level level);
 
+extern int grpc_call_error_trace;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/core/lib/surface/call_details.c b/src/core/lib/surface/call_details.c
index fe73da3..d0f88e1 100644
--- a/src/core/lib/surface/call_details.c
+++ b/src/core/lib/surface/call_details.c
@@ -36,15 +36,21 @@
 
 #include <string.h>
 
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/api_trace.h"
 
 void grpc_call_details_init(grpc_call_details* cd) {
   GRPC_API_TRACE("grpc_call_details_init(cd=%p)", 1, (cd));
   memset(cd, 0, sizeof(*cd));
+  cd->method = grpc_empty_slice();
+  cd->host = grpc_empty_slice();
 }
 
 void grpc_call_details_destroy(grpc_call_details* cd) {
   GRPC_API_TRACE("grpc_call_details_destroy(cd=%p)", 1, (cd));
-  gpr_free(cd->method);
-  gpr_free(cd->host);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_slice_unref_internal(&exec_ctx, cd->method);
+  grpc_slice_unref_internal(&exec_ctx, cd->host);
+  grpc_exec_ctx_finish(&exec_ctx);
 }
diff --git a/src/core/lib/surface/call_log_batch.c b/src/core/lib/surface/call_log_batch.c
index 61b73a1..529a1ef 100644
--- a/src/core/lib/surface/call_log_batch.c
+++ b/src/core/lib/surface/call_log_batch.c
@@ -35,17 +35,22 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
 
 static void add_metadata(gpr_strvec *b, const grpc_metadata *md, size_t count) {
   size_t i;
+  if (md == NULL) {
+    gpr_strvec_add(b, gpr_strdup("(nil)"));
+    return;
+  }
   for (i = 0; i < count; i++) {
     gpr_strvec_add(b, gpr_strdup("\nkey="));
-    gpr_strvec_add(b, gpr_strdup(md[i].key));
+    gpr_strvec_add(b, grpc_slice_to_c_string(md[i].key));
 
     gpr_strvec_add(b, gpr_strdup(" value="));
-    gpr_strvec_add(b, gpr_dump(md[i].value, md[i].value_length,
-                               GPR_DUMP_HEX | GPR_DUMP_ASCII));
+    gpr_strvec_add(b,
+                   grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII));
   }
 }
 
@@ -71,10 +76,16 @@
       gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT"));
       break;
     case GRPC_OP_SEND_STATUS_FROM_SERVER:
-      gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=%s",
-                   op->data.send_status_from_server.status,
-                   op->data.send_status_from_server.status_details);
+      gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=",
+                   op->data.send_status_from_server.status);
       gpr_strvec_add(&b, tmp);
+      if (op->data.send_status_from_server.status_details != NULL) {
+        gpr_strvec_add(&b, grpc_dump_slice(
+                               *op->data.send_status_from_server.status_details,
+                               GPR_DUMP_ASCII));
+      } else {
+        gpr_strvec_add(&b, gpr_strdup("(null)"));
+      }
       add_metadata(&b, op->data.send_status_from_server.trailing_metadata,
                    op->data.send_status_from_server.trailing_metadata_count);
       break;
diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c
index b872957..d6acd39 100644
--- a/src/core/lib/surface/channel.c
+++ b/src/core/lib/surface/channel.c
@@ -43,6 +43,7 @@
 
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/iomgr/iomgr.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/call.h"
@@ -57,15 +58,15 @@
 #define NUM_CACHED_STATUS_ELEMS 3
 
 typedef struct registered_call {
-  grpc_mdelem *path;
-  grpc_mdelem *authority;
+  grpc_mdelem path;
+  grpc_mdelem authority;
   struct registered_call *next;
 } registered_call;
 
 struct grpc_channel {
   int is_client;
   grpc_compression_options compression_options;
-  grpc_mdelem *default_authority;
+  grpc_mdelem default_authority;
 
   gpr_mu registered_call_mu;
   registered_call *registered_calls;
@@ -102,9 +103,8 @@
       exec_ctx, builder, sizeof(grpc_channel), 1, destroy_channel, NULL,
       (void **)&channel);
   if (error != GRPC_ERROR_NONE) {
-    const char *msg = grpc_error_string(error);
-    gpr_log(GPR_ERROR, "channel stack builder failed: %s", msg);
-    grpc_error_free_string(msg);
+    gpr_log(GPR_ERROR, "channel stack builder failed: %s",
+            grpc_error_string(error));
     GRPC_ERROR_UNREF(error);
     goto done;
   }
@@ -116,19 +116,20 @@
   channel->registered_calls = NULL;
 
   grpc_compression_options_init(&channel->compression_options);
-
   for (size_t i = 0; i < args->num_args; i++) {
     if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
       if (args->args[i].type != GRPC_ARG_STRING) {
         gpr_log(GPR_ERROR, "%s ignored: it must be a string",
                 GRPC_ARG_DEFAULT_AUTHORITY);
       } else {
-        if (channel->default_authority) {
+        if (!GRPC_MDISNULL(channel->default_authority)) {
           /* setting this takes precedence over anything else */
           GRPC_MDELEM_UNREF(exec_ctx, channel->default_authority);
         }
-        channel->default_authority = grpc_mdelem_from_strings(
-            exec_ctx, ":authority", args->args[i].value.string);
+        channel->default_authority = grpc_mdelem_from_slices(
+            exec_ctx, GRPC_MDSTR_AUTHORITY,
+            grpc_slice_intern(
+                grpc_slice_from_static_string(args->args[i].value.string)));
       }
     } else if (0 ==
                strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
@@ -136,14 +137,16 @@
         gpr_log(GPR_ERROR, "%s ignored: it must be a string",
                 GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
       } else {
-        if (channel->default_authority) {
+        if (!GRPC_MDISNULL(channel->default_authority)) {
           /* other ways of setting this (notably ssl) take precedence */
           gpr_log(GPR_ERROR,
                   "%s ignored: default host already set some other way",
                   GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
         } else {
-          channel->default_authority = grpc_mdelem_from_strings(
-              exec_ctx, ":authority", args->args[i].value.string);
+          channel->default_authority = grpc_mdelem_from_slices(
+              exec_ctx, GRPC_MDSTR_AUTHORITY,
+              grpc_slice_intern(
+                  grpc_slice_from_static_string(args->args[i].value.string)));
         }
       }
     } else if (0 == strcmp(args->args[i].key,
@@ -191,18 +194,18 @@
 static grpc_call *grpc_channel_create_call_internal(
     grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call,
     uint32_t propagation_mask, grpc_completion_queue *cq,
-    grpc_pollset_set *pollset_set_alternative, grpc_mdelem *path_mdelem,
-    grpc_mdelem *authority_mdelem, gpr_timespec deadline) {
-  grpc_mdelem *send_metadata[2];
+    grpc_pollset_set *pollset_set_alternative, grpc_mdelem path_mdelem,
+    grpc_mdelem authority_mdelem, gpr_timespec deadline) {
+  grpc_mdelem send_metadata[2];
   size_t num_metadata = 0;
 
   GPR_ASSERT(channel->is_client);
   GPR_ASSERT(!(cq != NULL && pollset_set_alternative != NULL));
 
   send_metadata[num_metadata++] = path_mdelem;
-  if (authority_mdelem != NULL) {
+  if (!GRPC_MDISNULL(authority_mdelem)) {
     send_metadata[num_metadata++] = authority_mdelem;
-  } else if (channel->default_authority != NULL) {
+  } else if (!GRPC_MDISNULL(channel->default_authority)) {
     send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority);
   }
 
@@ -227,27 +230,17 @@
                                     grpc_call *parent_call,
                                     uint32_t propagation_mask,
                                     grpc_completion_queue *cq,
-                                    const char *method, const char *host,
+                                    grpc_slice method, const grpc_slice *host,
                                     gpr_timespec deadline, void *reserved) {
-  GRPC_API_TRACE(
-      "grpc_channel_create_call("
-      "channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
-      "host=%s, "
-      "deadline=gpr_timespec { tv_sec: %" PRId64
-      ", tv_nsec: %d, clock_type: %d }, "
-      "reserved=%p)",
-      10,
-      (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
-       deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, reserved));
   GPR_ASSERT(!reserved);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_call *call = grpc_channel_create_call_internal(
       &exec_ctx, channel, parent_call, propagation_mask, cq, NULL,
-      grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_PATH,
-                                        grpc_mdstr_from_string(method)),
-      host ? grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_AUTHORITY,
-                                               grpc_mdstr_from_string(host))
-           : NULL,
+      grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_PATH,
+                              grpc_slice_ref_internal(method)),
+      host != NULL ? grpc_mdelem_from_slices(&exec_ctx, GRPC_MDSTR_AUTHORITY,
+                                             grpc_slice_ref_internal(*host))
+                   : GRPC_MDNULL,
       deadline);
   grpc_exec_ctx_finish(&exec_ctx);
   return call;
@@ -255,17 +248,16 @@
 
 grpc_call *grpc_channel_create_pollset_set_call(
     grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call,
-    uint32_t propagation_mask, grpc_pollset_set *pollset_set,
-    const char *method, const char *host, gpr_timespec deadline,
-    void *reserved) {
+    uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method,
+    const grpc_slice *host, gpr_timespec deadline, void *reserved) {
   GPR_ASSERT(!reserved);
   return grpc_channel_create_call_internal(
       exec_ctx, channel, parent_call, propagation_mask, NULL, pollset_set,
-      grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_PATH,
-                                        grpc_mdstr_from_string(method)),
-      host ? grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_AUTHORITY,
-                                               grpc_mdstr_from_string(host))
-           : NULL,
+      grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_PATH,
+                              grpc_slice_ref_internal(method)),
+      host != NULL ? grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY,
+                                             grpc_slice_ref_internal(*host))
+                   : GRPC_MDNULL,
       deadline);
 }
 
@@ -277,12 +269,15 @@
       4, (channel, method, host, reserved));
   GPR_ASSERT(!reserved);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  rc->path = grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_PATH,
-                                               grpc_mdstr_from_string(method));
+
+  rc->path = grpc_mdelem_from_slices(
+      &exec_ctx, GRPC_MDSTR_PATH,
+      grpc_slice_intern(grpc_slice_from_static_string(method)));
   rc->authority =
-      host ? grpc_mdelem_from_metadata_strings(&exec_ctx, GRPC_MDSTR_AUTHORITY,
-                                               grpc_mdstr_from_string(host))
-           : NULL;
+      host ? grpc_mdelem_from_slices(
+                 &exec_ctx, GRPC_MDSTR_AUTHORITY,
+                 grpc_slice_intern(grpc_slice_from_static_string(host)))
+           : GRPC_MDNULL;
   gpr_mu_lock(&channel->registered_call_mu);
   rc->next = channel->registered_calls;
   channel->registered_calls = rc;
@@ -310,8 +305,7 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_call *call = grpc_channel_create_call_internal(
       &exec_ctx, channel, parent_call, propagation_mask, completion_queue, NULL,
-      GRPC_MDELEM_REF(rc->path),
-      rc->authority ? GRPC_MDELEM_REF(rc->authority) : NULL, deadline);
+      GRPC_MDELEM_REF(rc->path), GRPC_MDELEM_REF(rc->authority), deadline);
   grpc_exec_ctx_finish(&exec_ctx);
   return call;
 }
@@ -340,14 +334,10 @@
     registered_call *rc = channel->registered_calls;
     channel->registered_calls = rc->next;
     GRPC_MDELEM_UNREF(exec_ctx, rc->path);
-    if (rc->authority) {
-      GRPC_MDELEM_UNREF(exec_ctx, rc->authority);
-    }
+    GRPC_MDELEM_UNREF(exec_ctx, rc->authority);
     gpr_free(rc);
   }
-  if (channel->default_authority != NULL) {
-    GRPC_MDELEM_UNREF(exec_ctx, channel->default_authority);
-  }
+  GRPC_MDELEM_UNREF(exec_ctx, channel->default_authority);
   gpr_mu_destroy(&channel->registered_call_mu);
   gpr_free(channel->target);
   gpr_free(channel);
@@ -376,8 +366,8 @@
   return channel->compression_options;
 }
 
-grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx,
-                                                 grpc_channel *channel, int i) {
+grpc_mdelem grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx,
+                                                grpc_channel *channel, int i) {
   char tmp[GPR_LTOA_MIN_BUFSIZE];
   switch (i) {
     case 0:
@@ -388,6 +378,6 @@
       return GRPC_MDELEM_GRPC_STATUS_2;
   }
   gpr_ltoa(i, tmp);
-  return grpc_mdelem_from_metadata_strings(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
-                                           grpc_mdstr_from_string(tmp));
+  return grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
+                                 grpc_slice_from_copied_string(tmp));
 }
diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h
index 2ebadb7..3a441d7 100644
--- a/src/core/lib/surface/channel.h
+++ b/src/core/lib/surface/channel.h
@@ -52,9 +52,8 @@
     value of \a propagation_mask (see propagation_bits.h for possible values) */
 grpc_call *grpc_channel_create_pollset_set_call(
     grpc_exec_ctx *exec_ctx, grpc_channel *channel, grpc_call *parent_call,
-    uint32_t propagation_mask, grpc_pollset_set *pollset_set,
-    const char *method, const char *host, gpr_timespec deadline,
-    void *reserved);
+    uint32_t propagation_mask, grpc_pollset_set *pollset_set, grpc_slice method,
+    const grpc_slice *host, gpr_timespec deadline, void *reserved);
 
 /** Get a (borrowed) pointer to this channels underlying channel stack */
 grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel);
@@ -63,9 +62,9 @@
     status_code.
 
     The returned elem is owned by the caller. */
-grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx,
-                                                 grpc_channel *channel,
-                                                 int status_code);
+grpc_mdelem grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx,
+                                                grpc_channel *channel,
+                                                int status_code);
 
 #ifdef GRPC_STREAM_REFCOUNT_DEBUG
 void grpc_channel_internal_ref(grpc_channel *channel, const char *reason);
diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c
index 4613c90..b459481 100644
--- a/src/core/lib/surface/completion_queue.c
+++ b/src/core/lib/surface/completion_queue.c
@@ -96,9 +96,6 @@
 #define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
 #define CQ_FROM_POLLSET(ps) (((grpc_completion_queue *)ps) - 1)
 
-static gpr_mu g_freelist_mu;
-static grpc_completion_queue *g_freelist;
-
 int grpc_cq_pluck_trace;
 int grpc_cq_event_timeout_trace;
 
@@ -113,21 +110,6 @@
 static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
                                      grpc_error *error);
 
-void grpc_cq_global_init(void) { gpr_mu_init(&g_freelist_mu); }
-
-void grpc_cq_global_shutdown(void) {
-  gpr_mu_destroy(&g_freelist_mu);
-  while (g_freelist) {
-    grpc_completion_queue *next = g_freelist->next_free;
-    grpc_pollset_destroy(POLLSET_FROM_CQ(g_freelist));
-#ifndef NDEBUG
-    gpr_free(g_freelist->outstanding_tags);
-#endif
-    gpr_free(g_freelist);
-    g_freelist = next;
-  }
-}
-
 grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
   grpc_completion_queue *cc;
   GPR_ASSERT(!reserved);
@@ -136,22 +118,12 @@
 
   GRPC_API_TRACE("grpc_completion_queue_create(reserved=%p)", 1, (reserved));
 
-  gpr_mu_lock(&g_freelist_mu);
-  if (g_freelist == NULL) {
-    gpr_mu_unlock(&g_freelist_mu);
-
-    cc = gpr_malloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
-    grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
+  cc = gpr_zalloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
+  grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
 #ifndef NDEBUG
-    cc->outstanding_tags = NULL;
-    cc->outstanding_tag_capacity = 0;
+  cc->outstanding_tags = NULL;
+  cc->outstanding_tag_capacity = 0;
 #endif
-  } else {
-    cc = g_freelist;
-    g_freelist = g_freelist->next_free;
-    gpr_mu_unlock(&g_freelist_mu);
-    /* pollset already initialized */
-  }
 
   /* Initial ref is dropped by grpc_completion_queue_shutdown */
   gpr_ref_init(&cc->pending_events, 1);
@@ -203,11 +175,11 @@
 #endif
   if (gpr_unref(&cc->owning_refs)) {
     GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head);
-    grpc_pollset_reset(POLLSET_FROM_CQ(cc));
-    gpr_mu_lock(&g_freelist_mu);
-    cc->next_free = g_freelist;
-    g_freelist = cc;
-    gpr_mu_unlock(&g_freelist_mu);
+    grpc_pollset_destroy(POLLSET_FROM_CQ(cc));
+#ifndef NDEBUG
+    gpr_free(cc->outstanding_tags);
+#endif
+    gpr_free(cc);
   }
 }
 
@@ -253,7 +225,6 @@
     if (grpc_trace_operation_failures && error != GRPC_ERROR_NONE) {
       gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg);
     }
-    grpc_error_free_string(errmsg);
   }
 
   storage->tag = tag;
@@ -294,7 +265,7 @@
     if (kick_error != GRPC_ERROR_NONE) {
       const char *msg = grpc_error_string(kick_error);
       gpr_log(GPR_ERROR, "Kick failed: %s", msg);
-      grpc_error_free_string(msg);
+
       GRPC_ERROR_UNREF(kick_error);
     }
   } else {
@@ -403,8 +374,8 @@
       .stolen_completion = NULL,
       .tag = NULL,
       .first_loop = true};
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(
-      cq_is_next_finished, &is_finished_arg);
+  grpc_exec_ctx exec_ctx =
+      GRPC_EXEC_CTX_INITIALIZER(0, cq_is_next_finished, &is_finished_arg);
   for (;;) {
     if (is_finished_arg.stolen_completion != NULL) {
       gpr_mu_unlock(cc->mu);
@@ -461,7 +432,7 @@
         gpr_mu_unlock(cc->mu);
         const char *msg = grpc_error_string(err);
         gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg);
-        grpc_error_free_string(msg);
+
         GRPC_ERROR_UNREF(err);
         memset(&ret, 0, sizeof(ret));
         ret.type = GRPC_QUEUE_TIMEOUT;
@@ -572,8 +543,8 @@
       .stolen_completion = NULL,
       .tag = tag,
       .first_loop = true};
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(
-      cq_is_pluck_finished, &is_finished_arg);
+  grpc_exec_ctx exec_ctx =
+      GRPC_EXEC_CTX_INITIALIZER(0, cq_is_pluck_finished, &is_finished_arg);
   for (;;) {
     if (is_finished_arg.stolen_completion != NULL) {
       gpr_mu_unlock(cc->mu);
@@ -647,7 +618,7 @@
         gpr_mu_unlock(cc->mu);
         const char *msg = grpc_error_string(err);
         gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg);
-        grpc_error_free_string(msg);
+
         GRPC_ERROR_UNREF(err);
         memset(&ret, 0, sizeof(ret));
         ret.type = GRPC_QUEUE_TIMEOUT;
diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h
index c1cafba..5d73dd7 100644
--- a/src/core/lib/surface/completion_queue.h
+++ b/src/core/lib/surface/completion_queue.h
@@ -99,7 +99,4 @@
 void grpc_cq_mark_server_cq(grpc_completion_queue *cc);
 int grpc_cq_is_server_cq(grpc_completion_queue *cc);
 
-void grpc_cq_global_init(void);
-void grpc_cq_global_shutdown(void);
-
 #endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H */
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
index f61bf15..91bd014 100644
--- a/src/core/lib/surface/init.c
+++ b/src/core/lib/surface/init.c
@@ -55,6 +55,7 @@
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/resource_quota.h"
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/channel_init.h"
@@ -62,6 +63,7 @@
 #include "src/core/lib/surface/init.h"
 #include "src/core/lib/surface/lame_client.h"
 #include "src/core/lib/surface/server.h"
+#include "src/core/lib/transport/bdp_estimator.h"
 #include "src/core/lib/transport/connectivity_state.h"
 #include "src/core/lib/transport/transport_impl.h"
 
@@ -178,6 +180,7 @@
   gpr_mu_lock(&g_init_mu);
   if (++g_initializations == 1) {
     gpr_time_init();
+    grpc_slice_intern_init();
     grpc_mdctx_global_init();
     grpc_channel_init_init();
     grpc_register_tracer("api", &grpc_api_trace);
@@ -190,6 +193,7 @@
     grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace);
     grpc_register_tracer("combiner", &grpc_combiner_trace);
     grpc_register_tracer("server_channel", &grpc_server_channel_trace);
+    grpc_register_tracer("bdp_estimator", &grpc_bdp_estimator_trace);
     // Default pluck trace to 1
     grpc_cq_pluck_trace = 1;
     grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace);
@@ -197,6 +201,7 @@
     grpc_cq_event_timeout_trace = 1;
     grpc_register_tracer("op_failure", &grpc_trace_operation_failures);
     grpc_register_tracer("resource_quota", &grpc_resource_quota_trace);
+    grpc_register_tracer("call_error", &grpc_call_error_trace);
 #ifndef NDEBUG
     grpc_register_tracer("pending_tags", &grpc_trace_pending_tags);
 #endif
@@ -204,7 +209,6 @@
     grpc_iomgr_init();
     grpc_executor_init();
     gpr_timers_global_init();
-    grpc_cq_global_init();
     grpc_handshaker_factory_registry_init();
     grpc_security_init();
     for (i = 0; i < g_number_of_plugins; i++) {
@@ -231,7 +235,6 @@
   gpr_mu_lock(&g_init_mu);
   if (--g_initializations == 0) {
     grpc_executor_shutdown(&exec_ctx);
-    grpc_cq_global_shutdown();
     grpc_iomgr_shutdown(&exec_ctx);
     gpr_timers_global_destroy();
     grpc_tracer_shutdown();
@@ -242,6 +245,7 @@
     }
     grpc_mdctx_global_shutdown(&exec_ctx);
     grpc_handshaker_factory_registry_shutdown(&exec_ctx);
+    grpc_slice_intern_shutdown();
   }
   gpr_mu_unlock(&g_init_mu);
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/src/core/lib/surface/init_secure.c b/src/core/lib/surface/init_secure.c
index a44407d..46b9a8f 100644
--- a/src/core/lib/surface/init_secure.c
+++ b/src/core/lib/surface/init_secure.c
@@ -56,7 +56,7 @@
       grpc_channel_stack_builder_get_channel_arguments(builder);
   if (args) {
     for (size_t i = 0; i < args->num_args; i++) {
-      if (0 == strcmp(GRPC_SECURITY_CONNECTOR_ARG, args->args[i].key)) {
+      if (0 == strcmp(GRPC_ARG_SECURITY_CONNECTOR, args->args[i].key)) {
         return grpc_channel_stack_builder_prepend_filter(
             builder, &grpc_client_auth_filter, NULL, NULL);
       }
diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c
index ae1eac0..49bc4c1 100644
--- a/src/core/lib/surface/lame_client.c
+++ b/src/core/lib/surface/lame_client.c
@@ -44,10 +44,12 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/channel.h"
+#include "src/core/lib/transport/static_metadata.h"
 
 typedef struct {
   grpc_linked_mdelem status;
   grpc_linked_mdelem details;
+  gpr_atm filled_metadata;
 } call_data;
 
 typedef struct {
@@ -58,17 +60,23 @@
 static void fill_metadata(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
                           grpc_metadata_batch *mdb) {
   call_data *calld = elem->call_data;
+  if (!gpr_atm_no_barrier_cas(&calld->filled_metadata, 0, 1)) {
+    return;
+  }
   channel_data *chand = elem->channel_data;
   char tmp[GPR_LTOA_MIN_BUFSIZE];
   gpr_ltoa(chand->error_code, tmp);
-  calld->status.md = grpc_mdelem_from_strings(exec_ctx, "grpc-status", tmp);
-  calld->details.md =
-      grpc_mdelem_from_strings(exec_ctx, "grpc-message", chand->error_message);
+  calld->status.md = grpc_mdelem_from_slices(
+      exec_ctx, GRPC_MDSTR_GRPC_STATUS, grpc_slice_from_copied_string(tmp));
+  calld->details.md = grpc_mdelem_from_slices(
+      exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
+      grpc_slice_from_copied_string(chand->error_message));
   calld->status.prev = calld->details.next = NULL;
   calld->status.next = &calld->details;
   calld->details.prev = &calld->status;
   mdb->list.head = &calld->status;
   mdb->list.tail = &calld->details;
+  mdb->list.count = 2;
   mdb->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
 }
 
@@ -114,7 +122,9 @@
 
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
+  call_data *calld = elem->call_data;
+  gpr_atm_no_barrier_store(&calld->filled_metadata, 0);
   return GRPC_ERROR_NONE;
 }
 
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 9e91646..b360579 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -98,8 +98,9 @@
 typedef struct channel_registered_method {
   registered_method *server_registered_method;
   uint32_t flags;
-  grpc_mdstr *method;
-  grpc_mdstr *host;
+  bool has_host;
+  grpc_slice method;
+  grpc_slice host;
 } channel_registered_method;
 
 struct channel_data {
@@ -144,8 +145,10 @@
   /** the current state of a call - see call_state */
   call_state state;
 
-  grpc_mdstr *path;
-  grpc_mdstr *host;
+  bool path_set;
+  bool host_set;
+  grpc_slice path;
+  grpc_slice host;
   gpr_timespec deadline;
 
   grpc_completion_queue *cq_new;
@@ -277,18 +280,20 @@
 }
 
 static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
-                          int send_goaway, grpc_error *send_disconnect) {
+                          bool send_goaway, grpc_error *send_disconnect) {
   struct shutdown_cleanup_args *sc = gpr_malloc(sizeof(*sc));
   grpc_closure_init(&sc->closure, shutdown_cleanup, sc,
                     grpc_schedule_on_exec_ctx);
   grpc_transport_op *op = grpc_make_transport_op(&sc->closure);
   grpc_channel_element *elem;
 
-  op->send_goaway = send_goaway;
+  op->goaway_error =
+      send_goaway
+          ? grpc_error_set_int(GRPC_ERROR_CREATE("Server shutdown"),
+                               GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK)
+          : GRPC_ERROR_NONE;
   op->set_accept_stream = true;
   sc->slice = grpc_slice_from_copied_string("Server shutdown");
-  op->goaway_message = &sc->slice;
-  op->goaway_status = GRPC_STATUS_OK;
   op->disconnect_with_error = send_disconnect;
 
   elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
@@ -448,7 +453,6 @@
   if (grpc_server_channel_trace && error != GRPC_ERROR_NONE) {
     const char *msg = grpc_error_string(error);
     gpr_log(GPR_INFO, "Disconnected client: %s", msg);
-    grpc_error_free_string(msg);
   }
   GRPC_ERROR_UNREF(error);
 
@@ -461,17 +465,6 @@
                        op);
 }
 
-static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
-  grpc_slice slice = value->slice;
-  size_t len = GRPC_SLICE_LENGTH(slice);
-
-  if (len + 1 > *capacity) {
-    *capacity = GPR_MAX(len + 1, *capacity * 2);
-    *dest = gpr_realloc(*dest, *capacity);
-  }
-  memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
-}
-
 static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
                                grpc_cq_completion *c) {
   requested_call *rc = req;
@@ -500,12 +493,10 @@
   GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
   switch (rc->type) {
     case BATCH_CALL:
-      GPR_ASSERT(calld->host != NULL);
-      GPR_ASSERT(calld->path != NULL);
-      cpstr(&rc->data.batch.details->host,
-            &rc->data.batch.details->host_capacity, calld->host);
-      cpstr(&rc->data.batch.details->method,
-            &rc->data.batch.details->method_capacity, calld->path);
+      GPR_ASSERT(calld->host_set);
+      GPR_ASSERT(calld->path_set);
+      rc->data.batch.details->host = grpc_slice_ref_internal(calld->host);
+      rc->data.batch.details->method = grpc_slice_ref_internal(calld->path);
       rc->data.batch.details->deadline = calld->deadline;
       rc->data.batch.details->flags =
           (calld->recv_idempotent_request
@@ -549,7 +540,8 @@
         &calld->kill_zombie_closure, kill_zombie,
         grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0),
         grpc_schedule_on_exec_ctx);
-    grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, error);
+    grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure,
+                       GRPC_ERROR_REF(error));
     return;
   }
 
@@ -627,35 +619,39 @@
   uint32_t hash;
   channel_registered_method *rm;
 
-  if (chand->registered_methods && calld->path && calld->host) {
+  if (chand->registered_methods && calld->path_set && calld->host_set) {
     /* TODO(ctiller): unify these two searches */
     /* check for an exact match with host */
-    hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
+    hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(calld->host),
+                              grpc_slice_hash(calld->path));
     for (i = 0; i <= chand->registered_method_max_probes; i++) {
       rm = &chand->registered_methods[(hash + i) %
                                       chand->registered_method_slots];
       if (!rm) break;
-      if (rm->host != calld->host) continue;
-      if (rm->method != calld->path) continue;
+      if (!rm->has_host) continue;
+      if (!grpc_slice_eq(rm->host, calld->host)) continue;
+      if (!grpc_slice_eq(rm->method, calld->path)) continue;
       if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
-          !calld->recv_idempotent_request)
+          !calld->recv_idempotent_request) {
         continue;
+      }
       finish_start_new_rpc(exec_ctx, server, elem,
                            &rm->server_registered_method->request_matcher,
                            rm->server_registered_method->payload_handling);
       return;
     }
     /* check for a wildcard method definition (no host set) */
-    hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
+    hash = GRPC_MDSTR_KV_HASH(0, grpc_slice_hash(calld->path));
     for (i = 0; i <= chand->registered_method_max_probes; i++) {
       rm = &chand->registered_methods[(hash + i) %
                                       chand->registered_method_slots];
       if (!rm) break;
-      if (rm->host != NULL) continue;
-      if (rm->method != calld->path) continue;
+      if (rm->has_host) continue;
+      if (!grpc_slice_eq(rm->method, calld->path)) continue;
       if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
-          !calld->recv_idempotent_request)
+          !calld->recv_idempotent_request) {
         continue;
+      }
       finish_start_new_rpc(exec_ctx, server, elem,
                            &rm->server_registered_method->request_matcher,
                            rm->server_registered_method->payload_handling);
@@ -744,43 +740,40 @@
   }
 }
 
-static grpc_mdelem *server_filter(grpc_exec_ctx *exec_ctx, void *user_data,
-                                  grpc_mdelem *md) {
-  grpc_call_element *elem = user_data;
-  call_data *calld = elem->call_data;
-  if (md->key == GRPC_MDSTR_PATH) {
-    if (calld->path == NULL) {
-      calld->path = GRPC_MDSTR_REF(md->value);
-    }
-    return NULL;
-  } else if (md->key == GRPC_MDSTR_AUTHORITY) {
-    if (calld->host == NULL) {
-      calld->host = GRPC_MDSTR_REF(md->value);
-    }
-    return NULL;
-  }
-  return md;
-}
-
 static void server_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, void *ptr,
                                             grpc_error *error) {
   grpc_call_element *elem = ptr;
   call_data *calld = elem->call_data;
   gpr_timespec op_deadline;
 
-  GRPC_ERROR_REF(error);
-  grpc_metadata_batch_filter(exec_ctx, calld->recv_initial_metadata,
-                             server_filter, elem);
+  if (error == GRPC_ERROR_NONE) {
+    GPR_ASSERT(calld->recv_initial_metadata->idx.named.path != NULL);
+    GPR_ASSERT(calld->recv_initial_metadata->idx.named.authority != NULL);
+    calld->path = grpc_slice_ref_internal(
+        GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md));
+    calld->host = grpc_slice_ref_internal(
+        GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.authority->md));
+    calld->path_set = true;
+    calld->host_set = true;
+    grpc_metadata_batch_remove(exec_ctx, calld->recv_initial_metadata,
+                               calld->recv_initial_metadata->idx.named.path);
+    grpc_metadata_batch_remove(
+        exec_ctx, calld->recv_initial_metadata,
+        calld->recv_initial_metadata->idx.named.authority);
+  } else {
+    GRPC_ERROR_REF(error);
+  }
   op_deadline = calld->recv_initial_metadata->deadline;
   if (0 != gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
     calld->deadline = op_deadline;
   }
-  if (calld->host && calld->path) {
+  if (calld->host_set && calld->path_set) {
     /* do nothing */
   } else {
-    GRPC_ERROR_UNREF(error);
+    grpc_error *src_error = error;
     error =
         GRPC_ERROR_CREATE_REFERENCING("Missing :authority or :path", &error, 1);
+    GRPC_ERROR_UNREF(src_error);
   }
 
   grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata, error);
@@ -887,7 +880,7 @@
 
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
   memset(calld, 0, sizeof(call_data));
@@ -911,11 +904,11 @@
 
   GPR_ASSERT(calld->state != PENDING);
 
-  if (calld->host) {
-    GRPC_MDSTR_UNREF(exec_ctx, calld->host);
+  if (calld->host_set) {
+    grpc_slice_unref_internal(exec_ctx, calld->host);
   }
-  if (calld->path) {
-    GRPC_MDSTR_UNREF(exec_ctx, calld->path);
+  if (calld->path_set) {
+    grpc_slice_unref_internal(exec_ctx, calld->path);
   }
   grpc_metadata_array_destroy(&calld->initial_metadata);
 
@@ -947,11 +940,9 @@
   channel_data *chand = elem->channel_data;
   if (chand->registered_methods) {
     for (i = 0; i < chand->registered_method_slots; i++) {
-      if (chand->registered_methods[i].method) {
-        GRPC_MDSTR_UNREF(exec_ctx, chand->registered_methods[i].method);
-      }
-      if (chand->registered_methods[i].host) {
-        GRPC_MDSTR_UNREF(exec_ctx, chand->registered_methods[i].host);
+      grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].method);
+      if (chand->registered_methods[i].has_host) {
+        grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].host);
       }
     }
     gpr_free(chand->registered_methods);
@@ -1025,12 +1016,10 @@
 grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
   GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved));
 
-  grpc_server *server = gpr_malloc(sizeof(grpc_server));
+  grpc_server *server = gpr_zalloc(sizeof(grpc_server));
 
   GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
 
-  memset(server, 0, sizeof(grpc_server));
-
   gpr_mu_init(&server->mu_global);
   gpr_mu_init(&server->mu_call);
 
@@ -1079,8 +1068,7 @@
             flags);
     return NULL;
   }
-  m = gpr_malloc(sizeof(registered_method));
-  memset(m, 0, sizeof(*m));
+  m = gpr_zalloc(sizeof(registered_method));
   m->method = gpr_strdup(method);
   m->host = gpr_strdup(host);
   m->next = server->registered_methods;
@@ -1149,8 +1137,6 @@
   channel_registered_method *crm;
   grpc_channel *channel;
   channel_data *chand;
-  grpc_mdstr *host;
-  grpc_mdstr *method;
   uint32_t hash;
   size_t slots;
   uint32_t probes;
@@ -1186,12 +1172,20 @@
   if (num_registered_methods > 0) {
     slots = 2 * num_registered_methods;
     alloc = sizeof(channel_registered_method) * slots;
-    chand->registered_methods = gpr_malloc(alloc);
-    memset(chand->registered_methods, 0, alloc);
+    chand->registered_methods = gpr_zalloc(alloc);
     for (rm = s->registered_methods; rm; rm = rm->next) {
-      host = rm->host ? grpc_mdstr_from_string(rm->host) : NULL;
-      method = grpc_mdstr_from_string(rm->method);
-      hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
+      grpc_slice host;
+      bool has_host;
+      grpc_slice method;
+      if (rm->host != NULL) {
+        host = grpc_slice_intern(grpc_slice_from_static_string(rm->host));
+        has_host = true;
+      } else {
+        has_host = false;
+      }
+      method = grpc_slice_intern(grpc_slice_from_static_string(rm->method));
+      hash = GRPC_MDSTR_KV_HASH(has_host ? grpc_slice_hash(host) : 0,
+                                grpc_slice_hash(method));
       for (probes = 0; chand->registered_methods[(hash + probes) % slots]
                            .server_registered_method != NULL;
            probes++)
@@ -1200,7 +1194,10 @@
       crm = &chand->registered_methods[(hash + probes) % slots];
       crm->server_registered_method = rm;
       crm->flags = rm->flags;
-      crm->host = host;
+      crm->has_host = has_host;
+      if (has_host) {
+        crm->host = host;
+      }
       crm->method = method;
     }
     GPR_ASSERT(slots <= UINT32_MAX);
diff --git a/src/core/lib/surface/validate_metadata.c b/src/core/lib/surface/validate_metadata.c
index f49dd85..7ec9137 100644
--- a/src/core/lib/surface/validate_metadata.c
+++ b/src/core/lib/surface/validate_metadata.c
@@ -34,40 +34,71 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
 #include <grpc/support/port_platform.h>
 
-static int conforms_to(const char *s, size_t len, const uint8_t *legal_bits) {
-  const char *p = s;
-  const char *e = s + len;
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
+
+static grpc_error *conforms_to(grpc_slice slice, const uint8_t *legal_bits,
+                               const char *err_desc) {
+  const uint8_t *p = GRPC_SLICE_START_PTR(slice);
+  const uint8_t *e = GRPC_SLICE_END_PTR(slice);
   for (; p != e; p++) {
-    int idx = (uint8_t)*p;
+    int idx = *p;
     int byte = idx / 8;
     int bit = idx % 8;
-    if ((legal_bits[byte] & (1 << bit)) == 0) return 0;
+    if ((legal_bits[byte] & (1 << bit)) == 0) {
+      char *dump = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
+      grpc_error *error = grpc_error_set_str(
+          grpc_error_set_int(GRPC_ERROR_CREATE(err_desc), GRPC_ERROR_INT_OFFSET,
+                             p - GRPC_SLICE_START_PTR(slice)),
+          GRPC_ERROR_STR_RAW_BYTES, dump);
+      gpr_free(dump);
+      return error;
+    }
   }
-  return 1;
+  return GRPC_ERROR_NONE;
 }
 
-int grpc_header_key_is_legal(const char *key, size_t length) {
+static int error2int(grpc_error *error) {
+  int r = (error == GRPC_ERROR_NONE);
+  GRPC_ERROR_UNREF(error);
+  return r;
+}
+
+grpc_error *grpc_validate_header_key_is_legal(grpc_slice slice) {
   static const uint8_t legal_header_bits[256 / 8] = {
       0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0x00, 0x00, 0x00,
       0x80, 0xfe, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-  if (length == 0 || key[0] == ':') {
-    return 0;
+  if (GRPC_SLICE_LENGTH(slice) == 0) {
+    return GRPC_ERROR_CREATE("Metadata keys cannot be zero length");
   }
-  return conforms_to(key, length, legal_header_bits);
+  if (GRPC_SLICE_START_PTR(slice)[0] == ':') {
+    return GRPC_ERROR_CREATE("Metadata keys cannot start with :");
+  }
+  return conforms_to(slice, legal_header_bits, "Illegal header key");
 }
 
-int grpc_header_nonbin_value_is_legal(const char *value, size_t length) {
+int grpc_header_key_is_legal(grpc_slice slice) {
+  return error2int(grpc_validate_header_key_is_legal(slice));
+}
+
+grpc_error *grpc_validate_header_nonbin_value_is_legal(grpc_slice slice) {
   static const uint8_t legal_header_bits[256 / 8] = {
       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-  return conforms_to(value, length, legal_header_bits);
+  return conforms_to(slice, legal_header_bits, "Illegal header value");
 }
 
-int grpc_is_binary_header(const char *key, size_t length) {
-  if (length < 5) return 0;
-  return 0 == memcmp(key + length - 4, "-bin", 4);
+int grpc_header_nonbin_value_is_legal(grpc_slice slice) {
+  return error2int(grpc_validate_header_nonbin_value_is_legal(slice));
+}
+
+int grpc_is_binary_header(grpc_slice slice) {
+  if (GRPC_SLICE_LENGTH(slice) < 5) return 0;
+  return 0 == memcmp(GRPC_SLICE_END_PTR(slice) - 4, "-bin", 4);
 }
diff --git a/src/core/lib/surface/validate_metadata.h b/src/core/lib/surface/validate_metadata.h
new file mode 100644
index 0000000..2b800d2
--- /dev/null
+++ b/src/core/lib/surface/validate_metadata.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H
+#define GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H
+
+#include <grpc/slice.h>
+#include "src/core/lib/iomgr/error.h"
+
+grpc_error *grpc_validate_header_key_is_legal(grpc_slice slice);
+grpc_error *grpc_validate_header_nonbin_value_is_legal(grpc_slice slice);
+
+#endif /* GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H */
diff --git a/src/core/lib/surface/version.c b/src/core/lib/surface/version.c
index ed6fd96..1143a9e 100644
--- a/src/core/lib/surface/version.c
+++ b/src/core/lib/surface/version.c
@@ -36,6 +36,6 @@
 
 #include <grpc/grpc.h>
 
-const char *grpc_version_string(void) { return "2.0.0"; }
+const char *grpc_version_string(void) { return "3.0.0-dev"; }
 
-const char *grpc_g_stands_for(void) { return "good"; }
+const char *grpc_g_stands_for(void) { return "green"; }
diff --git a/src/core/lib/transport/bdp_estimator.c b/src/core/lib/transport/bdp_estimator.c
new file mode 100644
index 0000000..e148367
--- /dev/null
+++ b/src/core/lib/transport/bdp_estimator.c
@@ -0,0 +1,104 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/transport/bdp_estimator.h"
+
+#include <stdlib.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+int grpc_bdp_estimator_trace = 0;
+
+void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name) {
+  estimator->estimate = 65536;
+  estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED;
+  estimator->name = name;
+}
+
+bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
+                                     int64_t *estimate) {
+  *estimate = estimator->estimate;
+  return true;
+}
+
+bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
+                                           int64_t num_bytes) {
+  estimator->accumulator += num_bytes;
+  switch (estimator->ping_state) {
+    case GRPC_BDP_PING_UNSCHEDULED:
+      return true;
+    case GRPC_BDP_PING_SCHEDULED:
+      return false;
+    case GRPC_BDP_PING_STARTED:
+      return false;
+  }
+  GPR_UNREACHABLE_CODE(return false);
+}
+
+void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator) {
+  if (grpc_bdp_estimator_trace) {
+    gpr_log(GPR_DEBUG, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64,
+            estimator->name, estimator->accumulator, estimator->estimate);
+  }
+  GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_UNSCHEDULED);
+  estimator->ping_state = GRPC_BDP_PING_SCHEDULED;
+  estimator->accumulator = 0;
+}
+
+void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator) {
+  if (grpc_bdp_estimator_trace) {
+    gpr_log(GPR_DEBUG, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64,
+            estimator->name, estimator->accumulator, estimator->estimate);
+  }
+  GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_SCHEDULED);
+  estimator->ping_state = GRPC_BDP_PING_STARTED;
+  estimator->accumulator = 0;
+}
+
+void grpc_bdp_estimator_complete_ping(grpc_bdp_estimator *estimator) {
+  if (grpc_bdp_estimator_trace) {
+    gpr_log(GPR_DEBUG, "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64,
+            estimator->name, estimator->accumulator, estimator->estimate);
+  }
+  GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_STARTED);
+  if (estimator->accumulator > 2 * estimator->estimate / 3) {
+    estimator->estimate *= 2;
+    if (grpc_bdp_estimator_trace) {
+      gpr_log(GPR_DEBUG, "bdp[%s]: estimate increased to %" PRId64,
+              estimator->name, estimator->estimate);
+    }
+  }
+  estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED;
+  estimator->accumulator = 0;
+}
diff --git a/src/core/lib/transport/bdp_estimator.h b/src/core/lib/transport/bdp_estimator.h
new file mode 100644
index 0000000..bcaf899
--- /dev/null
+++ b/src/core/lib/transport/bdp_estimator.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H
+#define GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define GRPC_BDP_SAMPLES 16
+#define GRPC_BDP_MIN_SAMPLES_FOR_ESTIMATE 3
+
+extern int grpc_bdp_estimator_trace;
+
+typedef enum {
+  GRPC_BDP_PING_UNSCHEDULED,
+  GRPC_BDP_PING_SCHEDULED,
+  GRPC_BDP_PING_STARTED
+} grpc_bdp_estimator_ping_state;
+
+typedef struct grpc_bdp_estimator {
+  grpc_bdp_estimator_ping_state ping_state;
+  int64_t accumulator;
+  int64_t estimate;
+  const char *name;
+} grpc_bdp_estimator;
+
+void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name);
+
+// Returns true if a reasonable estimate could be obtained
+bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
+                                     int64_t *estimate);
+// Returns true if the user should schedule a ping
+bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
+                                           int64_t num_bytes);
+// Schedule a ping: call in response to receiving a true from
+// grpc_bdp_estimator_add_incoming_bytes once a ping has been scheduled by a
+// transport (but not necessarily started)
+void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator);
+// Start a ping: call after calling grpc_bdp_estimator_schedule_ping and once
+// the ping is on the wire
+void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator);
+// Completes a previously started ping
+void grpc_bdp_estimator_complete_ping(grpc_bdp_estimator *estimator);
+
+#endif
diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c
index c656d93..afe1f61 100644
--- a/src/core/lib/transport/connectivity_state.c
+++ b/src/core/lib/transport/connectivity_state.c
@@ -62,7 +62,7 @@
 void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
                                   grpc_connectivity_state init_state,
                                   const char *name) {
-  tracker->current_state = init_state;
+  gpr_atm_no_barrier_store(&tracker->current_state_atm, init_state);
   tracker->current_error = GRPC_ERROR_NONE;
   tracker->watchers = NULL;
   tracker->name = gpr_strdup(name);
@@ -89,15 +89,30 @@
 }
 
 grpc_connectivity_state grpc_connectivity_state_check(
-    grpc_connectivity_state_tracker *tracker, grpc_error **error) {
+    grpc_connectivity_state_tracker *tracker) {
+  grpc_connectivity_state cur =
+      (grpc_connectivity_state)gpr_atm_no_barrier_load(
+          &tracker->current_state_atm);
   if (grpc_connectivity_state_trace) {
     gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
-            grpc_connectivity_state_name(tracker->current_state));
+            grpc_connectivity_state_name(cur));
+  }
+  return cur;
+}
+
+grpc_connectivity_state grpc_connectivity_state_get(
+    grpc_connectivity_state_tracker *tracker, grpc_error **error) {
+  grpc_connectivity_state cur =
+      (grpc_connectivity_state)gpr_atm_no_barrier_load(
+          &tracker->current_state_atm);
+  if (grpc_connectivity_state_trace) {
+    gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
+            grpc_connectivity_state_name(cur));
   }
   if (error != NULL) {
     *error = GRPC_ERROR_REF(tracker->current_error);
   }
-  return tracker->current_state;
+  return cur;
 }
 
 bool grpc_connectivity_state_has_watchers(
@@ -108,6 +123,9 @@
 bool grpc_connectivity_state_notify_on_state_change(
     grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
     grpc_connectivity_state *current, grpc_closure *notify) {
+  grpc_connectivity_state cur =
+      (grpc_connectivity_state)gpr_atm_no_barrier_load(
+          &tracker->current_state_atm);
   if (grpc_connectivity_state_trace) {
     if (current == NULL) {
       gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
@@ -115,7 +133,7 @@
     } else {
       gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
               tracker->name, grpc_connectivity_state_name(*current),
-              grpc_connectivity_state_name(tracker->current_state), notify);
+              grpc_connectivity_state_name(cur), notify);
     }
   }
   if (current == NULL) {
@@ -138,8 +156,8 @@
     }
     return false;
   } else {
-    if (tracker->current_state != *current) {
-      *current = tracker->current_state;
+    if (cur != *current) {
+      *current = cur;
       grpc_closure_sched(exec_ctx, notify,
                          GRPC_ERROR_REF(tracker->current_error));
     } else {
@@ -149,7 +167,7 @@
       w->next = tracker->watchers;
       tracker->watchers = w;
     }
-    return tracker->current_state == GRPC_CHANNEL_IDLE;
+    return cur == GRPC_CHANNEL_IDLE;
   }
 }
 
@@ -157,13 +175,15 @@
                                  grpc_connectivity_state_tracker *tracker,
                                  grpc_connectivity_state state,
                                  grpc_error *error, const char *reason) {
+  grpc_connectivity_state cur =
+      (grpc_connectivity_state)gpr_atm_no_barrier_load(
+          &tracker->current_state_atm);
   grpc_connectivity_state_watcher *w;
   if (grpc_connectivity_state_trace) {
     const char *error_string = grpc_error_string(error);
     gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
-            tracker->name, grpc_connectivity_state_name(tracker->current_state),
+            tracker->name, grpc_connectivity_state_name(cur),
             grpc_connectivity_state_name(state), reason, error, error_string);
-    grpc_error_free_string(error_string);
   }
   switch (state) {
     case GRPC_CHANNEL_INIT:
@@ -179,13 +199,13 @@
   }
   GRPC_ERROR_UNREF(tracker->current_error);
   tracker->current_error = error;
-  if (tracker->current_state == state) {
+  if (cur == state) {
     return;
   }
-  GPR_ASSERT(tracker->current_state != GRPC_CHANNEL_SHUTDOWN);
-  tracker->current_state = state;
+  GPR_ASSERT(cur != GRPC_CHANNEL_SHUTDOWN);
+  gpr_atm_no_barrier_store(&tracker->current_state_atm, state);
   while ((w = tracker->watchers) != NULL) {
-    *w->current = tracker->current_state;
+    *w->current = state;
     tracker->watchers = w->next;
     if (grpc_connectivity_state_trace) {
       gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name,
diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h
index 769c675..c9604c3 100644
--- a/src/core/lib/transport/connectivity_state.h
+++ b/src/core/lib/transport/connectivity_state.h
@@ -47,8 +47,8 @@
 } grpc_connectivity_state_watcher;
 
 typedef struct {
-  /** current connectivity state */
-  grpc_connectivity_state current_state;
+  /** current grpc_connectivity_state */
+  gpr_atm current_state_atm;
   /** error associated with state */
   grpc_error *current_error;
   /** all our watchers */
@@ -59,6 +59,7 @@
 
 extern int grpc_connectivity_state_trace;
 
+/** enum --> string conversion */
 const char *grpc_connectivity_state_name(grpc_connectivity_state state);
 
 void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
@@ -68,22 +69,31 @@
                                      grpc_connectivity_state_tracker *tracker);
 
 /** Set connectivity state; not thread safe; access must be serialized with an
- * external lock */
+ *  external lock */
 void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
                                  grpc_connectivity_state_tracker *tracker,
                                  grpc_connectivity_state state,
                                  grpc_error *associated_error,
                                  const char *reason);
 
+/** Return true if this connectivity state has watchers.
+    Access must be serialized with an external lock. */
 bool grpc_connectivity_state_has_watchers(
     grpc_connectivity_state_tracker *tracker);
 
+/** Return the last seen connectivity state. No need to synchronize access. */
 grpc_connectivity_state grpc_connectivity_state_check(
-    grpc_connectivity_state_tracker *tracker, grpc_error **current_error);
+    grpc_connectivity_state_tracker *tracker);
+
+/** Return the last seen connectivity state, and the associated error.
+    Access must be serialized with an external lock. */
+grpc_connectivity_state grpc_connectivity_state_get(
+    grpc_connectivity_state_tracker *tracker, grpc_error **error);
 
 /** Return 1 if the channel should start connecting, 0 otherwise.
     If current==NULL cancel notify if it is already queued (success==0 in that
-    case) */
+    case).
+    Access must be serialized with an external lock. */
 bool grpc_connectivity_state_notify_on_state_change(
     grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
     grpc_connectivity_state *current, grpc_closure *notify);
diff --git a/src/core/lib/transport/error_utils.c b/src/core/lib/transport/error_utils.c
new file mode 100644
index 0000000..da77828
--- /dev/null
+++ b/src/core/lib/transport/error_utils.c
@@ -0,0 +1,124 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/transport/error_utils.h"
+
+#include "src/core/lib/iomgr/error_internal.h"
+#include "src/core/lib/transport/status_conversion.h"
+
+static grpc_error *recursively_find_error_with_field(grpc_error *error,
+                                                     grpc_error_ints which) {
+  // If the error itself has a status code, return it.
+  if (grpc_error_get_int(error, which, NULL)) {
+    return error;
+  }
+  if (grpc_error_is_special(error)) return NULL;
+  // Otherwise, search through its children.
+  intptr_t key = 0;
+  while (true) {
+    grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++);
+    if (child_error == NULL) break;
+    grpc_error *result = recursively_find_error_with_field(child_error, which);
+    if (result != NULL) return result;
+  }
+  return NULL;
+}
+
+void grpc_error_get_status(grpc_error *error, gpr_timespec deadline,
+                           grpc_status_code *code, const char **msg,
+                           grpc_http2_error_code *http_error) {
+  // Start with the parent error and recurse through the tree of children
+  // until we find the first one that has a status code.
+  grpc_error *found_error =
+      recursively_find_error_with_field(error, GRPC_ERROR_INT_GRPC_STATUS);
+  if (found_error == NULL) {
+    /// If no grpc-status exists, retry through the tree to find a http2 error
+    /// code
+    found_error =
+        recursively_find_error_with_field(error, GRPC_ERROR_INT_HTTP2_ERROR);
+  }
+
+  // If we found an error with a status code above, use that; otherwise,
+  // fall back to using the parent error.
+  if (found_error == NULL) found_error = error;
+
+  grpc_status_code status = GRPC_STATUS_UNKNOWN;
+  intptr_t integer;
+  if (grpc_error_get_int(found_error, GRPC_ERROR_INT_GRPC_STATUS, &integer)) {
+    status = (grpc_status_code)integer;
+  } else if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR,
+                                &integer)) {
+    status = grpc_http2_error_to_grpc_status((grpc_http2_error_code)integer,
+                                             deadline);
+  }
+  if (code != NULL) *code = status;
+
+  if (http_error != NULL) {
+    if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, &integer)) {
+      *http_error = (grpc_http2_error_code)integer;
+    } else if (grpc_error_get_int(found_error, GRPC_ERROR_INT_GRPC_STATUS,
+                                  &integer)) {
+      *http_error = grpc_status_to_http2_error((grpc_status_code)integer);
+    } else {
+      *http_error = found_error == GRPC_ERROR_NONE ? GRPC_HTTP2_NO_ERROR
+                                                   : GRPC_HTTP2_INTERNAL_ERROR;
+    }
+  }
+
+  // If the error has a status message, use it.  Otherwise, fall back to
+  // the error description.
+  if (msg != NULL) {
+    *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE);
+    if (*msg == NULL && error != GRPC_ERROR_NONE) {
+      *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION);
+      if (*msg == NULL) *msg = "unknown error";  // Just in case.
+    }
+  }
+
+  if (found_error == NULL) found_error = error;
+}
+
+bool grpc_error_has_clear_grpc_status(grpc_error *error) {
+  if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) {
+    return true;
+  }
+  intptr_t key = 0;
+  while (true) {
+    grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++);
+    if (child_error == NULL) break;
+    if (grpc_error_has_clear_grpc_status(child_error)) {
+      return true;
+    }
+  }
+  return false;
+}
diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h
new file mode 100644
index 0000000..1053388
--- /dev/null
+++ b/src/core/lib/transport/error_utils.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H
+#define GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H
+
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/transport/http2_errors.h"
+
+/// A utility function to get the status code and message to be returned
+/// to the application.  If not set in the top-level message, looks
+/// through child errors until it finds the first one with these attributes.
+/// All attributes are pulled from the same child error. If any of the
+/// attributes (code, msg, http_status) are unneeded, they can be passed as
+/// NULL.
+void grpc_error_get_status(grpc_error *error, gpr_timespec deadline,
+                           grpc_status_code *code, const char **msg,
+                           grpc_http2_error_code *http_status);
+
+/// A utility function to check whether there is a clear status code that
+/// doesn't need to be guessed in \a error. This means that \a error or some
+/// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or
+/// GRPC_ERROR_CANCELLED
+bool grpc_error_has_clear_grpc_status(grpc_error *error);
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H */
diff --git a/src/core/lib/transport/http2_errors.h b/src/core/lib/transport/http2_errors.h
new file mode 100644
index 0000000..330bc98
--- /dev/null
+++ b/src/core/lib/transport/http2_errors.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H
+#define GRPC_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H
+
+/* error codes for RST_STREAM from http2 draft 14 section 7 */
+typedef enum {
+  GRPC_HTTP2_NO_ERROR = 0x0,
+  GRPC_HTTP2_PROTOCOL_ERROR = 0x1,
+  GRPC_HTTP2_INTERNAL_ERROR = 0x2,
+  GRPC_HTTP2_FLOW_CONTROL_ERROR = 0x3,
+  GRPC_HTTP2_SETTINGS_TIMEOUT = 0x4,
+  GRPC_HTTP2_STREAM_CLOSED = 0x5,
+  GRPC_HTTP2_FRAME_SIZE_ERROR = 0x6,
+  GRPC_HTTP2_REFUSED_STREAM = 0x7,
+  GRPC_HTTP2_CANCEL = 0x8,
+  GRPC_HTTP2_COMPRESSION_ERROR = 0x9,
+  GRPC_HTTP2_CONNECT_ERROR = 0xa,
+  GRPC_HTTP2_ENHANCE_YOUR_CALM = 0xb,
+  GRPC_HTTP2_INADEQUATE_SECURITY = 0xc,
+  /* force use of a default clause */
+  GRPC_HTTP2__ERROR_DO_NOT_USE = -1
+} grpc_http2_error_code;
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_HTTP2_ERRORS_H */
diff --git a/src/core/lib/transport/mdstr_hash_table.c b/src/core/lib/transport/mdstr_hash_table.c
deleted file mode 100644
index 2791bf6..0000000
--- a/src/core/lib/transport/mdstr_hash_table.c
+++ /dev/null
@@ -1,118 +0,0 @@
-//
-// Copyright 2016, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#include "src/core/lib/transport/mdstr_hash_table.h"
-
-#include <stdbool.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/lib/transport/metadata.h"
-
-struct grpc_mdstr_hash_table {
-  gpr_refcount refs;
-  size_t size;
-  grpc_mdstr_hash_table_entry* entries;
-};
-
-// Helper function for insert and get operations that performs quadratic
-// probing (https://en.wikipedia.org/wiki/Quadratic_probing).
-static size_t grpc_mdstr_hash_table_find_index(
-    const grpc_mdstr_hash_table* table, const grpc_mdstr* key,
-    bool find_empty) {
-  for (size_t i = 0; i < table->size; ++i) {
-    const size_t idx = (key->hash + i * i) % table->size;
-    if (table->entries[idx].key == NULL) return find_empty ? idx : table->size;
-    if (table->entries[idx].key == key) return idx;
-  }
-  return table->size;  // Not found.
-}
-
-static void grpc_mdstr_hash_table_add(
-    grpc_mdstr_hash_table* table, grpc_mdstr* key, void* value,
-    const grpc_mdstr_hash_table_vtable* vtable) {
-  GPR_ASSERT(value != NULL);
-  const size_t idx =
-      grpc_mdstr_hash_table_find_index(table, key, true /* find_empty */);
-  GPR_ASSERT(idx != table->size);  // Table should never be full.
-  grpc_mdstr_hash_table_entry* entry = &table->entries[idx];
-  entry->key = GRPC_MDSTR_REF(key);
-  entry->value = vtable->copy_value(value);
-  entry->vtable = vtable;
-}
-
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
-    size_t num_entries, grpc_mdstr_hash_table_entry* entries) {
-  grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table));
-  memset(table, 0, sizeof(*table));
-  gpr_ref_init(&table->refs, 1);
-  // Quadratic probing gets best performance when the table is no more
-  // than half full.
-  table->size = num_entries * 2;
-  const size_t entry_size = sizeof(grpc_mdstr_hash_table_entry) * table->size;
-  table->entries = gpr_malloc(entry_size);
-  memset(table->entries, 0, entry_size);
-  for (size_t i = 0; i < num_entries; ++i) {
-    grpc_mdstr_hash_table_entry* entry = &entries[i];
-    grpc_mdstr_hash_table_add(table, entry->key, entry->value, entry->vtable);
-  }
-  return table;
-}
-
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) {
-  if (table != NULL) gpr_ref(&table->refs);
-  return table;
-}
-
-void grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
-                                 grpc_mdstr_hash_table* table) {
-  if (table != NULL && gpr_unref(&table->refs)) {
-    for (size_t i = 0; i < table->size; ++i) {
-      grpc_mdstr_hash_table_entry* entry = &table->entries[i];
-      if (entry->key != NULL) {
-        GRPC_MDSTR_UNREF(exec_ctx, entry->key);
-        entry->vtable->destroy_value(exec_ctx, entry->value);
-      }
-    }
-    gpr_free(table->entries);
-    gpr_free(table);
-  }
-}
-
-void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
-                                const grpc_mdstr* key) {
-  const size_t idx =
-      grpc_mdstr_hash_table_find_index(table, key, false /* find_empty */);
-  if (idx == table->size) return NULL;  // Not found.
-  return table->entries[idx].value;
-}
diff --git a/src/core/lib/transport/mdstr_hash_table.h b/src/core/lib/transport/mdstr_hash_table.h
deleted file mode 100644
index 57f497e..0000000
--- a/src/core/lib/transport/mdstr_hash_table.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H
-#define GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H
-
-#include "src/core/lib/transport/metadata.h"
-
-/** Hash table implementation.
- *
- * This implementation uses open addressing
- * (https://en.wikipedia.org/wiki/Open_addressing) with quadratic
- * probing (https://en.wikipedia.org/wiki/Quadratic_probing).
- *
- * The keys are \a grpc_mdstr objects.  The values are arbitrary pointers
- * with a common vtable.
- *
- * Hash tables are intentionally immutable, to avoid the need for locking.
- */
-
-typedef struct grpc_mdstr_hash_table grpc_mdstr_hash_table;
-
-typedef struct grpc_mdstr_hash_table_vtable {
-  void (*destroy_value)(grpc_exec_ctx* exec_ctx, void* value);
-  void* (*copy_value)(void* value);
-} grpc_mdstr_hash_table_vtable;
-
-typedef struct grpc_mdstr_hash_table_entry {
-  grpc_mdstr* key;
-  void* value; /* Must not be NULL. */
-  const grpc_mdstr_hash_table_vtable* vtable;
-} grpc_mdstr_hash_table_entry;
-
-/** Creates a new hash table of containing \a entries, which is an array
-    of length \a num_entries.
-    Creates its own copy of all keys and values from \a entries. */
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
-    size_t num_entries, grpc_mdstr_hash_table_entry* entries);
-
-grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table);
-void grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
-                                 grpc_mdstr_hash_table* table);
-
-/** Returns the value from \a table associated with \a key.
-    Returns NULL if \a key is not found. */
-void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
-                                const grpc_mdstr* key);
-
-#endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index 54c39df..f2417d8 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -48,12 +48,11 @@
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/murmur_hash.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/transport/static_metadata.h"
 
-grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(grpc_slice input);
-
 /* There are two kinds of mdelem and mdstr instances.
  * Static instances are declared in static_metadata.{h,c} and
  * are initialized by grpc_mdctx_global_init().
@@ -63,9 +62,6 @@
  * used to determine which kind of element a pointer refers to.
  */
 
-#define INITIAL_STRTAB_CAPACITY 4
-#define INITIAL_MDTAB_CAPACITY 4
-
 #ifdef GRPC_METADATA_REFCOUNT_DEBUG
 #define DEBUG_ARGS , const char *file, int line
 #define FWD_DEBUG_ARGS , file, line
@@ -76,37 +72,20 @@
 #define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s))
 #endif
 
-#define TABLE_IDX(hash, log2_shards, capacity) \
-  (((hash) >> (log2_shards)) % (capacity))
-#define SHARD_IDX(hash, log2_shards) ((hash) & ((1 << (log2_shards)) - 1))
+#define INITIAL_SHARD_CAPACITY 8
+#define LOG2_SHARD_COUNT 4
+#define SHARD_COUNT ((size_t)(1 << LOG2_SHARD_COUNT))
+
+#define TABLE_IDX(hash, capacity) (((hash) >> (LOG2_SHARD_COUNT)) % (capacity))
+#define SHARD_IDX(hash) ((hash) & ((1 << (LOG2_SHARD_COUNT)) - 1))
 
 typedef void (*destroy_user_data_func)(void *user_data);
 
-#define SIZE_IN_DECODER_TABLE_NOT_SET -1
-/* Shadow structure for grpc_mdstr for non-static values */
-typedef struct internal_string {
-  /* must be byte compatible with grpc_mdstr */
-  grpc_slice slice;
-  uint32_t hash;
-
-  /* private only data */
-  gpr_atm refcnt;
-
-  uint8_t has_base64_and_huffman_encoded;
-  grpc_slice_refcount refcount;
-
-  grpc_slice base64_and_huffman;
-
-  gpr_atm size_in_decoder_table;
-
-  struct internal_string *bucket_next;
-} internal_string;
-
-/* Shadow structure for grpc_mdelem for non-static elements */
-typedef struct internal_metadata {
-  /* must be byte compatible with grpc_mdelem */
-  internal_string *key;
-  internal_string *value;
+/* Shadow structure for grpc_mdelem_data for interned elements */
+typedef struct interned_metadata {
+  /* must be byte compatible with grpc_mdelem_data */
+  grpc_slice key;
+  grpc_slice value;
 
   /* private only data */
   gpr_atm refcnt;
@@ -115,19 +94,22 @@
   gpr_atm destroy_user_data;
   gpr_atm user_data;
 
-  struct internal_metadata *bucket_next;
-} internal_metadata;
+  struct interned_metadata *bucket_next;
+} interned_metadata;
 
-typedef struct strtab_shard {
-  gpr_mu mu;
-  internal_string **strs;
-  size_t count;
-  size_t capacity;
-} strtab_shard;
+/* Shadow structure for grpc_mdelem_data for allocated elements */
+typedef struct allocated_metadata {
+  /* must be byte compatible with grpc_mdelem_data */
+  grpc_slice key;
+  grpc_slice value;
+
+  /* private only data */
+  gpr_atm refcnt;
+} allocated_metadata;
 
 typedef struct mdtab_shard {
   gpr_mu mu;
-  internal_metadata **elems;
+  interned_metadata **elems;
   size_t count;
   size_t capacity;
   /** Estimate of the number of unreferenced mdelems in the hash table.
@@ -136,102 +118,25 @@
   gpr_atm free_estimate;
 } mdtab_shard;
 
-#define LOG2_STRTAB_SHARD_COUNT 5
-#define LOG2_MDTAB_SHARD_COUNT 4
-#define STRTAB_SHARD_COUNT ((size_t)(1 << LOG2_STRTAB_SHARD_COUNT))
-#define MDTAB_SHARD_COUNT ((size_t)(1 << LOG2_MDTAB_SHARD_COUNT))
-
-/* hash seed: decided at initialization time */
-static uint32_t g_hash_seed;
-static int g_forced_hash_seed = 0;
-
-/* linearly probed hash tables for static element lookup */
-static grpc_mdstr *g_static_strtab[GRPC_STATIC_MDSTR_COUNT * 2];
-static grpc_mdelem *g_static_mdtab[GRPC_STATIC_MDELEM_COUNT * 2];
-static size_t g_static_strtab_maxprobe;
-static size_t g_static_mdtab_maxprobe;
-
-static strtab_shard g_strtab_shard[STRTAB_SHARD_COUNT];
-static mdtab_shard g_mdtab_shard[MDTAB_SHARD_COUNT];
+static mdtab_shard g_shards[SHARD_COUNT];
 
 static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard);
 
-void grpc_test_only_set_metadata_hash_seed(uint32_t seed) {
-  g_hash_seed = seed;
-  g_forced_hash_seed = 1;
-}
-
 void grpc_mdctx_global_init(void) {
-  size_t i, j;
-  if (!g_forced_hash_seed) {
-    g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
-  }
-  g_static_strtab_maxprobe = 0;
-  g_static_mdtab_maxprobe = 0;
-  /* build static tables */
-  memset(g_static_mdtab, 0, sizeof(g_static_mdtab));
-  memset(g_static_strtab, 0, sizeof(g_static_strtab));
-  for (i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
-    grpc_mdstr *elem = &grpc_static_mdstr_table[i];
-    const char *str = grpc_static_metadata_strings[i];
-    uint32_t hash = gpr_murmur_hash3(str, strlen(str), g_hash_seed);
-    *(grpc_slice *)&elem->slice = grpc_slice_from_static_string(str);
-    *(uint32_t *)&elem->hash = hash;
-    for (j = 0;; j++) {
-      size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_strtab);
-      if (g_static_strtab[idx] == NULL) {
-        g_static_strtab[idx] = &grpc_static_mdstr_table[i];
-        break;
-      }
-    }
-    if (j > g_static_strtab_maxprobe) {
-      g_static_strtab_maxprobe = j;
-    }
-  }
-  for (i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
-    grpc_mdelem *elem = &grpc_static_mdelem_table[i];
-    grpc_mdstr *key =
-        &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 0]];
-    grpc_mdstr *value =
-        &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 1]];
-    uint32_t hash = GRPC_MDSTR_KV_HASH(key->hash, value->hash);
-    *(grpc_mdstr **)&elem->key = key;
-    *(grpc_mdstr **)&elem->value = value;
-    for (j = 0;; j++) {
-      size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_mdtab);
-      if (g_static_mdtab[idx] == NULL) {
-        g_static_mdtab[idx] = elem;
-        break;
-      }
-    }
-    if (j > g_static_mdtab_maxprobe) {
-      g_static_mdtab_maxprobe = j;
-    }
-  }
   /* initialize shards */
-  for (i = 0; i < STRTAB_SHARD_COUNT; i++) {
-    strtab_shard *shard = &g_strtab_shard[i];
-    gpr_mu_init(&shard->mu);
-    shard->count = 0;
-    shard->capacity = INITIAL_STRTAB_CAPACITY;
-    shard->strs = gpr_malloc(sizeof(*shard->strs) * shard->capacity);
-    memset(shard->strs, 0, sizeof(*shard->strs) * shard->capacity);
-  }
-  for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
-    mdtab_shard *shard = &g_mdtab_shard[i];
+  for (size_t i = 0; i < SHARD_COUNT; i++) {
+    mdtab_shard *shard = &g_shards[i];
     gpr_mu_init(&shard->mu);
     shard->count = 0;
     gpr_atm_no_barrier_store(&shard->free_estimate, 0);
-    shard->capacity = INITIAL_MDTAB_CAPACITY;
-    shard->elems = gpr_malloc(sizeof(*shard->elems) * shard->capacity);
-    memset(shard->elems, 0, sizeof(*shard->elems) * shard->capacity);
+    shard->capacity = INITIAL_SHARD_CAPACITY;
+    shard->elems = gpr_zalloc(sizeof(*shard->elems) * shard->capacity);
   }
 }
 
 void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) {
-  size_t i;
-  for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
-    mdtab_shard *shard = &g_mdtab_shard[i];
+  for (size_t i = 0; i < SHARD_COUNT; i++) {
+    mdtab_shard *shard = &g_shards[i];
     gpr_mu_destroy(&shard->mu);
     gc_mdtab(exec_ctx, shard);
     /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
@@ -244,212 +149,35 @@
     }
     gpr_free(shard->elems);
   }
-  for (i = 0; i < STRTAB_SHARD_COUNT; i++) {
-    strtab_shard *shard = &g_strtab_shard[i];
-    gpr_mu_destroy(&shard->mu);
-    /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
-    if (shard->count != 0) {
-      gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata strings were leaked",
-              shard->count);
-      for (size_t j = 0; j < shard->capacity; j++) {
-        for (internal_string *s = shard->strs[j]; s; s = s->bucket_next) {
-          gpr_log(GPR_DEBUG, "LEAKED: %s",
-                  grpc_mdstr_as_c_string((grpc_mdstr *)s));
-        }
-      }
-      if (grpc_iomgr_abort_on_leaks()) {
-        abort();
-      }
-    }
-    gpr_free(shard->strs);
-  }
 }
 
-static int is_mdstr_static(grpc_mdstr *s) {
-  return s >= &grpc_static_mdstr_table[0] &&
-         s < &grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
-}
-
-static int is_mdelem_static(grpc_mdelem *e) {
-  return e >= &grpc_static_mdelem_table[0] &&
-         e < &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+static int is_mdelem_static(grpc_mdelem e) {
+  return GRPC_MDELEM_DATA(e) >= &grpc_static_mdelem_table[0] &&
+         GRPC_MDELEM_DATA(e) <
+             &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
 }
 
 static void ref_md_locked(mdtab_shard *shard,
-                          internal_metadata *md DEBUG_ARGS) {
+                          interned_metadata *md DEBUG_ARGS) {
 #ifdef GRPC_METADATA_REFCOUNT_DEBUG
+  char *key_str = grpc_slice_to_c_string(md->key);
+  char *value_str = grpc_slice_to_c_string(md->value);
   gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
           "ELM   REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
           gpr_atm_no_barrier_load(&md->refcnt),
-          gpr_atm_no_barrier_load(&md->refcnt) + 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+          gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
+  gpr_free(key_str);
+  gpr_free(value_str);
 #endif
   if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) {
     gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1);
   }
 }
 
-static void grow_strtab(strtab_shard *shard) {
-  size_t capacity = shard->capacity * 2;
-  size_t i;
-  internal_string **strtab;
-  internal_string *s, *next;
-
-  GPR_TIMER_BEGIN("grow_strtab", 0);
-
-  strtab = gpr_malloc(sizeof(internal_string *) * capacity);
-  memset(strtab, 0, sizeof(internal_string *) * capacity);
-
-  for (i = 0; i < shard->capacity; i++) {
-    for (s = shard->strs[i]; s; s = next) {
-      size_t idx = TABLE_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT, capacity);
-      next = s->bucket_next;
-      s->bucket_next = strtab[idx];
-      strtab[idx] = s;
-    }
-  }
-
-  gpr_free(shard->strs);
-  shard->strs = strtab;
-  shard->capacity = capacity;
-
-  GPR_TIMER_END("grow_strtab", 0);
-}
-
-static void internal_destroy_string(grpc_exec_ctx *exec_ctx,
-                                    strtab_shard *shard, internal_string *is) {
-  internal_string **prev_next;
-  internal_string *cur;
-  GPR_TIMER_BEGIN("internal_destroy_string", 0);
-  if (is->has_base64_and_huffman_encoded) {
-    grpc_slice_unref_internal(exec_ctx, is->base64_and_huffman);
-  }
-  for (prev_next = &shard->strs[TABLE_IDX(is->hash, LOG2_STRTAB_SHARD_COUNT,
-                                          shard->capacity)],
-      cur = *prev_next;
-       cur != is; prev_next = &cur->bucket_next, cur = cur->bucket_next)
-    ;
-  *prev_next = cur->bucket_next;
-  shard->count--;
-  gpr_free(is);
-  GPR_TIMER_END("internal_destroy_string", 0);
-}
-
-static void slice_ref(void *p) {
-  internal_string *is =
-      (internal_string *)((char *)p - offsetof(internal_string, refcount));
-  GRPC_MDSTR_REF((grpc_mdstr *)(is));
-}
-
-static void slice_unref(grpc_exec_ctx *exec_ctx, void *p) {
-  internal_string *is =
-      (internal_string *)((char *)p - offsetof(internal_string, refcount));
-  GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)(is));
-}
-
-grpc_mdstr *grpc_mdstr_from_string(const char *str) {
-  return grpc_mdstr_from_buffer((const uint8_t *)str, strlen(str));
-}
-
-grpc_mdstr *grpc_mdstr_from_slice(grpc_exec_ctx *exec_ctx, grpc_slice slice) {
-  grpc_mdstr *result = grpc_mdstr_from_buffer(GRPC_SLICE_START_PTR(slice),
-                                              GRPC_SLICE_LENGTH(slice));
-  grpc_slice_unref_internal(exec_ctx, slice);
-  return result;
-}
-
-grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
-  uint32_t hash = gpr_murmur_hash3(buf, length, g_hash_seed);
-  internal_string *s;
-  strtab_shard *shard =
-      &g_strtab_shard[SHARD_IDX(hash, LOG2_STRTAB_SHARD_COUNT)];
-  size_t i;
-  size_t idx;
-
-  GPR_TIMER_BEGIN("grpc_mdstr_from_buffer", 0);
-
-  /* search for a static string */
-  for (i = 0; i <= g_static_strtab_maxprobe; i++) {
-    grpc_mdstr *ss;
-    idx = (hash + i) % GPR_ARRAY_SIZE(g_static_strtab);
-    ss = g_static_strtab[idx];
-    if (ss == NULL) break;
-    if (ss->hash == hash && GRPC_SLICE_LENGTH(ss->slice) == length &&
-        (length == 0 ||
-         0 == memcmp(buf, GRPC_SLICE_START_PTR(ss->slice), length))) {
-      GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
-      return ss;
-    }
-  }
-
-  gpr_mu_lock(&shard->mu);
-
-  /* search for an existing string */
-  idx = TABLE_IDX(hash, LOG2_STRTAB_SHARD_COUNT, shard->capacity);
-  for (s = shard->strs[idx]; s; s = s->bucket_next) {
-    if (s->hash == hash && GRPC_SLICE_LENGTH(s->slice) == length &&
-        0 == memcmp(buf, GRPC_SLICE_START_PTR(s->slice), length)) {
-      if (gpr_atm_full_fetch_add(&s->refcnt, 1) == 0) {
-        /* If we get here, we've added a ref to something that was about to
-         * die - drop it immediately.
-         * The *only* possible path here (given the shard mutex) should be to
-         * drop from one ref back to zero - assert that with a CAS */
-        GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0));
-        /* and treat this as if we were never here... sshhh */
-      } else {
-        gpr_mu_unlock(&shard->mu);
-        GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
-        return (grpc_mdstr *)s;
-      }
-    }
-  }
-
-  /* not found: create a new string */
-  if (length + 1 < GRPC_SLICE_INLINED_SIZE) {
-    /* string data goes directly into the slice */
-    s = gpr_malloc(sizeof(internal_string));
-    gpr_atm_rel_store(&s->refcnt, 1);
-    s->slice.refcount = NULL;
-    memcpy(s->slice.data.inlined.bytes, buf, length);
-    s->slice.data.inlined.bytes[length] = 0;
-    s->slice.data.inlined.length = (uint8_t)length;
-  } else {
-    /* string data goes after the internal_string header, and we +1 for null
-       terminator */
-    s = gpr_malloc(sizeof(internal_string) + length + 1);
-    gpr_atm_rel_store(&s->refcnt, 1);
-    s->refcount.ref = slice_ref;
-    s->refcount.unref = slice_unref;
-    s->slice.refcount = &s->refcount;
-    s->slice.data.refcounted.bytes = (uint8_t *)(s + 1);
-    s->slice.data.refcounted.length = length;
-    memcpy(s->slice.data.refcounted.bytes, buf, length);
-    /* add a null terminator for cheap c string conversion when desired */
-    s->slice.data.refcounted.bytes[length] = 0;
-  }
-  s->has_base64_and_huffman_encoded = 0;
-  s->hash = hash;
-  s->size_in_decoder_table = SIZE_IN_DECODER_TABLE_NOT_SET;
-  s->bucket_next = shard->strs[idx];
-  shard->strs[idx] = s;
-
-  shard->count++;
-
-  if (shard->count > shard->capacity * 2) {
-    grow_strtab(shard);
-  }
-
-  gpr_mu_unlock(&shard->mu);
-  GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
-
-  return (grpc_mdstr *)s;
-}
-
 static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) {
   size_t i;
-  internal_metadata **prev_next;
-  internal_metadata *md, *next;
+  interned_metadata **prev_next;
+  interned_metadata *md, *next;
   gpr_atm num_freed = 0;
 
   GPR_TIMER_BEGIN("gc_mdtab", 0);
@@ -459,8 +187,8 @@
       void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data);
       next = md->bucket_next;
       if (gpr_atm_acq_load(&md->refcnt) == 0) {
-        GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)md->key);
-        GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)md->value);
+        grpc_slice_unref_internal(exec_ctx, md->key);
+        grpc_slice_unref_internal(exec_ctx, md->value);
         if (md->user_data) {
           ((destroy_user_data_func)gpr_atm_no_barrier_load(
               &md->destroy_user_data))(user_data);
@@ -481,21 +209,21 @@
 static void grow_mdtab(mdtab_shard *shard) {
   size_t capacity = shard->capacity * 2;
   size_t i;
-  internal_metadata **mdtab;
-  internal_metadata *md, *next;
+  interned_metadata **mdtab;
+  interned_metadata *md, *next;
   uint32_t hash;
 
   GPR_TIMER_BEGIN("grow_mdtab", 0);
 
-  mdtab = gpr_malloc(sizeof(internal_metadata *) * capacity);
-  memset(mdtab, 0, sizeof(internal_metadata *) * capacity);
+  mdtab = gpr_zalloc(sizeof(interned_metadata *) * capacity);
 
   for (i = 0; i < shard->capacity; i++) {
     for (md = shard->elems[i]; md; md = next) {
       size_t idx;
-      hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash);
+      hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key),
+                                grpc_slice_hash(md->value));
       next = md->bucket_next;
-      idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, capacity);
+      idx = TABLE_IDX(hash, capacity);
       md->bucket_next = mdtab[idx];
       mdtab[idx] = md;
     }
@@ -517,62 +245,77 @@
   }
 }
 
-grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
-                                               grpc_mdstr *mkey,
-                                               grpc_mdstr *mvalue) {
-  internal_string *key = (internal_string *)mkey;
-  internal_string *value = (internal_string *)mvalue;
-  uint32_t hash = GRPC_MDSTR_KV_HASH(mkey->hash, mvalue->hash);
-  internal_metadata *md;
-  mdtab_shard *shard = &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)];
-  size_t i;
+grpc_mdelem grpc_mdelem_create(
+    grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value,
+    grpc_mdelem_data *compatible_external_backing_store) {
+  if (!grpc_slice_is_interned(key) || !grpc_slice_is_interned(value)) {
+    if (compatible_external_backing_store != NULL) {
+      return GRPC_MAKE_MDELEM(compatible_external_backing_store,
+                              GRPC_MDELEM_STORAGE_EXTERNAL);
+    }
+
+    allocated_metadata *allocated = gpr_malloc(sizeof(*allocated));
+    allocated->key = grpc_slice_ref_internal(key);
+    allocated->value = grpc_slice_ref_internal(value);
+    gpr_atm_rel_store(&allocated->refcnt, 1);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+    char *key_str = grpc_slice_to_c_string(allocated->key);
+    char *value_str = grpc_slice_to_c_string(allocated->value);
+    gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%zu: '%s' = '%s'", (void *)allocated,
+            gpr_atm_no_barrier_load(&allocated->refcnt), key_str, value_str);
+    gpr_free(key_str);
+    gpr_free(value_str);
+#endif
+    return GRPC_MAKE_MDELEM(allocated, GRPC_MDELEM_STORAGE_ALLOCATED);
+  }
+
+  if (GRPC_IS_STATIC_METADATA_STRING(key) &&
+      GRPC_IS_STATIC_METADATA_STRING(value)) {
+    grpc_mdelem static_elem = grpc_static_mdelem_for_static_strings(
+        GRPC_STATIC_METADATA_INDEX(key), GRPC_STATIC_METADATA_INDEX(value));
+    if (!GRPC_MDISNULL(static_elem)) {
+      return static_elem;
+    }
+  }
+
+  uint32_t hash =
+      GRPC_MDSTR_KV_HASH(grpc_slice_hash(key), grpc_slice_hash(value));
+  interned_metadata *md;
+  mdtab_shard *shard = &g_shards[SHARD_IDX(hash)];
   size_t idx;
 
   GPR_TIMER_BEGIN("grpc_mdelem_from_metadata_strings", 0);
 
-  if (is_mdstr_static(mkey) && is_mdstr_static(mvalue)) {
-    for (i = 0; i <= g_static_mdtab_maxprobe; i++) {
-      grpc_mdelem *smd;
-      idx = (hash + i) % GPR_ARRAY_SIZE(g_static_mdtab);
-      smd = g_static_mdtab[idx];
-      if (smd == NULL) break;
-      if (smd->key == mkey && smd->value == mvalue) {
-        GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
-        return smd;
-      }
-    }
-  }
-
   gpr_mu_lock(&shard->mu);
 
-  idx = TABLE_IDX(hash, LOG2_MDTAB_SHARD_COUNT, shard->capacity);
+  idx = TABLE_IDX(hash, shard->capacity);
   /* search for an existing pair */
   for (md = shard->elems[idx]; md; md = md->bucket_next) {
-    if (md->key == key && md->value == value) {
+    if (grpc_slice_eq(key, md->key) && grpc_slice_eq(value, md->value)) {
       REF_MD_LOCKED(shard, md);
-      GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)key);
-      GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)value);
       gpr_mu_unlock(&shard->mu);
       GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
-      return (grpc_mdelem *)md;
+      return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED);
     }
   }
 
   /* not found: create a new pair */
-  md = gpr_malloc(sizeof(internal_metadata));
+  md = gpr_malloc(sizeof(interned_metadata));
   gpr_atm_rel_store(&md->refcnt, 1);
-  md->key = key;
-  md->value = value;
+  md->key = grpc_slice_ref_internal(key);
+  md->value = grpc_slice_ref_internal(value);
   md->user_data = 0;
   md->destroy_user_data = 0;
   md->bucket_next = shard->elems[idx];
   shard->elems[idx] = md;
   gpr_mu_init(&md->mu_user_data);
 #ifdef GRPC_METADATA_REFCOUNT_DEBUG
+  char *key_str = grpc_slice_to_c_string(md->key);
+  char *value_str = grpc_slice_to_c_string(md->value);
   gpr_log(GPR_DEBUG, "ELM   NEW:%p:%zu: '%s' = '%s'", (void *)md,
-          gpr_atm_no_barrier_load(&md->refcnt),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+          gpr_atm_no_barrier_load(&md->refcnt), key_str, value_str);
+  gpr_free(key_str);
+  gpr_free(value_str);
 #endif
   shard->count++;
 
@@ -584,29 +327,26 @@
 
   GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
 
-  return (grpc_mdelem *)md;
+  return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED);
 }
 
-grpc_mdelem *grpc_mdelem_from_strings(grpc_exec_ctx *exec_ctx, const char *key,
-                                      const char *value) {
-  return grpc_mdelem_from_metadata_strings(
-      exec_ctx, grpc_mdstr_from_string(key), grpc_mdstr_from_string(value));
+grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
+                                    grpc_slice value) {
+  grpc_mdelem out = grpc_mdelem_create(exec_ctx, key, value, NULL);
+  grpc_slice_unref_internal(exec_ctx, key);
+  grpc_slice_unref_internal(exec_ctx, value);
+  return out;
 }
 
-grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
-                                     grpc_slice value) {
-  return grpc_mdelem_from_metadata_strings(
-      exec_ctx, grpc_mdstr_from_slice(exec_ctx, key),
-      grpc_mdstr_from_slice(exec_ctx, value));
-}
-
-grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_exec_ctx *exec_ctx,
-                                                const char *key,
-                                                const uint8_t *value,
-                                                size_t value_length) {
-  return grpc_mdelem_from_metadata_strings(
-      exec_ctx, grpc_mdstr_from_string(key),
-      grpc_mdstr_from_buffer(value, value_length));
+grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx,
+                                           grpc_metadata *metadata) {
+  bool changed = false;
+  grpc_slice key_slice =
+      grpc_slice_maybe_static_intern(metadata->key, &changed);
+  grpc_slice value_slice =
+      grpc_slice_maybe_static_intern(metadata->value, &changed);
+  return grpc_mdelem_create(exec_ctx, key_slice, value_slice,
+                            changed ? NULL : (grpc_mdelem_data *)metadata);
 }
 
 static size_t get_base64_encoded_size(size_t raw_length) {
@@ -614,160 +354,176 @@
   return raw_length / 3 * 4 + tail_xtra[raw_length % 3];
 }
 
-size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem) {
-  size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(elem->key->slice);
-  size_t value_len = GRPC_SLICE_LENGTH(elem->value->slice);
-  if (is_mdstr_static(elem->value)) {
-    if (grpc_is_binary_header(
-            (const char *)GRPC_SLICE_START_PTR(elem->key->slice),
-            GRPC_SLICE_LENGTH(elem->key->slice))) {
-      return overhead_and_key + get_base64_encoded_size(value_len);
-    } else {
-      return overhead_and_key + value_len;
-    }
+size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem) {
+  size_t overhead_and_key = 32 + GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
+  size_t value_len = GRPC_SLICE_LENGTH(GRPC_MDVALUE(elem));
+  if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
+    return overhead_and_key + get_base64_encoded_size(value_len);
   } else {
-    internal_string *is = (internal_string *)elem->value;
-    gpr_atm current_size = gpr_atm_acq_load(&is->size_in_decoder_table);
-    if (current_size == SIZE_IN_DECODER_TABLE_NOT_SET) {
-      if (grpc_is_binary_header(
-              (const char *)GRPC_SLICE_START_PTR(elem->key->slice),
-              GRPC_SLICE_LENGTH(elem->key->slice))) {
-        current_size = (gpr_atm)get_base64_encoded_size(value_len);
-      } else {
-        current_size = (gpr_atm)value_len;
-      }
-      gpr_atm_rel_store(&is->size_in_decoder_table, current_size);
-    }
-    return overhead_and_key + (size_t)current_size;
+    return overhead_and_key + value_len;
   }
 }
 
-grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) {
-  internal_metadata *md = (internal_metadata *)gmd;
-  if (is_mdelem_static(gmd)) return gmd;
+grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd DEBUG_ARGS) {
+  switch (GRPC_MDELEM_STORAGE(gmd)) {
+    case GRPC_MDELEM_STORAGE_EXTERNAL:
+    case GRPC_MDELEM_STORAGE_STATIC:
+      break;
+    case GRPC_MDELEM_STORAGE_INTERNED: {
+      interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd);
 #ifdef GRPC_METADATA_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "ELM   REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
-          gpr_atm_no_barrier_load(&md->refcnt),
-          gpr_atm_no_barrier_load(&md->refcnt) + 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+      char *key_str = grpc_slice_to_c_string(md->key);
+      char *value_str = grpc_slice_to_c_string(md->value);
+      gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+              "ELM   REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
+              gpr_atm_no_barrier_load(&md->refcnt),
+              gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
+      gpr_free(key_str);
+      gpr_free(value_str);
 #endif
-  /* we can assume the ref count is >= 1 as the application is calling
-     this function - meaning that no adjustment to mdtab_free is necessary,
-     simplifying the logic here to be just an atomic increment */
-  /* use C assert to have this removed in opt builds */
-  GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
-  gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
+      /* we can assume the ref count is >= 1 as the application is calling
+         this function - meaning that no adjustment to mdtab_free is necessary,
+         simplifying the logic here to be just an atomic increment */
+      /* use C assert to have this removed in opt builds */
+      GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
+      gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
+      break;
+    }
+    case GRPC_MDELEM_STORAGE_ALLOCATED: {
+      allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+      char *key_str = grpc_slice_to_c_string(md->key);
+      char *value_str = grpc_slice_to_c_string(md->value);
+      gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+              "ELM   REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
+              gpr_atm_no_barrier_load(&md->refcnt),
+              gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
+      gpr_free(key_str);
+      gpr_free(value_str);
+#endif
+      /* we can assume the ref count is >= 1 as the application is calling
+         this function - meaning that no adjustment to mdtab_free is necessary,
+         simplifying the logic here to be just an atomic increment */
+      /* use C assert to have this removed in opt builds */
+      gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
+      break;
+    }
+  }
   return gmd;
 }
 
-void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *gmd DEBUG_ARGS) {
-  internal_metadata *md = (internal_metadata *)gmd;
-  if (!md) return;
-  if (is_mdelem_static(gmd)) return;
+void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem gmd DEBUG_ARGS) {
+  switch (GRPC_MDELEM_STORAGE(gmd)) {
+    case GRPC_MDELEM_STORAGE_EXTERNAL:
+    case GRPC_MDELEM_STORAGE_STATIC:
+      break;
+    case GRPC_MDELEM_STORAGE_INTERNED: {
+      interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd);
 #ifdef GRPC_METADATA_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
-          "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
-          gpr_atm_no_barrier_load(&md->refcnt),
-          gpr_atm_no_barrier_load(&md->refcnt) - 1,
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
-          grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
+      char *key_str = grpc_slice_to_c_string(md->key);
+      char *value_str = grpc_slice_to_c_string(md->value);
+      gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+              "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
+              gpr_atm_no_barrier_load(&md->refcnt),
+              gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str);
+      gpr_free(key_str);
+      gpr_free(value_str);
 #endif
-  uint32_t hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash);
-  const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
-  GPR_ASSERT(prev_refcount >= 1);
-  if (1 == prev_refcount) {
-    /* once the refcount hits zero, some other thread can come along and
-       free md at any time: it's unsafe from this point on to access it */
-    mdtab_shard *shard =
-        &g_mdtab_shard[SHARD_IDX(hash, LOG2_MDTAB_SHARD_COUNT)];
-    gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1);
-  }
-}
-
-const char *grpc_mdstr_as_c_string(const grpc_mdstr *s) {
-  return (const char *)GRPC_SLICE_START_PTR(s->slice);
-}
-
-size_t grpc_mdstr_length(const grpc_mdstr *s) { return GRPC_MDSTR_LENGTH(s); }
-
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
-  internal_string *s = (internal_string *)gs;
-  if (is_mdstr_static(gs)) return gs;
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR   REF:%p:%zu->%zu: '%s'",
-          (void *)s, gpr_atm_no_barrier_load(&s->refcnt),
-          gpr_atm_no_barrier_load(&s->refcnt) + 1, grpc_mdstr_as_c_string(gs));
-#endif
-  GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) > 0);
-  return gs;
-}
-
-void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *gs DEBUG_ARGS) {
-  internal_string *s = (internal_string *)gs;
-  if (is_mdstr_static(gs)) return;
-#ifdef GRPC_METADATA_REFCOUNT_DEBUG
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR UNREF:%p:%zu->%zu: '%s'",
-          (void *)s, gpr_atm_no_barrier_load(&s->refcnt),
-          gpr_atm_no_barrier_load(&s->refcnt) - 1, grpc_mdstr_as_c_string(gs));
-#endif
-  if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) {
-    strtab_shard *shard =
-        &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
-    gpr_mu_lock(&shard->mu);
-    GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt));
-    internal_destroy_string(exec_ctx, shard, s);
-    gpr_mu_unlock(&shard->mu);
-  }
-}
-
-void *grpc_mdelem_get_user_data(grpc_mdelem *md, void (*destroy_func)(void *)) {
-  internal_metadata *im = (internal_metadata *)md;
-  void *result;
-  if (is_mdelem_static(md)) {
-    return (void *)grpc_static_mdelem_user_data[md - grpc_static_mdelem_table];
-  }
-  if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) {
-    return (void *)gpr_atm_no_barrier_load(&im->user_data);
-  } else {
-    return NULL;
-  }
-  return result;
-}
-
-void *grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
-                                void *user_data) {
-  internal_metadata *im = (internal_metadata *)md;
-  GPR_ASSERT(!is_mdelem_static(md));
-  GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
-  gpr_mu_lock(&im->mu_user_data);
-  if (gpr_atm_no_barrier_load(&im->destroy_user_data)) {
-    /* user data can only be set once */
-    gpr_mu_unlock(&im->mu_user_data);
-    if (destroy_func != NULL) {
-      destroy_func(user_data);
+      uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key),
+                                         grpc_slice_hash(md->value));
+      const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
+      GPR_ASSERT(prev_refcount >= 1);
+      if (1 == prev_refcount) {
+        /* once the refcount hits zero, some other thread can come along and
+           free md at any time: it's unsafe from this point on to access it */
+        mdtab_shard *shard = &g_shards[SHARD_IDX(hash)];
+        gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1);
+      }
+      break;
     }
-    return (void *)gpr_atm_no_barrier_load(&im->user_data);
+    case GRPC_MDELEM_STORAGE_ALLOCATED: {
+      allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+      char *key_str = grpc_slice_to_c_string(md->key);
+      char *value_str = grpc_slice_to_c_string(md->value);
+      gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+              "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
+              gpr_atm_no_barrier_load(&md->refcnt),
+              gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str);
+      gpr_free(key_str);
+      gpr_free(value_str);
+#endif
+      const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
+      GPR_ASSERT(prev_refcount >= 1);
+      if (1 == prev_refcount) {
+        grpc_slice_unref_internal(exec_ctx, md->key);
+        grpc_slice_unref_internal(exec_ctx, md->value);
+        gpr_free(md);
+      }
+      break;
+    }
   }
-  gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data);
-  gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func);
-  gpr_mu_unlock(&im->mu_user_data);
-  return user_data;
 }
 
-grpc_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) {
-  internal_string *s = (internal_string *)gs;
-  grpc_slice slice;
-  strtab_shard *shard =
-      &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
-  gpr_mu_lock(&shard->mu);
-  if (!s->has_base64_and_huffman_encoded) {
-    s->base64_and_huffman =
-        grpc_chttp2_base64_encode_and_huffman_compress(s->slice);
-    s->has_base64_and_huffman_encoded = 1;
+void *grpc_mdelem_get_user_data(grpc_mdelem md, void (*destroy_func)(void *)) {
+  switch (GRPC_MDELEM_STORAGE(md)) {
+    case GRPC_MDELEM_STORAGE_EXTERNAL:
+    case GRPC_MDELEM_STORAGE_ALLOCATED:
+      return NULL;
+    case GRPC_MDELEM_STORAGE_STATIC:
+      return (void *)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) -
+                                                  grpc_static_mdelem_table];
+    case GRPC_MDELEM_STORAGE_INTERNED: {
+      interned_metadata *im = (interned_metadata *)GRPC_MDELEM_DATA(md);
+      void *result;
+      if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) {
+        return (void *)gpr_atm_no_barrier_load(&im->user_data);
+      } else {
+        return NULL;
+      }
+      return result;
+    }
   }
-  slice = s->base64_and_huffman;
-  gpr_mu_unlock(&shard->mu);
-  return slice;
+  GPR_UNREACHABLE_CODE(return NULL);
+}
+
+void *grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void *),
+                                void *user_data) {
+  switch (GRPC_MDELEM_STORAGE(md)) {
+    case GRPC_MDELEM_STORAGE_EXTERNAL:
+    case GRPC_MDELEM_STORAGE_ALLOCATED:
+      destroy_func(user_data);
+      return NULL;
+    case GRPC_MDELEM_STORAGE_STATIC:
+      destroy_func(user_data);
+      return (void *)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) -
+                                                  grpc_static_mdelem_table];
+    case GRPC_MDELEM_STORAGE_INTERNED: {
+      interned_metadata *im = (interned_metadata *)GRPC_MDELEM_DATA(md);
+      GPR_ASSERT(!is_mdelem_static(md));
+      GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
+      gpr_mu_lock(&im->mu_user_data);
+      if (gpr_atm_no_barrier_load(&im->destroy_user_data)) {
+        /* user data can only be set once */
+        gpr_mu_unlock(&im->mu_user_data);
+        if (destroy_func != NULL) {
+          destroy_func(user_data);
+        }
+        return (void *)gpr_atm_no_barrier_load(&im->user_data);
+      }
+      gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data);
+      gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func);
+      gpr_mu_unlock(&im->mu_user_data);
+      return user_data;
+    }
+  }
+  GPR_UNREACHABLE_CODE(return NULL);
+}
+
+bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b) {
+  if (a.payload == b.payload) return true;
+  if (GRPC_MDELEM_IS_INTERNED(a) && GRPC_MDELEM_IS_INTERNED(b)) return false;
+  if (GRPC_MDISNULL(a) || GRPC_MDISNULL(b)) return false;
+  return grpc_slice_eq(GRPC_MDKEY(a), GRPC_MDKEY(b)) &&
+         grpc_slice_eq(GRPC_MDVALUE(a), GRPC_MDVALUE(b));
 }
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index 991eee9..f4ba86c 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -34,6 +34,7 @@
 #ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_H
 #define GRPC_CORE_LIB_TRANSPORT_METADATA_H
 
+#include <grpc/grpc.h>
 #include <grpc/slice.h>
 #include <grpc/support/useful.h>
 
@@ -74,110 +75,110 @@
    declared here - in which case those functions are effectively no-ops. */
 
 /* Forward declarations */
-typedef struct grpc_mdstr grpc_mdstr;
 typedef struct grpc_mdelem grpc_mdelem;
 
-/* if changing this, make identical changes in internal_string in metadata.c */
-struct grpc_mdstr {
-  const grpc_slice slice;
-  const uint32_t hash;
+/* if changing this, make identical changes in:
+   - interned_metadata, allocated_metadata in metadata.c
+   - grpc_metadata in grpc_types.h */
+typedef struct grpc_mdelem_data {
+  const grpc_slice key;
+  const grpc_slice value;
   /* there is a private part to this in metadata.c */
-};
+} grpc_mdelem_data;
 
-/* if changing this, make identical changes in internal_metadata in
-   metadata.c */
+/* GRPC_MDELEM_STORAGE_* enum values that can be treated as interned always have
+   this bit set in their integer value */
+#define GRPC_MDELEM_STORAGE_INTERNED_BIT 1
+
+typedef enum {
+  /* memory pointed to by grpc_mdelem::payload is owned by an external system */
+  GRPC_MDELEM_STORAGE_EXTERNAL = 0,
+  /* memory pointed to by grpc_mdelem::payload is interned by the metadata
+     system */
+  GRPC_MDELEM_STORAGE_INTERNED = GRPC_MDELEM_STORAGE_INTERNED_BIT,
+  /* memory pointed to by grpc_mdelem::payload is allocated by the metadata
+     system */
+  GRPC_MDELEM_STORAGE_ALLOCATED = 2,
+  /* memory is in the static metadata table */
+  GRPC_MDELEM_STORAGE_STATIC = 2 | GRPC_MDELEM_STORAGE_INTERNED_BIT,
+} grpc_mdelem_data_storage;
+
 struct grpc_mdelem {
-  grpc_mdstr *const key;
-  grpc_mdstr *const value;
-  /* there is a private part to this in metadata.c */
+  /* a grpc_mdelem_data* generally, with the two lower bits signalling memory
+     ownership as per grpc_mdelem_data_storage */
+  uintptr_t payload;
 };
 
-void grpc_test_only_set_metadata_hash_seed(uint32_t seed);
+#define GRPC_MDELEM_DATA(md) \
+  ((grpc_mdelem_data *)((md).payload & ~(uintptr_t)3))
+#define GRPC_MDELEM_STORAGE(md) \
+  ((grpc_mdelem_data_storage)((md).payload & (uintptr_t)3))
+#define GRPC_MAKE_MDELEM(data, storage) \
+  ((grpc_mdelem){((uintptr_t)(data)) | ((uintptr_t)storage)})
+#define GRPC_MDELEM_IS_INTERNED(md)          \
+  ((grpc_mdelem_data_storage)((md).payload & \
+                              (uintptr_t)GRPC_MDELEM_STORAGE_INTERNED_BIT))
 
-/* Constructors for grpc_mdstr instances; take a variety of data types that
-   clients may have handy */
-grpc_mdstr *grpc_mdstr_from_string(const char *str);
-/* Unrefs the slice. */
-grpc_mdstr *grpc_mdstr_from_slice(grpc_exec_ctx *exec_ctx, grpc_slice slice);
-grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *str, size_t length);
-
-/* Returns a borrowed slice from the mdstr with its contents base64 encoded
-   and huffman compressed */
-grpc_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *str);
-
-/* Constructors for grpc_mdelem instances; take a variety of data types that
-   clients may have handy */
-grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
-                                               grpc_mdstr *key,
-                                               grpc_mdstr *value);
-grpc_mdelem *grpc_mdelem_from_strings(grpc_exec_ctx *exec_ctx, const char *key,
-                                      const char *value);
 /* Unrefs the slices. */
-grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
-                                     grpc_slice value);
-grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_exec_ctx *exec_ctx,
-                                                const char *key,
-                                                const uint8_t *value,
-                                                size_t value_length);
+grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
+                                    grpc_slice value);
 
-size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem);
+/* Cheaply convert a grpc_metadata to a grpc_mdelem; may use the grpc_metadata
+   object as backing storage (so lifetimes should align) */
+grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx,
+                                           grpc_metadata *metadata);
+
+/* Does not unref the slices; if a new non-interned mdelem is needed, allocates
+   one if compatible_external_backing_store is NULL, or uses
+   compatible_external_backing_store if it is non-NULL (in which case it's the
+   users responsibility to ensure that it outlives usage) */
+grpc_mdelem grpc_mdelem_create(
+    grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value,
+    grpc_mdelem_data *compatible_external_backing_store);
+
+bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b);
+
+size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem);
 
 /* Mutator and accessor for grpc_mdelem user data. The destructor function
    is used as a type tag and is checked during user_data fetch. */
-void *grpc_mdelem_get_user_data(grpc_mdelem *md,
+void *grpc_mdelem_get_user_data(grpc_mdelem md,
                                 void (*if_destroy_func)(void *));
-void *grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
+void *grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void *),
                                 void *user_data);
 
 /* Reference counting */
 //#define GRPC_METADATA_REFCOUNT_DEBUG
 #ifdef GRPC_METADATA_REFCOUNT_DEBUG
-#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__)
-#define GRPC_MDSTR_UNREF(exec_ctx, s) \
-  grpc_mdstr_unref((exec_ctx), (s), __FILE__, __LINE__)
 #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__)
 #define GRPC_MDELEM_UNREF(exec_ctx, s) \
   grpc_mdelem_unref((exec_ctx), (s), __FILE__, __LINE__)
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s, const char *file, int line);
-void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *s, const char *file,
-                      int line);
-grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md, const char *file, int line);
-void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md,
+grpc_mdelem grpc_mdelem_ref(grpc_mdelem md, const char *file, int line);
+void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md,
                        const char *file, int line);
 #else
-#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s))
-#define GRPC_MDSTR_UNREF(exec_ctx, s) grpc_mdstr_unref((exec_ctx), (s))
 #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s))
 #define GRPC_MDELEM_UNREF(exec_ctx, s) grpc_mdelem_unref((exec_ctx), (s))
-grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s);
-void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *s);
-grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md);
-void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md);
+grpc_mdelem grpc_mdelem_ref(grpc_mdelem md);
+void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md);
 #endif
 
-/* Recover a char* from a grpc_mdstr. The returned string is null terminated.
-   Does not promise that the returned string has no embedded nulls however. */
-const char *grpc_mdstr_as_c_string(const grpc_mdstr *s);
+#define GRPC_MDKEY(md) (GRPC_MDELEM_DATA(md)->key)
+#define GRPC_MDVALUE(md) (GRPC_MDELEM_DATA(md)->value)
 
-#define GRPC_MDSTR_LENGTH(s) (GRPC_SLICE_LENGTH(s->slice))
+#define GRPC_MDNULL GRPC_MAKE_MDELEM(NULL, GRPC_MDELEM_STORAGE_EXTERNAL)
+#define GRPC_MDISNULL(md) (GRPC_MDELEM_DATA(md) == NULL)
 
 /* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */
-#define GRPC_MDELEM_LENGTH(e) \
-  (GRPC_MDSTR_LENGTH((e)->key) + GRPC_MDSTR_LENGTH((e)->value) + 32)
-
-int grpc_mdstr_is_legal_header(grpc_mdstr *s);
-int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s);
-int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s);
+#define GRPC_MDELEM_LENGTH(e)                                                  \
+  (GRPC_SLICE_LENGTH(GRPC_MDKEY((e))) + GRPC_SLICE_LENGTH(GRPC_MDVALUE((e))) + \
+   32)
 
 #define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash))
 
 void grpc_mdctx_global_init(void);
 void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx);
 
-/* Implementation provided by chttp2_transport */
-extern grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(
-    grpc_slice input);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c
index b62ecc3..fc2c52b 100644
--- a/src/core/lib/transport/metadata_batch.c
+++ b/src/core/lib/transport/metadata_batch.c
@@ -40,6 +40,8 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 
 static void assert_valid_list(grpc_mdelem_list *list) {
 #ifndef NDEBUG
@@ -51,16 +53,34 @@
   GPR_ASSERT(list->tail->next == NULL);
   GPR_ASSERT((list->head == list->tail) == (list->head->next == NULL));
 
+  size_t verified_count = 0;
   for (l = list->head; l; l = l->next) {
-    GPR_ASSERT(l->md);
+    GPR_ASSERT(!GRPC_MDISNULL(l->md));
     GPR_ASSERT((l->prev == NULL) == (l == list->head));
     GPR_ASSERT((l->next == NULL) == (l == list->tail));
     if (l->next) GPR_ASSERT(l->next->prev == l);
     if (l->prev) GPR_ASSERT(l->prev->next == l);
+    verified_count++;
   }
+  GPR_ASSERT(list->count == verified_count);
 #endif /* NDEBUG */
 }
 
+static void assert_valid_callouts(grpc_exec_ctx *exec_ctx,
+                                  grpc_metadata_batch *batch) {
+#ifndef NDEBUG
+  for (grpc_linked_mdelem *l = batch->list.head; l != NULL; l = l->next) {
+    grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md));
+    grpc_metadata_batch_callouts_index callout_idx =
+        GRPC_BATCH_INDEX_OF(key_interned);
+    if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) {
+      GPR_ASSERT(batch->idx.array[callout_idx] == l);
+    }
+    grpc_slice_unref_internal(exec_ctx, key_interned);
+  }
+#endif
+}
+
 #ifndef NDEBUG
 void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) {
   assert_valid_list(&batch->list);
@@ -68,7 +88,7 @@
 #endif /* NDEBUG */
 
 void grpc_metadata_batch_init(grpc_metadata_batch *batch) {
-  batch->list.head = batch->list.tail = NULL;
+  memset(batch, 0, sizeof(*batch));
   batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
 }
 
@@ -80,17 +100,58 @@
   }
 }
 
-void grpc_metadata_batch_add_head(grpc_metadata_batch *batch,
-                                  grpc_linked_mdelem *storage,
-                                  grpc_mdelem *elem_to_add) {
-  GPR_ASSERT(elem_to_add);
+grpc_error *grpc_attach_md_to_error(grpc_error *src, grpc_mdelem md) {
+  char *k = grpc_slice_to_c_string(GRPC_MDKEY(md));
+  char *v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+  grpc_error *out = grpc_error_set_str(
+      grpc_error_set_str(src, GRPC_ERROR_STR_KEY, k), GRPC_ERROR_STR_VALUE, v);
+  gpr_free(k);
+  gpr_free(v);
+  return out;
+}
+
+static grpc_error *maybe_link_callout(grpc_metadata_batch *batch,
+                                      grpc_linked_mdelem *storage)
+    GRPC_MUST_USE_RESULT;
+
+static grpc_error *maybe_link_callout(grpc_metadata_batch *batch,
+                                      grpc_linked_mdelem *storage) {
+  grpc_metadata_batch_callouts_index idx =
+      GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md));
+  if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
+    return GRPC_ERROR_NONE;
+  }
+  if (batch->idx.array[idx] == NULL) {
+    batch->idx.array[idx] = storage;
+    return GRPC_ERROR_NONE;
+  }
+  return grpc_attach_md_to_error(
+      GRPC_ERROR_CREATE("Unallowed duplicate metadata"), storage->md);
+}
+
+static void maybe_unlink_callout(grpc_metadata_batch *batch,
+                                 grpc_linked_mdelem *storage) {
+  grpc_metadata_batch_callouts_index idx =
+      GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md));
+  if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
+    return;
+  }
+  GPR_ASSERT(batch->idx.array[idx] != NULL);
+  batch->idx.array[idx] = NULL;
+}
+
+grpc_error *grpc_metadata_batch_add_head(grpc_exec_ctx *exec_ctx,
+                                         grpc_metadata_batch *batch,
+                                         grpc_linked_mdelem *storage,
+                                         grpc_mdelem elem_to_add) {
+  GPR_ASSERT(!GRPC_MDISNULL(elem_to_add));
   storage->md = elem_to_add;
-  grpc_metadata_batch_link_head(batch, storage);
+  return grpc_metadata_batch_link_head(exec_ctx, batch, storage);
 }
 
 static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) {
   assert_valid_list(list);
-  GPR_ASSERT(storage->md);
+  GPR_ASSERT(!GRPC_MDISNULL(storage->md));
   storage->prev = NULL;
   storage->next = list->head;
   if (list->head != NULL) {
@@ -99,25 +160,36 @@
     list->tail = storage;
   }
   list->head = storage;
+  list->count++;
   assert_valid_list(list);
 }
 
-void grpc_metadata_batch_link_head(grpc_metadata_batch *batch,
-                                   grpc_linked_mdelem *storage) {
+grpc_error *grpc_metadata_batch_link_head(grpc_exec_ctx *exec_ctx,
+                                          grpc_metadata_batch *batch,
+                                          grpc_linked_mdelem *storage) {
+  assert_valid_callouts(exec_ctx, batch);
+  grpc_error *err = maybe_link_callout(batch, storage);
+  if (err != GRPC_ERROR_NONE) {
+    assert_valid_callouts(exec_ctx, batch);
+    return err;
+  }
   link_head(&batch->list, storage);
+  assert_valid_callouts(exec_ctx, batch);
+  return GRPC_ERROR_NONE;
 }
 
-void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch,
-                                  grpc_linked_mdelem *storage,
-                                  grpc_mdelem *elem_to_add) {
-  GPR_ASSERT(elem_to_add);
+grpc_error *grpc_metadata_batch_add_tail(grpc_exec_ctx *exec_ctx,
+                                         grpc_metadata_batch *batch,
+                                         grpc_linked_mdelem *storage,
+                                         grpc_mdelem elem_to_add) {
+  GPR_ASSERT(!GRPC_MDISNULL(elem_to_add));
   storage->md = elem_to_add;
-  grpc_metadata_batch_link_tail(batch, storage);
+  return grpc_metadata_batch_link_tail(exec_ctx, batch, storage);
 }
 
 static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) {
   assert_valid_list(list);
-  GPR_ASSERT(storage->md);
+  GPR_ASSERT(!GRPC_MDISNULL(storage->md));
   storage->prev = list->tail;
   storage->next = NULL;
   storage->reserved = NULL;
@@ -127,70 +199,88 @@
     list->head = storage;
   }
   list->tail = storage;
+  list->count++;
   assert_valid_list(list);
 }
 
-void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch,
-                                   grpc_linked_mdelem *storage) {
-  link_tail(&batch->list, storage);
-}
-
-void grpc_metadata_batch_move(grpc_metadata_batch *dst,
-                              grpc_metadata_batch *src) {
-  *dst = *src;
-  memset(src, 0, sizeof(grpc_metadata_batch));
-}
-
-void grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx,
-                                grpc_metadata_batch *batch,
-                                grpc_mdelem *(*filter)(grpc_exec_ctx *exec_ctx,
-                                                       void *user_data,
-                                                       grpc_mdelem *elem),
-                                void *user_data) {
-  grpc_linked_mdelem *l;
-  grpc_linked_mdelem *next;
-
-  GPR_TIMER_BEGIN("grpc_metadata_batch_filter", 0);
-
-  assert_valid_list(&batch->list);
-  for (l = batch->list.head; l; l = next) {
-    grpc_mdelem *orig = l->md;
-    grpc_mdelem *filt = filter(exec_ctx, user_data, orig);
-    next = l->next;
-    if (filt == NULL) {
-      if (l->prev) {
-        l->prev->next = l->next;
-      }
-      if (l->next) {
-        l->next->prev = l->prev;
-      }
-      if (batch->list.head == l) {
-        batch->list.head = l->next;
-      }
-      if (batch->list.tail == l) {
-        batch->list.tail = l->prev;
-      }
-      assert_valid_list(&batch->list);
-      GRPC_MDELEM_UNREF(exec_ctx, l->md);
-    } else if (filt != orig) {
-      GRPC_MDELEM_UNREF(exec_ctx, orig);
-      l->md = filt;
-    }
+grpc_error *grpc_metadata_batch_link_tail(grpc_exec_ctx *exec_ctx,
+                                          grpc_metadata_batch *batch,
+                                          grpc_linked_mdelem *storage) {
+  assert_valid_callouts(exec_ctx, batch);
+  grpc_error *err = maybe_link_callout(batch, storage);
+  if (err != GRPC_ERROR_NONE) {
+    assert_valid_callouts(exec_ctx, batch);
+    return err;
   }
-  assert_valid_list(&batch->list);
-
-  GPR_TIMER_END("grpc_metadata_batch_filter", 0);
+  link_tail(&batch->list, storage);
+  assert_valid_callouts(exec_ctx, batch);
+  return GRPC_ERROR_NONE;
 }
 
-static grpc_mdelem *no_metadata_for_you(grpc_exec_ctx *exec_ctx,
-                                        void *user_data, grpc_mdelem *elem) {
-  return NULL;
+static void unlink_storage(grpc_mdelem_list *list,
+                           grpc_linked_mdelem *storage) {
+  assert_valid_list(list);
+  if (storage->prev != NULL) {
+    storage->prev->next = storage->next;
+  } else {
+    list->head = storage->next;
+  }
+  if (storage->next != NULL) {
+    storage->next->prev = storage->prev;
+  } else {
+    list->tail = storage->prev;
+  }
+  list->count--;
+  assert_valid_list(list);
+}
+
+void grpc_metadata_batch_remove(grpc_exec_ctx *exec_ctx,
+                                grpc_metadata_batch *batch,
+                                grpc_linked_mdelem *storage) {
+  assert_valid_callouts(exec_ctx, batch);
+  maybe_unlink_callout(batch, storage);
+  unlink_storage(&batch->list, storage);
+  GRPC_MDELEM_UNREF(exec_ctx, storage->md);
+  assert_valid_callouts(exec_ctx, batch);
+}
+
+void grpc_metadata_batch_set_value(grpc_exec_ctx *exec_ctx,
+                                   grpc_linked_mdelem *storage,
+                                   grpc_slice value) {
+  grpc_mdelem old = storage->md;
+  grpc_mdelem new = grpc_mdelem_from_slices(
+      exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(old)), value);
+  storage->md = new;
+  GRPC_MDELEM_UNREF(exec_ctx, old);
+}
+
+grpc_error *grpc_metadata_batch_substitute(grpc_exec_ctx *exec_ctx,
+                                           grpc_metadata_batch *batch,
+                                           grpc_linked_mdelem *storage,
+                                           grpc_mdelem new) {
+  assert_valid_callouts(exec_ctx, batch);
+  grpc_error *error = GRPC_ERROR_NONE;
+  grpc_mdelem old = storage->md;
+  if (!grpc_slice_eq(GRPC_MDKEY(new), GRPC_MDKEY(old))) {
+    maybe_unlink_callout(batch, storage);
+    storage->md = new;
+    error = maybe_link_callout(batch, storage);
+    if (error != GRPC_ERROR_NONE) {
+      unlink_storage(&batch->list, storage);
+      GRPC_MDELEM_UNREF(exec_ctx, storage->md);
+    }
+  } else {
+    storage->md = new;
+  }
+  GRPC_MDELEM_UNREF(exec_ctx, old);
+  assert_valid_callouts(exec_ctx, batch);
+  return error;
 }
 
 void grpc_metadata_batch_clear(grpc_exec_ctx *exec_ctx,
                                grpc_metadata_batch *batch) {
-  batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
-  grpc_metadata_batch_filter(exec_ctx, batch, no_metadata_for_you, NULL);
+  grpc_metadata_batch_destroy(exec_ctx, batch);
+  grpc_metadata_batch_init(batch);
 }
 
 bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) {
@@ -207,3 +297,33 @@
   }
   return size;
 }
+
+static void add_error(grpc_error **composite, grpc_error *error,
+                      const char *composite_error_string) {
+  if (error == GRPC_ERROR_NONE) return;
+  if (*composite == GRPC_ERROR_NONE) {
+    *composite = GRPC_ERROR_CREATE(composite_error_string);
+  }
+  *composite = grpc_error_add_child(*composite, error);
+}
+
+grpc_error *grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx,
+                                       grpc_metadata_batch *batch,
+                                       grpc_metadata_batch_filter_func func,
+                                       void *user_data,
+                                       const char *composite_error_string) {
+  grpc_linked_mdelem *l = batch->list.head;
+  grpc_error *error = GRPC_ERROR_NONE;
+  while (l) {
+    grpc_linked_mdelem *next = l->next;
+    grpc_filtered_mdelem new = func(exec_ctx, user_data, l->md);
+    add_error(&error, new.error, composite_error_string);
+    if (GRPC_MDISNULL(new.md)) {
+      grpc_metadata_batch_remove(exec_ctx, batch, l);
+    } else if (new.md.payload != l->md.payload) {
+      grpc_metadata_batch_substitute(exec_ctx, batch, l, new.md);
+    }
+    l = next;
+  }
+  return error;
+}
diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h
index c0bd517..5471539 100644
--- a/src/core/lib/transport/metadata_batch.h
+++ b/src/core/lib/transport/metadata_batch.h
@@ -41,19 +41,21 @@
 #include <grpc/support/port_platform.h>
 #include <grpc/support/time.h>
 #include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/static_metadata.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 typedef struct grpc_linked_mdelem {
-  grpc_mdelem *md;
+  grpc_mdelem md;
   struct grpc_linked_mdelem *next;
   struct grpc_linked_mdelem *prev;
   void *reserved;
 } grpc_linked_mdelem;
 
 typedef struct grpc_mdelem_list {
+  size_t count;
   grpc_linked_mdelem *head;
   grpc_linked_mdelem *tail;
 } grpc_mdelem_list;
@@ -61,6 +63,7 @@
 typedef struct grpc_metadata_batch {
   /** Metadata elements in this batch */
   grpc_mdelem_list list;
+  grpc_metadata_batch_callouts idx;
   /** Used to calculate grpc-timeout at the point of sending,
       or gpr_inf_future if this batch does not need to send a
       grpc-timeout */
@@ -77,25 +80,37 @@
 /* Returns the transport size of the batch. */
 size_t grpc_metadata_batch_size(grpc_metadata_batch *batch);
 
-/** Moves the metadata information from \a src to \a dst. Upon return, \a src is
- * zeroed. */
-void grpc_metadata_batch_move(grpc_metadata_batch *dst,
-                              grpc_metadata_batch *src);
+/** Remove \a storage from the batch, unreffing the mdelem contained */
+void grpc_metadata_batch_remove(grpc_exec_ctx *exec_ctx,
+                                grpc_metadata_batch *batch,
+                                grpc_linked_mdelem *storage);
+
+/** Substitute a new mdelem for an old value */
+grpc_error *grpc_metadata_batch_substitute(grpc_exec_ctx *exec_ctx,
+                                           grpc_metadata_batch *batch,
+                                           grpc_linked_mdelem *storage,
+                                           grpc_mdelem new_value);
+
+void grpc_metadata_batch_set_value(grpc_exec_ctx *exec_ctx,
+                                   grpc_linked_mdelem *storage,
+                                   grpc_slice value);
 
 /** Add \a storage to the beginning of \a batch. storage->md is
     assumed to be valid.
     \a storage is owned by the caller and must survive for the
     lifetime of batch. This usually means it should be around
     for the lifetime of the call. */
-void grpc_metadata_batch_link_head(grpc_metadata_batch *batch,
-                                   grpc_linked_mdelem *storage);
+grpc_error *grpc_metadata_batch_link_head(
+    grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch,
+    grpc_linked_mdelem *storage) GRPC_MUST_USE_RESULT;
 /** Add \a storage to the end of \a batch. storage->md is
     assumed to be valid.
     \a storage is owned by the caller and must survive for the
     lifetime of batch. This usually means it should be around
     for the lifetime of the call. */
-void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch,
-                                   grpc_linked_mdelem *storage);
+grpc_error *grpc_metadata_batch_link_tail(
+    grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch,
+    grpc_linked_mdelem *storage) GRPC_MUST_USE_RESULT;
 
 /** Add \a elem_to_add as the first element in \a batch, using
     \a storage as backing storage for the linked list element.
@@ -103,29 +118,38 @@
     lifetime of batch. This usually means it should be around
     for the lifetime of the call.
     Takes ownership of \a elem_to_add */
-void grpc_metadata_batch_add_head(grpc_metadata_batch *batch,
-                                  grpc_linked_mdelem *storage,
-                                  grpc_mdelem *elem_to_add);
+grpc_error *grpc_metadata_batch_add_head(
+    grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch,
+    grpc_linked_mdelem *storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
 /** Add \a elem_to_add as the last element in \a batch, using
     \a storage as backing storage for the linked list element.
     \a storage is owned by the caller and must survive for the
     lifetime of batch. This usually means it should be around
     for the lifetime of the call.
     Takes ownership of \a elem_to_add */
-void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch,
-                                  grpc_linked_mdelem *storage,
-                                  grpc_mdelem *elem_to_add);
+grpc_error *grpc_metadata_batch_add_tail(
+    grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch,
+    grpc_linked_mdelem *storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
 
-/** For each element in \a batch, execute \a filter.
-    The return value from \a filter will be substituted for the
-    grpc_mdelem passed to \a filter. If \a filter returns NULL,
-    the element will be moved to the garbage list. */
-void grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx,
-                                grpc_metadata_batch *batch,
-                                grpc_mdelem *(*filter)(grpc_exec_ctx *exec_ctx,
-                                                       void *user_data,
-                                                       grpc_mdelem *elem),
-                                void *user_data);
+grpc_error *grpc_attach_md_to_error(grpc_error *src, grpc_mdelem md);
+
+typedef struct {
+  grpc_error *error;
+  grpc_mdelem md;
+} grpc_filtered_mdelem;
+
+#define GRPC_FILTERED_ERROR(error) \
+  ((grpc_filtered_mdelem){(error), GRPC_MDNULL})
+#define GRPC_FILTERED_MDELEM(md) ((grpc_filtered_mdelem){GRPC_ERROR_NONE, (md)})
+#define GRPC_FILTERED_REMOVE() \
+  ((grpc_filtered_mdelem){GRPC_ERROR_NONE, GRPC_MDNULL})
+
+typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)(
+    grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem elem);
+grpc_error *grpc_metadata_batch_filter(
+    grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch,
+    grpc_metadata_batch_filter_func func, void *user_data,
+    const char *composite_error_string) GRPC_MUST_USE_RESULT;
 
 #ifndef NDEBUG
 void grpc_metadata_batch_assert_ok(grpc_metadata_batch *comd);
diff --git a/src/core/lib/transport/method_config.c b/src/core/lib/transport/method_config.c
deleted file mode 100644
index 25fb54b..0000000
--- a/src/core/lib/transport/method_config.c
+++ /dev/null
@@ -1,347 +0,0 @@
-//
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#include "src/core/lib/transport/method_config.h"
-
-#include <string.h>
-
-#include <grpc/impl/codegen/grpc_types.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/time.h>
-
-#include "src/core/lib/transport/mdstr_hash_table.h"
-#include "src/core/lib/transport/metadata.h"
-
-//
-// grpc_method_config
-//
-
-// bool vtable
-
-static void* bool_copy(void* valuep) {
-  bool value = *(bool*)valuep;
-  bool* new_value = gpr_malloc(sizeof(bool));
-  *new_value = value;
-  return new_value;
-}
-
-static int bool_cmp(void* v1, void* v2) {
-  bool b1 = *(bool*)v1;
-  bool b2 = *(bool*)v2;
-  if (!b1 && b2) return -1;
-  if (b1 && !b2) return 1;
-  return 0;
-}
-
-static void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); }
-
-static grpc_mdstr_hash_table_vtable bool_vtable = {free_mem, bool_copy,
-                                                   bool_cmp};
-
-// timespec vtable
-
-static void* timespec_copy(void* valuep) {
-  gpr_timespec value = *(gpr_timespec*)valuep;
-  gpr_timespec* new_value = gpr_malloc(sizeof(gpr_timespec));
-  *new_value = value;
-  return new_value;
-}
-
-static int timespec_cmp(void* v1, void* v2) {
-  return gpr_time_cmp(*(gpr_timespec*)v1, *(gpr_timespec*)v2);
-}
-
-static grpc_mdstr_hash_table_vtable timespec_vtable = {free_mem, timespec_copy,
-                                                       timespec_cmp};
-
-// int32 vtable
-
-static void* int32_copy(void* valuep) {
-  int32_t value = *(int32_t*)valuep;
-  int32_t* new_value = gpr_malloc(sizeof(int32_t));
-  *new_value = value;
-  return new_value;
-}
-
-static int int32_cmp(void* v1, void* v2) {
-  int32_t i1 = *(int32_t*)v1;
-  int32_t i2 = *(int32_t*)v2;
-  if (i1 < i2) return -1;
-  if (i1 > i2) return 1;
-  return 0;
-}
-
-static grpc_mdstr_hash_table_vtable int32_vtable = {free_mem, int32_copy,
-                                                    int32_cmp};
-
-// Hash table keys.
-#define GRPC_METHOD_CONFIG_WAIT_FOR_READY "grpc.wait_for_ready"  // bool
-#define GRPC_METHOD_CONFIG_TIMEOUT "grpc.timeout"                // gpr_timespec
-#define GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES \
-  "grpc.max_request_message_bytes"  // int32
-#define GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES \
-  "grpc.max_response_message_bytes"  // int32
-
-struct grpc_method_config {
-  grpc_mdstr_hash_table* table;
-  grpc_mdstr* wait_for_ready_key;
-  grpc_mdstr* timeout_key;
-  grpc_mdstr* max_request_message_bytes_key;
-  grpc_mdstr* max_response_message_bytes_key;
-};
-
-grpc_method_config* grpc_method_config_create(
-    bool* wait_for_ready, gpr_timespec* timeout,
-    int32_t* max_request_message_bytes, int32_t* max_response_message_bytes) {
-  grpc_method_config* method_config = gpr_malloc(sizeof(grpc_method_config));
-  memset(method_config, 0, sizeof(grpc_method_config));
-  method_config->wait_for_ready_key =
-      grpc_mdstr_from_string(GRPC_METHOD_CONFIG_WAIT_FOR_READY);
-  method_config->timeout_key =
-      grpc_mdstr_from_string(GRPC_METHOD_CONFIG_TIMEOUT);
-  method_config->max_request_message_bytes_key =
-      grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES);
-  method_config->max_response_message_bytes_key =
-      grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES);
-  grpc_mdstr_hash_table_entry entries[4];
-  size_t num_entries = 0;
-  if (wait_for_ready != NULL) {
-    entries[num_entries].key = method_config->wait_for_ready_key;
-    entries[num_entries].value = wait_for_ready;
-    entries[num_entries].vtable = &bool_vtable;
-    ++num_entries;
-  }
-  if (timeout != NULL) {
-    entries[num_entries].key = method_config->timeout_key;
-    entries[num_entries].value = timeout;
-    entries[num_entries].vtable = &timespec_vtable;
-    ++num_entries;
-  }
-  if (max_request_message_bytes != NULL) {
-    entries[num_entries].key = method_config->max_request_message_bytes_key;
-    entries[num_entries].value = max_request_message_bytes;
-    entries[num_entries].vtable = &int32_vtable;
-    ++num_entries;
-  }
-  if (max_response_message_bytes != NULL) {
-    entries[num_entries].key = method_config->max_response_message_bytes_key;
-    entries[num_entries].value = max_response_message_bytes;
-    entries[num_entries].vtable = &int32_vtable;
-    ++num_entries;
-  }
-  method_config->table = grpc_mdstr_hash_table_create(num_entries, entries);
-  return method_config;
-}
-
-grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config) {
-  grpc_mdstr_hash_table_ref(method_config->table);
-  return method_config;
-}
-
-void grpc_method_config_unref(grpc_exec_ctx* exec_ctx,
-                              grpc_method_config* method_config) {
-  if (grpc_mdstr_hash_table_unref(exec_ctx, method_config->table)) {
-    GRPC_MDSTR_UNREF(exec_ctx, method_config->wait_for_ready_key);
-    GRPC_MDSTR_UNREF(exec_ctx, method_config->timeout_key);
-    GRPC_MDSTR_UNREF(exec_ctx, method_config->max_request_message_bytes_key);
-    GRPC_MDSTR_UNREF(exec_ctx, method_config->max_response_message_bytes_key);
-    gpr_free(method_config);
-  }
-}
-
-int grpc_method_config_cmp(const grpc_method_config* method_config1,
-                           const grpc_method_config* method_config2) {
-  return grpc_mdstr_hash_table_cmp(method_config1->table,
-                                   method_config2->table);
-}
-
-const bool* grpc_method_config_get_wait_for_ready(
-    const grpc_method_config* method_config) {
-  return grpc_mdstr_hash_table_get(method_config->table,
-                                   method_config->wait_for_ready_key);
-}
-
-const gpr_timespec* grpc_method_config_get_timeout(
-    const grpc_method_config* method_config) {
-  return grpc_mdstr_hash_table_get(method_config->table,
-                                   method_config->timeout_key);
-}
-
-const int32_t* grpc_method_config_get_max_request_message_bytes(
-    const grpc_method_config* method_config) {
-  return grpc_mdstr_hash_table_get(
-      method_config->table, method_config->max_request_message_bytes_key);
-}
-
-const int32_t* grpc_method_config_get_max_response_message_bytes(
-    const grpc_method_config* method_config) {
-  return grpc_mdstr_hash_table_get(
-      method_config->table, method_config->max_response_message_bytes_key);
-}
-
-//
-// grpc_method_config_table
-//
-
-static void method_config_unref(grpc_exec_ctx* exec_ctx, void* valuep) {
-  grpc_method_config_unref(exec_ctx, valuep);
-}
-
-static void* method_config_ref(void* valuep) {
-  return grpc_method_config_ref(valuep);
-}
-
-static int method_config_cmp(void* valuep1, void* valuep2) {
-  return grpc_method_config_cmp(valuep1, valuep2);
-}
-
-static const grpc_mdstr_hash_table_vtable method_config_table_vtable = {
-    method_config_unref, method_config_ref, method_config_cmp};
-
-grpc_method_config_table* grpc_method_config_table_create(
-    size_t num_entries, grpc_method_config_table_entry* entries) {
-  grpc_mdstr_hash_table_entry* hash_table_entries =
-      gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) * num_entries);
-  for (size_t i = 0; i < num_entries; ++i) {
-    hash_table_entries[i].key = entries[i].method_name;
-    hash_table_entries[i].value = entries[i].method_config;
-    hash_table_entries[i].vtable = &method_config_table_vtable;
-  }
-  grpc_method_config_table* method_config_table =
-      grpc_mdstr_hash_table_create(num_entries, hash_table_entries);
-  gpr_free(hash_table_entries);
-  return method_config_table;
-}
-
-grpc_method_config_table* grpc_method_config_table_ref(
-    grpc_method_config_table* table) {
-  return grpc_mdstr_hash_table_ref(table);
-}
-
-void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx,
-                                    grpc_method_config_table* table) {
-  grpc_mdstr_hash_table_unref(exec_ctx, table);
-}
-
-int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
-                                 const grpc_method_config_table* table2) {
-  return grpc_mdstr_hash_table_cmp(table1, table2);
-}
-
-void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
-                                   const grpc_mdstr_hash_table* table,
-                                   const grpc_mdstr* path) {
-  void* value = grpc_mdstr_hash_table_get(table, path);
-  // If we didn't find a match for the path, try looking for a wildcard
-  // entry (i.e., change "/service/method" to "/service/*").
-  if (value == NULL) {
-    const char* path_str = grpc_mdstr_as_c_string(path);
-    const char* sep = strrchr(path_str, '/') + 1;
-    const size_t len = (size_t)(sep - path_str);
-    char* buf = gpr_malloc(len + 2);  // '*' and NUL
-    memcpy(buf, path_str, len);
-    buf[len] = '*';
-    buf[len + 1] = '\0';
-    grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
-    gpr_free(buf);
-    value = grpc_mdstr_hash_table_get(table, wildcard_path);
-    GRPC_MDSTR_UNREF(exec_ctx, wildcard_path);
-  }
-  return value;
-}
-
-static void* copy_arg(void* p) { return grpc_method_config_table_ref(p); }
-
-static void destroy_arg(grpc_exec_ctx* exec_ctx, void* p) {
-  grpc_method_config_table_unref(exec_ctx, p);
-}
-
-static int cmp_arg(void* p1, void* p2) {
-  return grpc_method_config_table_cmp(p1, p2);
-}
-
-static grpc_arg_pointer_vtable arg_vtable = {copy_arg, destroy_arg, cmp_arg};
-
-grpc_arg grpc_method_config_table_create_channel_arg(
-    grpc_method_config_table* table) {
-  grpc_arg arg;
-  arg.type = GRPC_ARG_POINTER;
-  arg.key = GRPC_ARG_SERVICE_CONFIG;
-  arg.value.pointer.p = table;
-  arg.value.pointer.vtable = &arg_vtable;
-  return arg;
-}
-
-// State used by convert_entry() below.
-typedef struct conversion_state {
-  void* (*convert_value)(const grpc_method_config* method_config);
-  const grpc_mdstr_hash_table_vtable* vtable;
-  size_t num_entries;
-  grpc_mdstr_hash_table_entry* entries;
-} conversion_state;
-
-// A function to be passed to grpc_mdstr_hash_table_iterate() to create
-// a copy of the entries.
-static void convert_entry(const grpc_mdstr_hash_table_entry* entry,
-                          void* user_data) {
-  conversion_state* state = user_data;
-  state->entries[state->num_entries].key = GRPC_MDSTR_REF(entry->key);
-  state->entries[state->num_entries].value = state->convert_value(entry->value);
-  state->entries[state->num_entries].vtable = state->vtable;
-  ++state->num_entries;
-}
-
-grpc_mdstr_hash_table* grpc_method_config_table_convert(
-    grpc_exec_ctx* exec_ctx, const grpc_method_config_table* table,
-    void* (*convert_value)(const grpc_method_config* method_config),
-    const grpc_mdstr_hash_table_vtable* vtable) {
-  // Create an array of the entries in the table with converted values.
-  conversion_state state;
-  state.convert_value = convert_value;
-  state.vtable = vtable;
-  state.num_entries = 0;
-  state.entries = gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) *
-                             grpc_mdstr_hash_table_num_entries(table));
-  grpc_mdstr_hash_table_iterate(table, convert_entry, &state);
-  // Create a new table based on the array we just constructed.
-  grpc_mdstr_hash_table* new_table =
-      grpc_mdstr_hash_table_create(state.num_entries, state.entries);
-  // Clean up the array.
-  for (size_t i = 0; i < state.num_entries; ++i) {
-    GRPC_MDSTR_UNREF(exec_ctx, state.entries[i].key);
-    vtable->destroy_value(exec_ctx, state.entries[i].value);
-  }
-  gpr_free(state.entries);
-  // Return the new table.
-  return new_table;
-}
diff --git a/src/core/lib/transport/method_config.h b/src/core/lib/transport/method_config.h
deleted file mode 100644
index d17a493..0000000
--- a/src/core/lib/transport/method_config.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//
-// Copyright 2016, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#ifndef GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H
-#define GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H
-
-#include <stdbool.h>
-
-#include <grpc/impl/codegen/gpr_types.h>
-#include <grpc/impl/codegen/grpc_types.h>
-
-#include "src/core/lib/transport/mdstr_hash_table.h"
-#include "src/core/lib/transport/metadata.h"
-
-/// Per-method configuration.
-typedef struct grpc_method_config grpc_method_config;
-
-/// Creates a grpc_method_config with the specified parameters.
-/// Any parameter may be NULL to indicate that the value is unset.
-///
-/// \a wait_for_ready indicates whether the client should wait until the
-/// request deadline for the channel to become ready, even if there is a
-/// temporary failure before the deadline while attempting to connect.
-///
-/// \a timeout indicates the timeout for calls.
-///
-/// \a max_request_message_bytes and \a max_response_message_bytes
-/// indicate the maximum sizes of the request (checked when sending) and
-/// response (checked when receiving) messages.
-grpc_method_config* grpc_method_config_create(
-    bool* wait_for_ready, gpr_timespec* timeout,
-    int32_t* max_request_message_bytes, int32_t* max_response_message_bytes);
-
-grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config);
-void grpc_method_config_unref(grpc_exec_ctx* exec_ctx,
-                              grpc_method_config* method_config);
-
-/// Compares two grpc_method_configs.
-/// The sort order is stable but undefined.
-int grpc_method_config_cmp(const grpc_method_config* method_config1,
-                           const grpc_method_config* method_config2);
-
-/// These methods return NULL if the requested field is unset.
-/// The caller does NOT take ownership of the result.
-const bool* grpc_method_config_get_wait_for_ready(
-    const grpc_method_config* method_config);
-const gpr_timespec* grpc_method_config_get_timeout(
-    const grpc_method_config* method_config);
-const int32_t* grpc_method_config_get_max_request_message_bytes(
-    const grpc_method_config* method_config);
-const int32_t* grpc_method_config_get_max_response_message_bytes(
-    const grpc_method_config* method_config);
-
-/// A table of method configs.
-typedef grpc_mdstr_hash_table grpc_method_config_table;
-
-typedef struct grpc_method_config_table_entry {
-  /// The name is of one of the following forms:
-  ///   service/method -- specifies exact service and method name
-  ///   service/*      -- matches all methods for the specified service
-  grpc_mdstr* method_name;
-  grpc_method_config* method_config;
-} grpc_method_config_table_entry;
-
-/// Takes new references to all keys and values in \a entries.
-grpc_method_config_table* grpc_method_config_table_create(
-    size_t num_entries, grpc_method_config_table_entry* entries);
-
-grpc_method_config_table* grpc_method_config_table_ref(
-    grpc_method_config_table* table);
-void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx,
-                                    grpc_method_config_table* table);
-
-/// Compares two grpc_method_config_tables.
-/// The sort order is stable but undefined.
-int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
-                                 const grpc_method_config_table* table2);
-
-/// Gets the method config for the specified \a path, which should be of
-/// the form "/service/method".
-/// Returns NULL if the method has no config.
-/// Caller does NOT own a reference to the result.
-///
-/// Note: This returns a void* instead of a grpc_method_config* so that
-/// it can also be used for tables constructed via
-/// grpc_method_config_table_convert().
-void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
-                                   const grpc_mdstr_hash_table* table,
-                                   const grpc_mdstr* path);
-
-/// Returns a channel arg containing \a table.
-grpc_arg grpc_method_config_table_create_channel_arg(
-    grpc_method_config_table* table);
-
-/// Generates a new table from \a table whose values are converted to a
-/// new form via the \a convert_value function.  The new table will use
-/// \a vtable for its values.
-///
-/// This is generally used to convert the table's value type from
-/// grpc_method_config to a simple struct containing only the parameters
-/// relevant to a particular filter, thus avoiding the need for a hash
-/// table lookup on the fast path.  In that scenario, \a convert_value
-/// will return a new instance of the struct containing the values from
-/// the grpc_method_config, and \a vtable provides the methods for
-/// operating on the struct type.
-grpc_mdstr_hash_table* grpc_method_config_table_convert(
-    grpc_exec_ctx* exec_ctx, const grpc_method_config_table* table,
-    void* (*convert_value)(const grpc_method_config* method_config),
-    const grpc_mdstr_hash_table_vtable* vtable);
-
-#endif /* GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H */
diff --git a/src/core/lib/transport/pid_controller.c b/src/core/lib/transport/pid_controller.c
index 3cef225..19cb1c0 100644
--- a/src/core/lib/transport/pid_controller.c
+++ b/src/core/lib/transport/pid_controller.c
@@ -32,26 +32,46 @@
  */
 
 #include "src/core/lib/transport/pid_controller.h"
+#include <grpc/support/useful.h>
 
 void grpc_pid_controller_init(grpc_pid_controller *pid_controller,
-                              double gain_p, double gain_i, double gain_d) {
-  pid_controller->gain_p = gain_p;
-  pid_controller->gain_i = gain_i;
-  pid_controller->gain_d = gain_d;
+                              grpc_pid_controller_args args) {
+  pid_controller->args = args;
+  pid_controller->last_control_value = args.initial_control_value;
   grpc_pid_controller_reset(pid_controller);
 }
 
 void grpc_pid_controller_reset(grpc_pid_controller *pid_controller) {
   pid_controller->last_error = 0.0;
+  pid_controller->last_dc_dt = 0.0;
   pid_controller->error_integral = 0.0;
 }
 
 double grpc_pid_controller_update(grpc_pid_controller *pid_controller,
                                   double error, double dt) {
-  pid_controller->error_integral += error * dt;
+  /* integrate error using the trapezoid rule */
+  pid_controller->error_integral +=
+      dt * (pid_controller->last_error + error) * 0.5;
+  pid_controller->error_integral = GPR_CLAMP(
+      pid_controller->error_integral, -pid_controller->args.integral_range,
+      pid_controller->args.integral_range);
   double diff_error = (error - pid_controller->last_error) / dt;
+  /* calculate derivative of control value vs time */
+  double dc_dt = pid_controller->args.gain_p * error +
+                 pid_controller->args.gain_i * pid_controller->error_integral +
+                 pid_controller->args.gain_d * diff_error;
+  /* and perform trapezoidal integration */
+  double new_control_value = pid_controller->last_control_value +
+                             dt * (pid_controller->last_dc_dt + dc_dt) * 0.5;
+  new_control_value =
+      GPR_CLAMP(new_control_value, pid_controller->args.min_control_value,
+                pid_controller->args.max_control_value);
   pid_controller->last_error = error;
-  return dt * (pid_controller->gain_p * error +
-               pid_controller->gain_i * pid_controller->error_integral +
-               pid_controller->gain_d * diff_error);
+  pid_controller->last_dc_dt = dc_dt;
+  pid_controller->last_control_value = new_control_value;
+  return new_control_value;
+}
+
+double grpc_pid_controller_last(grpc_pid_controller *pid_controller) {
+  return pid_controller->last_control_value;
 }
diff --git a/src/core/lib/transport/pid_controller.h b/src/core/lib/transport/pid_controller.h
index 83c82d6..0a86521 100644
--- a/src/core/lib/transport/pid_controller.h
+++ b/src/core/lib/transport/pid_controller.h
@@ -45,20 +45,33 @@
   double gain_p;
   double gain_i;
   double gain_d;
+  double initial_control_value;
+  double min_control_value;
+  double max_control_value;
+  double integral_range;
+} grpc_pid_controller_args;
+
+typedef struct {
   double last_error;
   double error_integral;
+  double last_control_value;
+  double last_dc_dt;
+  grpc_pid_controller_args args;
 } grpc_pid_controller;
 
 /** Initialize the controller */
 void grpc_pid_controller_init(grpc_pid_controller *pid_controller,
-                              double gain_p, double gain_i, double gain_d);
+                              grpc_pid_controller_args args);
 
 /** Reset the controller: useful when things have changed significantly */
 void grpc_pid_controller_reset(grpc_pid_controller *pid_controller);
 
 /** Update the controller: given a current error estimate, and the time since
-    the last update, returns a delta to the control value */
+    the last update, returns a new control value */
 double grpc_pid_controller_update(grpc_pid_controller *pid_controller,
                                   double error, double dt);
 
+/** Returns the last control value calculated */
+double grpc_pid_controller_last(grpc_pid_controller *pid_controller);
+
 #endif /* GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H */
diff --git a/src/core/lib/transport/service_config.c b/src/core/lib/transport/service_config.c
index 552d3ec..12da2a8 100644
--- a/src/core/lib/transport/service_config.c
+++ b/src/core/lib/transport/service_config.c
@@ -39,8 +39,10 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/json/json.h"
+#include "src/core/lib/slice/slice_hash_table.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
-#include "src/core/lib/transport/mdstr_hash_table.h"
 
 // The main purpose of the code here is to parse the service config in
 // JSON form, which will look like this:
@@ -148,8 +150,8 @@
 static bool parse_json_method_config(
     grpc_exec_ctx* exec_ctx, grpc_json* json,
     void* (*create_value)(const grpc_json* method_config_json),
-    const grpc_mdstr_hash_table_vtable* vtable,
-    grpc_mdstr_hash_table_entry* entries, size_t* idx) {
+    const grpc_slice_hash_table_vtable* vtable,
+    grpc_slice_hash_table_entry* entries, size_t* idx) {
   // Construct value.
   void* method_config = create_value(json);
   if (method_config == NULL) return false;
@@ -170,7 +172,7 @@
   if (paths.count == 0) goto done;  // No names specified.
   // Add entry for each path.
   for (size_t i = 0; i < paths.count; ++i) {
-    entries[*idx].key = grpc_mdstr_from_string(paths.strs[i]);
+    entries[*idx].key = grpc_slice_from_copied_string(paths.strs[i]);
     entries[*idx].value = vtable->copy_value(method_config);
     entries[*idx].vtable = vtable;
     ++*idx;
@@ -182,15 +184,15 @@
   return success;
 }
 
-grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
+grpc_slice_hash_table* grpc_service_config_create_method_config_table(
     grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config,
     void* (*create_value)(const grpc_json* method_config_json),
-    const grpc_mdstr_hash_table_vtable* vtable) {
+    const grpc_slice_hash_table_vtable* vtable) {
   const grpc_json* json = service_config->json_tree;
   // Traverse parsed JSON tree.
   if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL;
   size_t num_entries = 0;
-  grpc_mdstr_hash_table_entry* entries = NULL;
+  grpc_slice_hash_table_entry* entries = NULL;
   for (grpc_json* field = json->child; field != NULL; field = field->next) {
     if (field->key == NULL) return NULL;
     if (strcmp(field->key, "methodConfig") == 0) {
@@ -202,7 +204,7 @@
         num_entries += count_names_in_method_config_json(method);
       }
       // Populate method config table entries.
-      entries = gpr_malloc(num_entries * sizeof(grpc_mdstr_hash_table_entry));
+      entries = gpr_malloc(num_entries * sizeof(grpc_slice_hash_table_entry));
       size_t idx = 0;
       for (grpc_json* method = field->child; method != NULL;
            method = method->next) {
@@ -215,12 +217,12 @@
     }
   }
   // Instantiate method config table.
-  grpc_mdstr_hash_table* method_config_table = NULL;
+  grpc_slice_hash_table* method_config_table = NULL;
   if (entries != NULL) {
-    method_config_table = grpc_mdstr_hash_table_create(num_entries, entries);
+    method_config_table = grpc_slice_hash_table_create(num_entries, entries);
     // Clean up.
     for (size_t i = 0; i < num_entries; ++i) {
-      GRPC_MDSTR_UNREF(exec_ctx, entries[i].key);
+      grpc_slice_unref_internal(exec_ctx, entries[i].key);
       vtable->destroy_value(exec_ctx, entries[i].value);
     }
     gpr_free(entries);
@@ -229,23 +231,24 @@
 }
 
 void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
-                                   const grpc_mdstr_hash_table* table,
-                                   const grpc_mdstr* path) {
-  void* value = grpc_mdstr_hash_table_get(table, path);
+                                   const grpc_slice_hash_table* table,
+                                   grpc_slice path) {
+  void* value = grpc_slice_hash_table_get(table, path);
   // If we didn't find a match for the path, try looking for a wildcard
   // entry (i.e., change "/service/method" to "/service/*").
   if (value == NULL) {
-    const char* path_str = grpc_mdstr_as_c_string(path);
+    char* path_str = grpc_slice_to_c_string(path);
     const char* sep = strrchr(path_str, '/') + 1;
     const size_t len = (size_t)(sep - path_str);
     char* buf = gpr_malloc(len + 2);  // '*' and NUL
     memcpy(buf, path_str, len);
     buf[len] = '*';
     buf[len + 1] = '\0';
-    grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
+    grpc_slice wildcard_path = grpc_slice_from_copied_string(buf);
     gpr_free(buf);
-    value = grpc_mdstr_hash_table_get(table, wildcard_path);
-    GRPC_MDSTR_UNREF(exec_ctx, wildcard_path);
+    value = grpc_slice_hash_table_get(table, wildcard_path);
+    grpc_slice_unref_internal(exec_ctx, wildcard_path);
+    gpr_free(path_str);
   }
   return value;
 }
diff --git a/src/core/lib/transport/service_config.h b/src/core/lib/transport/service_config.h
index f089717..cd739a5 100644
--- a/src/core/lib/transport/service_config.h
+++ b/src/core/lib/transport/service_config.h
@@ -35,7 +35,7 @@
 #include <grpc/impl/codegen/grpc_types.h>
 
 #include "src/core/lib/json/json.h"
-#include "src/core/lib/transport/mdstr_hash_table.h"
+#include "src/core/lib/slice/slice_hash_table.h"
 
 typedef struct grpc_service_config grpc_service_config;
 
@@ -53,10 +53,10 @@
 /// returned by \a create_value(), based on data parsed from the JSON tree.
 /// \a vtable provides methods used to manage the values.
 /// Returns NULL on error.
-grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
+grpc_slice_hash_table* grpc_service_config_create_method_config_table(
     grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config,
     void* (*create_value)(const grpc_json* method_config_json),
-    const grpc_mdstr_hash_table_vtable* vtable);
+    const grpc_slice_hash_table_vtable* vtable);
 
 /// A helper function for looking up values in the table returned by
 /// \a grpc_service_config_create_method_config_table().
@@ -65,7 +65,7 @@
 /// Returns NULL if the method has no config.
 /// Caller does NOT own a reference to the result.
 void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
-                                   const grpc_mdstr_hash_table* table,
-                                   const grpc_mdstr* path);
+                                   const grpc_slice_hash_table* table,
+                                   grpc_slice path);
 
 #endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */
diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c
index 8b22592..c13ba23 100644
--- a/src/core/lib/transport/static_metadata.c
+++ b/src/core/lib/transport/static_metadata.c
@@ -41,120 +41,761 @@
 
 #include "src/core/lib/transport/static_metadata.h"
 
-grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
+#include "src/core/lib/slice/slice_internal.h"
 
-grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+static uint8_t g_bytes[] = {
+    58,  112, 97,  116, 104, 58,  109, 101, 116, 104, 111, 100, 58,  115, 116,
+    97,  116, 117, 115, 58,  97,  117, 116, 104, 111, 114, 105, 116, 121, 58,
+    115, 99,  104, 101, 109, 101, 116, 101, 103, 114, 112, 99,  45,  109, 101,
+    115, 115, 97,  103, 101, 103, 114, 112, 99,  45,  115, 116, 97,  116, 117,
+    115, 103, 114, 112, 99,  45,  112, 97,  121, 108, 111, 97,  100, 45,  98,
+    105, 110, 103, 114, 112, 99,  45,  101, 110, 99,  111, 100, 105, 110, 103,
+    103, 114, 112, 99,  45,  97,  99,  99,  101, 112, 116, 45,  101, 110, 99,
+    111, 100, 105, 110, 103, 99,  111, 110, 116, 101, 110, 116, 45,  116, 121,
+    112, 101, 103, 114, 112, 99,  45,  105, 110, 116, 101, 114, 110, 97,  108,
+    45,  101, 110, 99,  111, 100, 105, 110, 103, 45,  114, 101, 113, 117, 101,
+    115, 116, 117, 115, 101, 114, 45,  97,  103, 101, 110, 116, 104, 111, 115,
+    116, 108, 98,  45,  116, 111, 107, 101, 110, 103, 114, 112, 99,  45,  116,
+    105, 109, 101, 111, 117, 116, 103, 114, 112, 99,  45,  116, 114, 97,  99,
+    105, 110, 103, 45,  98,  105, 110, 103, 114, 112, 99,  45,  115, 116, 97,
+    116, 115, 45,  98,  105, 110, 103, 114, 112, 99,  46,  119, 97,  105, 116,
+    95,  102, 111, 114, 95,  114, 101, 97,  100, 121, 103, 114, 112, 99,  46,
+    116, 105, 109, 101, 111, 117, 116, 103, 114, 112, 99,  46,  109, 97,  120,
+    95,  114, 101, 113, 117, 101, 115, 116, 95,  109, 101, 115, 115, 97,  103,
+    101, 95,  98,  121, 116, 101, 115, 103, 114, 112, 99,  46,  109, 97,  120,
+    95,  114, 101, 115, 112, 111, 110, 115, 101, 95,  109, 101, 115, 115, 97,
+    103, 101, 95,  98,  121, 116, 101, 115, 47,  103, 114, 112, 99,  46,  108,
+    98,  46,  118, 49,  46,  76,  111, 97,  100, 66,  97,  108, 97,  110, 99,
+    101, 114, 47,  66,  97,  108, 97,  110, 99,  101, 76,  111, 97,  100, 48,
+    49,  50,  105, 100, 101, 110, 116, 105, 116, 121, 103, 122, 105, 112, 100,
+    101, 102, 108, 97,  116, 101, 116, 114, 97,  105, 108, 101, 114, 115, 97,
+    112, 112, 108, 105, 99,  97,  116, 105, 111, 110, 47,  103, 114, 112, 99,
+    80,  79,  83,  84,  50,  48,  48,  52,  48,  52,  104, 116, 116, 112, 104,
+    116, 116, 112, 115, 103, 114, 112, 99,  71,  69,  84,  80,  85,  84,  47,
+    47,  105, 110, 100, 101, 120, 46,  104, 116, 109, 108, 50,  48,  52,  50,
+    48,  54,  51,  48,  52,  52,  48,  48,  53,  48,  48,  97,  99,  99,  101,
+    112, 116, 45,  99,  104, 97,  114, 115, 101, 116, 97,  99,  99,  101, 112,
+    116, 45,  101, 110, 99,  111, 100, 105, 110, 103, 103, 122, 105, 112, 44,
+    32,  100, 101, 102, 108, 97,  116, 101, 97,  99,  99,  101, 112, 116, 45,
+    108, 97,  110, 103, 117, 97,  103, 101, 97,  99,  99,  101, 112, 116, 45,
+    114, 97,  110, 103, 101, 115, 97,  99,  99,  101, 112, 116, 97,  99,  99,
+    101, 115, 115, 45,  99,  111, 110, 116, 114, 111, 108, 45,  97,  108, 108,
+    111, 119, 45,  111, 114, 105, 103, 105, 110, 97,  103, 101, 97,  108, 108,
+    111, 119, 97,  117, 116, 104, 111, 114, 105, 122, 97,  116, 105, 111, 110,
+    99,  97,  99,  104, 101, 45,  99,  111, 110, 116, 114, 111, 108, 99,  111,
+    110, 116, 101, 110, 116, 45,  100, 105, 115, 112, 111, 115, 105, 116, 105,
+    111, 110, 99,  111, 110, 116, 101, 110, 116, 45,  101, 110, 99,  111, 100,
+    105, 110, 103, 99,  111, 110, 116, 101, 110, 116, 45,  108, 97,  110, 103,
+    117, 97,  103, 101, 99,  111, 110, 116, 101, 110, 116, 45,  108, 101, 110,
+    103, 116, 104, 99,  111, 110, 116, 101, 110, 116, 45,  108, 111, 99,  97,
+    116, 105, 111, 110, 99,  111, 110, 116, 101, 110, 116, 45,  114, 97,  110,
+    103, 101, 99,  111, 111, 107, 105, 101, 100, 97,  116, 101, 101, 116, 97,
+    103, 101, 120, 112, 101, 99,  116, 101, 120, 112, 105, 114, 101, 115, 102,
+    114, 111, 109, 105, 102, 45,  109, 97,  116, 99,  104, 105, 102, 45,  109,
+    111, 100, 105, 102, 105, 101, 100, 45,  115, 105, 110, 99,  101, 105, 102,
+    45,  110, 111, 110, 101, 45,  109, 97,  116, 99,  104, 105, 102, 45,  114,
+    97,  110, 103, 101, 105, 102, 45,  117, 110, 109, 111, 100, 105, 102, 105,
+    101, 100, 45,  115, 105, 110, 99,  101, 108, 97,  115, 116, 45,  109, 111,
+    100, 105, 102, 105, 101, 100, 108, 105, 110, 107, 108, 111, 99,  97,  116,
+    105, 111, 110, 109, 97,  120, 45,  102, 111, 114, 119, 97,  114, 100, 115,
+    112, 114, 111, 120, 121, 45,  97,  117, 116, 104, 101, 110, 116, 105, 99,
+    97,  116, 101, 112, 114, 111, 120, 121, 45,  97,  117, 116, 104, 111, 114,
+    105, 122, 97,  116, 105, 111, 110, 114, 97,  110, 103, 101, 114, 101, 102,
+    101, 114, 101, 114, 114, 101, 102, 114, 101, 115, 104, 114, 101, 116, 114,
+    121, 45,  97,  102, 116, 101, 114, 115, 101, 114, 118, 101, 114, 115, 101,
+    116, 45,  99,  111, 111, 107, 105, 101, 115, 116, 114, 105, 99,  116, 45,
+    116, 114, 97,  110, 115, 112, 111, 114, 116, 45,  115, 101, 99,  117, 114,
+    105, 116, 121, 116, 114, 97,  110, 115, 102, 101, 114, 45,  101, 110, 99,
+    111, 100, 105, 110, 103, 118, 97,  114, 121, 118, 105, 97,  119, 119, 119,
+    45,  97,  117, 116, 104, 101, 110, 116, 105, 99,  97,  116, 101, 105, 100,
+    101, 110, 116, 105, 116, 121, 44,  100, 101, 102, 108, 97,  116, 101, 105,
+    100, 101, 110, 116, 105, 116, 121, 44,  103, 122, 105, 112, 100, 101, 102,
+    108, 97,  116, 101, 44,  103, 122, 105, 112, 105, 100, 101, 110, 116, 105,
+    116, 121, 44,  100, 101, 102, 108, 97,  116, 101, 44,  103, 122, 105, 112};
+
+static void static_ref(void *unused) {}
+static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}
+static const grpc_slice_refcount_vtable static_sub_vtable = {
+    static_ref, static_unref, grpc_slice_default_eq_impl,
+    grpc_slice_default_hash_impl};
+const grpc_slice_refcount_vtable grpc_static_metadata_vtable = {
+    static_ref, static_unref, grpc_static_slice_eq, grpc_static_slice_hash};
+static grpc_slice_refcount static_sub_refcnt = {&static_sub_vtable,
+                                                &static_sub_refcnt};
+grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = {
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+    {&grpc_static_metadata_vtable, &static_sub_refcnt},
+};
+
+const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {
+    {.refcount = &grpc_static_metadata_refcounts[0],
+     .data.refcounted = {g_bytes + 0, 5}},
+    {.refcount = &grpc_static_metadata_refcounts[1],
+     .data.refcounted = {g_bytes + 5, 7}},
+    {.refcount = &grpc_static_metadata_refcounts[2],
+     .data.refcounted = {g_bytes + 12, 7}},
+    {.refcount = &grpc_static_metadata_refcounts[3],
+     .data.refcounted = {g_bytes + 19, 10}},
+    {.refcount = &grpc_static_metadata_refcounts[4],
+     .data.refcounted = {g_bytes + 29, 7}},
+    {.refcount = &grpc_static_metadata_refcounts[5],
+     .data.refcounted = {g_bytes + 36, 2}},
+    {.refcount = &grpc_static_metadata_refcounts[6],
+     .data.refcounted = {g_bytes + 38, 12}},
+    {.refcount = &grpc_static_metadata_refcounts[7],
+     .data.refcounted = {g_bytes + 50, 11}},
+    {.refcount = &grpc_static_metadata_refcounts[8],
+     .data.refcounted = {g_bytes + 61, 16}},
+    {.refcount = &grpc_static_metadata_refcounts[9],
+     .data.refcounted = {g_bytes + 77, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[10],
+     .data.refcounted = {g_bytes + 90, 20}},
+    {.refcount = &grpc_static_metadata_refcounts[11],
+     .data.refcounted = {g_bytes + 110, 12}},
+    {.refcount = &grpc_static_metadata_refcounts[12],
+     .data.refcounted = {g_bytes + 122, 30}},
+    {.refcount = &grpc_static_metadata_refcounts[13],
+     .data.refcounted = {g_bytes + 152, 10}},
+    {.refcount = &grpc_static_metadata_refcounts[14],
+     .data.refcounted = {g_bytes + 162, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[15],
+     .data.refcounted = {g_bytes + 166, 8}},
+    {.refcount = &grpc_static_metadata_refcounts[16],
+     .data.refcounted = {g_bytes + 174, 12}},
+    {.refcount = &grpc_static_metadata_refcounts[17],
+     .data.refcounted = {g_bytes + 186, 16}},
+    {.refcount = &grpc_static_metadata_refcounts[18],
+     .data.refcounted = {g_bytes + 202, 14}},
+    {.refcount = &grpc_static_metadata_refcounts[19],
+     .data.refcounted = {g_bytes + 216, 0}},
+    {.refcount = &grpc_static_metadata_refcounts[20],
+     .data.refcounted = {g_bytes + 216, 19}},
+    {.refcount = &grpc_static_metadata_refcounts[21],
+     .data.refcounted = {g_bytes + 235, 12}},
+    {.refcount = &grpc_static_metadata_refcounts[22],
+     .data.refcounted = {g_bytes + 247, 30}},
+    {.refcount = &grpc_static_metadata_refcounts[23],
+     .data.refcounted = {g_bytes + 277, 31}},
+    {.refcount = &grpc_static_metadata_refcounts[24],
+     .data.refcounted = {g_bytes + 308, 36}},
+    {.refcount = &grpc_static_metadata_refcounts[25],
+     .data.refcounted = {g_bytes + 344, 1}},
+    {.refcount = &grpc_static_metadata_refcounts[26],
+     .data.refcounted = {g_bytes + 345, 1}},
+    {.refcount = &grpc_static_metadata_refcounts[27],
+     .data.refcounted = {g_bytes + 346, 1}},
+    {.refcount = &grpc_static_metadata_refcounts[28],
+     .data.refcounted = {g_bytes + 347, 8}},
+    {.refcount = &grpc_static_metadata_refcounts[29],
+     .data.refcounted = {g_bytes + 355, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[30],
+     .data.refcounted = {g_bytes + 359, 7}},
+    {.refcount = &grpc_static_metadata_refcounts[31],
+     .data.refcounted = {g_bytes + 366, 8}},
+    {.refcount = &grpc_static_metadata_refcounts[32],
+     .data.refcounted = {g_bytes + 374, 16}},
+    {.refcount = &grpc_static_metadata_refcounts[33],
+     .data.refcounted = {g_bytes + 390, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[34],
+     .data.refcounted = {g_bytes + 394, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[35],
+     .data.refcounted = {g_bytes + 397, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[36],
+     .data.refcounted = {g_bytes + 400, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[37],
+     .data.refcounted = {g_bytes + 404, 5}},
+    {.refcount = &grpc_static_metadata_refcounts[38],
+     .data.refcounted = {g_bytes + 409, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[39],
+     .data.refcounted = {g_bytes + 413, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[40],
+     .data.refcounted = {g_bytes + 416, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[41],
+     .data.refcounted = {g_bytes + 419, 1}},
+    {.refcount = &grpc_static_metadata_refcounts[42],
+     .data.refcounted = {g_bytes + 420, 11}},
+    {.refcount = &grpc_static_metadata_refcounts[43],
+     .data.refcounted = {g_bytes + 431, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[44],
+     .data.refcounted = {g_bytes + 434, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[45],
+     .data.refcounted = {g_bytes + 437, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[46],
+     .data.refcounted = {g_bytes + 440, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[47],
+     .data.refcounted = {g_bytes + 443, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[48],
+     .data.refcounted = {g_bytes + 446, 14}},
+    {.refcount = &grpc_static_metadata_refcounts[49],
+     .data.refcounted = {g_bytes + 460, 15}},
+    {.refcount = &grpc_static_metadata_refcounts[50],
+     .data.refcounted = {g_bytes + 475, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[51],
+     .data.refcounted = {g_bytes + 488, 15}},
+    {.refcount = &grpc_static_metadata_refcounts[52],
+     .data.refcounted = {g_bytes + 503, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[53],
+     .data.refcounted = {g_bytes + 516, 6}},
+    {.refcount = &grpc_static_metadata_refcounts[54],
+     .data.refcounted = {g_bytes + 522, 27}},
+    {.refcount = &grpc_static_metadata_refcounts[55],
+     .data.refcounted = {g_bytes + 549, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[56],
+     .data.refcounted = {g_bytes + 552, 5}},
+    {.refcount = &grpc_static_metadata_refcounts[57],
+     .data.refcounted = {g_bytes + 557, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[58],
+     .data.refcounted = {g_bytes + 570, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[59],
+     .data.refcounted = {g_bytes + 583, 19}},
+    {.refcount = &grpc_static_metadata_refcounts[60],
+     .data.refcounted = {g_bytes + 602, 16}},
+    {.refcount = &grpc_static_metadata_refcounts[61],
+     .data.refcounted = {g_bytes + 618, 16}},
+    {.refcount = &grpc_static_metadata_refcounts[62],
+     .data.refcounted = {g_bytes + 634, 14}},
+    {.refcount = &grpc_static_metadata_refcounts[63],
+     .data.refcounted = {g_bytes + 648, 16}},
+    {.refcount = &grpc_static_metadata_refcounts[64],
+     .data.refcounted = {g_bytes + 664, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[65],
+     .data.refcounted = {g_bytes + 677, 6}},
+    {.refcount = &grpc_static_metadata_refcounts[66],
+     .data.refcounted = {g_bytes + 683, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[67],
+     .data.refcounted = {g_bytes + 687, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[68],
+     .data.refcounted = {g_bytes + 691, 6}},
+    {.refcount = &grpc_static_metadata_refcounts[69],
+     .data.refcounted = {g_bytes + 697, 7}},
+    {.refcount = &grpc_static_metadata_refcounts[70],
+     .data.refcounted = {g_bytes + 704, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[71],
+     .data.refcounted = {g_bytes + 708, 8}},
+    {.refcount = &grpc_static_metadata_refcounts[72],
+     .data.refcounted = {g_bytes + 716, 17}},
+    {.refcount = &grpc_static_metadata_refcounts[73],
+     .data.refcounted = {g_bytes + 733, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[74],
+     .data.refcounted = {g_bytes + 746, 8}},
+    {.refcount = &grpc_static_metadata_refcounts[75],
+     .data.refcounted = {g_bytes + 754, 19}},
+    {.refcount = &grpc_static_metadata_refcounts[76],
+     .data.refcounted = {g_bytes + 773, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[77],
+     .data.refcounted = {g_bytes + 786, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[78],
+     .data.refcounted = {g_bytes + 790, 8}},
+    {.refcount = &grpc_static_metadata_refcounts[79],
+     .data.refcounted = {g_bytes + 798, 12}},
+    {.refcount = &grpc_static_metadata_refcounts[80],
+     .data.refcounted = {g_bytes + 810, 18}},
+    {.refcount = &grpc_static_metadata_refcounts[81],
+     .data.refcounted = {g_bytes + 828, 19}},
+    {.refcount = &grpc_static_metadata_refcounts[82],
+     .data.refcounted = {g_bytes + 847, 5}},
+    {.refcount = &grpc_static_metadata_refcounts[83],
+     .data.refcounted = {g_bytes + 852, 7}},
+    {.refcount = &grpc_static_metadata_refcounts[84],
+     .data.refcounted = {g_bytes + 859, 7}},
+    {.refcount = &grpc_static_metadata_refcounts[85],
+     .data.refcounted = {g_bytes + 866, 11}},
+    {.refcount = &grpc_static_metadata_refcounts[86],
+     .data.refcounted = {g_bytes + 877, 6}},
+    {.refcount = &grpc_static_metadata_refcounts[87],
+     .data.refcounted = {g_bytes + 883, 10}},
+    {.refcount = &grpc_static_metadata_refcounts[88],
+     .data.refcounted = {g_bytes + 893, 25}},
+    {.refcount = &grpc_static_metadata_refcounts[89],
+     .data.refcounted = {g_bytes + 918, 17}},
+    {.refcount = &grpc_static_metadata_refcounts[90],
+     .data.refcounted = {g_bytes + 935, 4}},
+    {.refcount = &grpc_static_metadata_refcounts[91],
+     .data.refcounted = {g_bytes + 939, 3}},
+    {.refcount = &grpc_static_metadata_refcounts[92],
+     .data.refcounted = {g_bytes + 942, 16}},
+    {.refcount = &grpc_static_metadata_refcounts[93],
+     .data.refcounted = {g_bytes + 958, 16}},
+    {.refcount = &grpc_static_metadata_refcounts[94],
+     .data.refcounted = {g_bytes + 974, 13}},
+    {.refcount = &grpc_static_metadata_refcounts[95],
+     .data.refcounted = {g_bytes + 987, 12}},
+    {.refcount = &grpc_static_metadata_refcounts[96],
+     .data.refcounted = {g_bytes + 999, 21}},
+};
+
 uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8};
 
-const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] =
-    {11, 33, 10, 33, 12, 33, 12, 50, 13, 33, 14, 33, 15, 33, 16, 33, 17, 33,
-     19, 33, 20, 33, 21, 33, 22, 33, 23, 33, 24, 33, 25, 33, 26, 33, 27, 33,
-     28, 18, 28, 33, 29, 33, 30, 33, 34, 33, 35, 33, 36, 33, 37, 33, 40, 31,
-     40, 32, 40, 49, 40, 54, 40, 55, 40, 56, 40, 57, 41, 31, 41, 49, 41, 54,
-     46, 0,  46, 1,  46, 2,  51, 33, 58, 33, 59, 33, 60, 33, 61, 33, 62, 33,
-     63, 33, 64, 33, 65, 33, 66, 33, 67, 33, 68, 33, 69, 38, 69, 71, 69, 74,
-     70, 82, 70, 83, 72, 33, 73, 33, 75, 33, 76, 33, 77, 33, 78, 33, 79, 39,
-     79, 52, 79, 53, 80, 33, 81, 33, 84, 3,  84, 4,  84, 5,  84, 6,  84, 7,
-     84, 8,  84, 9,  85, 33, 86, 87, 88, 33, 89, 33, 90, 33, 91, 33, 92, 33};
+static const int8_t elems_r[] = {
+    10,  8,   -3, 0,   9,   21,  -75, 22,  0,   10,  -7,  20, 0,  19, 18, 17,
+    0,   0,   0,  0,   0,   0,   0,   0,   0,   0,   0,   0,  0,  0,  0,  0,
+    0,   0,   0,  0,   0,   0,   0,   0,   0,   0,   0,   0,  0,  0,  0,  0,
+    -48, -49, 16, -51, -52, -53, -54, -54, -55, -56, -57, 0,  37, 36, 35, 34,
+    33,  32,  31, 30,  29,  28,  27,  26,  25,  24,  23,  22, 21, 20, 19, 18,
+    17,  16,  15, 14,  13,  12,  11,  14,  13,  12,  11,  10, 9,  8,  0};
+static uint32_t elems_phash(uint32_t i) {
+  i -= 41;
+  uint32_t x = i % 95;
+  uint32_t y = i / 95;
+  uint32_t h = x;
+  if (y < GPR_ARRAY_SIZE(elems_r)) {
+    uint32_t delta = (uint32_t)elems_r[y];
+    h += delta;
+  }
+  return h;
+}
 
-const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {
-    "0",
-    "1",
-    "2",
-    "200",
-    "204",
-    "206",
-    "304",
-    "400",
-    "404",
-    "500",
-    "accept",
-    "accept-charset",
-    "accept-encoding",
-    "accept-language",
-    "accept-ranges",
-    "access-control-allow-origin",
-    "age",
-    "allow",
-    "application/grpc",
-    ":authority",
-    "authorization",
-    "cache-control",
-    "content-disposition",
-    "content-encoding",
-    "content-language",
-    "content-length",
-    "content-location",
-    "content-range",
-    "content-type",
-    "cookie",
-    "date",
-    "deflate",
-    "deflate,gzip",
-    "",
-    "etag",
-    "expect",
-    "expires",
-    "from",
-    "GET",
-    "grpc",
-    "grpc-accept-encoding",
-    "grpc-encoding",
-    "grpc-internal-encoding-request",
-    "grpc-message",
-    "grpc-payload-bin",
-    "grpc-stats-bin",
-    "grpc-status",
-    "grpc-timeout",
-    "grpc-tracing-bin",
-    "gzip",
-    "gzip, deflate",
-    "host",
-    "http",
-    "https",
-    "identity",
-    "identity,deflate",
-    "identity,deflate,gzip",
-    "identity,gzip",
-    "if-match",
-    "if-modified-since",
-    "if-none-match",
-    "if-range",
-    "if-unmodified-since",
-    "last-modified",
-    "lb-cost-bin",
-    "lb-token",
-    "link",
-    "location",
-    "max-forwards",
-    ":method",
-    ":path",
-    "POST",
-    "proxy-authenticate",
-    "proxy-authorization",
-    "PUT",
-    "range",
-    "referer",
-    "refresh",
-    "retry-after",
-    ":scheme",
-    "server",
-    "set-cookie",
-    "/",
-    "/index.html",
-    ":status",
-    "strict-transport-security",
-    "te",
-    "trailers",
-    "transfer-encoding",
-    "user-agent",
-    "vary",
-    "via",
-    "www-authenticate"};
+static const uint16_t elem_keys[] = {
+    998,  999,  1000, 237,  238,  239,  240,  241,  136,  137,  41,   42,
+    424,  425,  426,  901,  902,  903,  704,  705,  1086, 516,  706,  1280,
+    1377, 1474, 4675, 4772, 4803, 4966, 5063, 5160, 5257, 1099, 5354, 5451,
+    5548, 5645, 5742, 5839, 5936, 6033, 6130, 6227, 6324, 6421, 6518, 6615,
+    6712, 6809, 6906, 7003, 7100, 7197, 7294, 7391, 7488, 7585, 7682, 7779,
+    7876, 7973, 8070, 8167, 8264, 1063, 1064, 1065, 1066, 8361, 8458, 8555,
+    8652, 8749, 8846, 8943, 310,  0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    130,  228,  229,  0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+static const uint8_t elem_idxs[] = {
+    73,  76,  74,  19,  20,  21,  22,  23,  15,  16,  17,  18,  11,  12,  13,
+    3,   4,   5,   0,   1,   41,  6,   2,   69,  48,  55,  24,  25,  26,  27,
+    28,  29,  30,  7,   31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  42,
+    43,  44,  45,  46,  47,  49,  50,  51,  52,  53,  54,  56,  57,  58,  59,
+    60,  61,  62,  63,  64,  75,  77,  78,  79,  65,  66,  67,  68,  70,  71,
+    72,  14,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 8,   9,   10};
 
-const uint8_t grpc_static_accept_encoding_metadata[8] = {0,  29, 26, 30,
-                                                         28, 32, 27, 31};
+grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) {
+  if (a == -1 || b == -1) return GRPC_MDNULL;
+  uint32_t k = (uint32_t)(a * 97 + b);
+  uint32_t h = elems_phash(k);
+  return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k
+             ? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[elem_idxs[h]],
+                                GRPC_MDELEM_STORAGE_STATIC)
+             : GRPC_MDNULL;
+}
+
+grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {
+    {{.refcount = &grpc_static_metadata_refcounts[7],
+      .data.refcounted = {g_bytes + 50, 11}},
+     {.refcount = &grpc_static_metadata_refcounts[25],
+      .data.refcounted = {g_bytes + 344, 1}}},
+    {{.refcount = &grpc_static_metadata_refcounts[7],
+      .data.refcounted = {g_bytes + 50, 11}},
+     {.refcount = &grpc_static_metadata_refcounts[26],
+      .data.refcounted = {g_bytes + 345, 1}}},
+    {{.refcount = &grpc_static_metadata_refcounts[7],
+      .data.refcounted = {g_bytes + 50, 11}},
+     {.refcount = &grpc_static_metadata_refcounts[27],
+      .data.refcounted = {g_bytes + 346, 1}}},
+    {{.refcount = &grpc_static_metadata_refcounts[9],
+      .data.refcounted = {g_bytes + 77, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[28],
+      .data.refcounted = {g_bytes + 347, 8}}},
+    {{.refcount = &grpc_static_metadata_refcounts[9],
+      .data.refcounted = {g_bytes + 77, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[29],
+      .data.refcounted = {g_bytes + 355, 4}}},
+    {{.refcount = &grpc_static_metadata_refcounts[9],
+      .data.refcounted = {g_bytes + 77, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[30],
+      .data.refcounted = {g_bytes + 359, 7}}},
+    {{.refcount = &grpc_static_metadata_refcounts[5],
+      .data.refcounted = {g_bytes + 36, 2}},
+     {.refcount = &grpc_static_metadata_refcounts[31],
+      .data.refcounted = {g_bytes + 366, 8}}},
+    {{.refcount = &grpc_static_metadata_refcounts[11],
+      .data.refcounted = {g_bytes + 110, 12}},
+     {.refcount = &grpc_static_metadata_refcounts[32],
+      .data.refcounted = {g_bytes + 374, 16}}},
+    {{.refcount = &grpc_static_metadata_refcounts[1],
+      .data.refcounted = {g_bytes + 5, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[33],
+      .data.refcounted = {g_bytes + 390, 4}}},
+    {{.refcount = &grpc_static_metadata_refcounts[2],
+      .data.refcounted = {g_bytes + 12, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[34],
+      .data.refcounted = {g_bytes + 394, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[2],
+      .data.refcounted = {g_bytes + 12, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[35],
+      .data.refcounted = {g_bytes + 397, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[4],
+      .data.refcounted = {g_bytes + 29, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[36],
+      .data.refcounted = {g_bytes + 400, 4}}},
+    {{.refcount = &grpc_static_metadata_refcounts[4],
+      .data.refcounted = {g_bytes + 29, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[37],
+      .data.refcounted = {g_bytes + 404, 5}}},
+    {{.refcount = &grpc_static_metadata_refcounts[4],
+      .data.refcounted = {g_bytes + 29, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[38],
+      .data.refcounted = {g_bytes + 409, 4}}},
+    {{.refcount = &grpc_static_metadata_refcounts[3],
+      .data.refcounted = {g_bytes + 19, 10}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[1],
+      .data.refcounted = {g_bytes + 5, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[39],
+      .data.refcounted = {g_bytes + 413, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[1],
+      .data.refcounted = {g_bytes + 5, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[40],
+      .data.refcounted = {g_bytes + 416, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[0],
+      .data.refcounted = {g_bytes + 0, 5}},
+     {.refcount = &grpc_static_metadata_refcounts[41],
+      .data.refcounted = {g_bytes + 419, 1}}},
+    {{.refcount = &grpc_static_metadata_refcounts[0],
+      .data.refcounted = {g_bytes + 0, 5}},
+     {.refcount = &grpc_static_metadata_refcounts[42],
+      .data.refcounted = {g_bytes + 420, 11}}},
+    {{.refcount = &grpc_static_metadata_refcounts[2],
+      .data.refcounted = {g_bytes + 12, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[43],
+      .data.refcounted = {g_bytes + 431, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[2],
+      .data.refcounted = {g_bytes + 12, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[44],
+      .data.refcounted = {g_bytes + 434, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[2],
+      .data.refcounted = {g_bytes + 12, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[45],
+      .data.refcounted = {g_bytes + 437, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[2],
+      .data.refcounted = {g_bytes + 12, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[46],
+      .data.refcounted = {g_bytes + 440, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[2],
+      .data.refcounted = {g_bytes + 12, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[47],
+      .data.refcounted = {g_bytes + 443, 3}}},
+    {{.refcount = &grpc_static_metadata_refcounts[48],
+      .data.refcounted = {g_bytes + 446, 14}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[49],
+      .data.refcounted = {g_bytes + 460, 15}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[49],
+      .data.refcounted = {g_bytes + 460, 15}},
+     {.refcount = &grpc_static_metadata_refcounts[50],
+      .data.refcounted = {g_bytes + 475, 13}}},
+    {{.refcount = &grpc_static_metadata_refcounts[51],
+      .data.refcounted = {g_bytes + 488, 15}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[52],
+      .data.refcounted = {g_bytes + 503, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[53],
+      .data.refcounted = {g_bytes + 516, 6}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[54],
+      .data.refcounted = {g_bytes + 522, 27}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[55],
+      .data.refcounted = {g_bytes + 549, 3}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[56],
+      .data.refcounted = {g_bytes + 552, 5}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[57],
+      .data.refcounted = {g_bytes + 557, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[58],
+      .data.refcounted = {g_bytes + 570, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[59],
+      .data.refcounted = {g_bytes + 583, 19}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[60],
+      .data.refcounted = {g_bytes + 602, 16}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[61],
+      .data.refcounted = {g_bytes + 618, 16}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[62],
+      .data.refcounted = {g_bytes + 634, 14}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[63],
+      .data.refcounted = {g_bytes + 648, 16}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[64],
+      .data.refcounted = {g_bytes + 664, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[11],
+      .data.refcounted = {g_bytes + 110, 12}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[65],
+      .data.refcounted = {g_bytes + 677, 6}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[66],
+      .data.refcounted = {g_bytes + 683, 4}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[67],
+      .data.refcounted = {g_bytes + 687, 4}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[68],
+      .data.refcounted = {g_bytes + 691, 6}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[69],
+      .data.refcounted = {g_bytes + 697, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[70],
+      .data.refcounted = {g_bytes + 704, 4}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[14],
+      .data.refcounted = {g_bytes + 162, 4}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[71],
+      .data.refcounted = {g_bytes + 708, 8}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[72],
+      .data.refcounted = {g_bytes + 716, 17}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[73],
+      .data.refcounted = {g_bytes + 733, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[74],
+      .data.refcounted = {g_bytes + 746, 8}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[75],
+      .data.refcounted = {g_bytes + 754, 19}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[76],
+      .data.refcounted = {g_bytes + 773, 13}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[15],
+      .data.refcounted = {g_bytes + 166, 8}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[77],
+      .data.refcounted = {g_bytes + 786, 4}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[78],
+      .data.refcounted = {g_bytes + 790, 8}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[79],
+      .data.refcounted = {g_bytes + 798, 12}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[80],
+      .data.refcounted = {g_bytes + 810, 18}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[81],
+      .data.refcounted = {g_bytes + 828, 19}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[82],
+      .data.refcounted = {g_bytes + 847, 5}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[83],
+      .data.refcounted = {g_bytes + 852, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[84],
+      .data.refcounted = {g_bytes + 859, 7}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[85],
+      .data.refcounted = {g_bytes + 866, 11}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[86],
+      .data.refcounted = {g_bytes + 877, 6}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[87],
+      .data.refcounted = {g_bytes + 883, 10}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[88],
+      .data.refcounted = {g_bytes + 893, 25}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[89],
+      .data.refcounted = {g_bytes + 918, 17}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[13],
+      .data.refcounted = {g_bytes + 152, 10}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[90],
+      .data.refcounted = {g_bytes + 935, 4}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[91],
+      .data.refcounted = {g_bytes + 939, 3}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[92],
+      .data.refcounted = {g_bytes + 942, 16}},
+     {.refcount = &grpc_static_metadata_refcounts[19],
+      .data.refcounted = {g_bytes + 216, 0}}},
+    {{.refcount = &grpc_static_metadata_refcounts[10],
+      .data.refcounted = {g_bytes + 90, 20}},
+     {.refcount = &grpc_static_metadata_refcounts[28],
+      .data.refcounted = {g_bytes + 347, 8}}},
+    {{.refcount = &grpc_static_metadata_refcounts[10],
+      .data.refcounted = {g_bytes + 90, 20}},
+     {.refcount = &grpc_static_metadata_refcounts[30],
+      .data.refcounted = {g_bytes + 359, 7}}},
+    {{.refcount = &grpc_static_metadata_refcounts[10],
+      .data.refcounted = {g_bytes + 90, 20}},
+     {.refcount = &grpc_static_metadata_refcounts[93],
+      .data.refcounted = {g_bytes + 958, 16}}},
+    {{.refcount = &grpc_static_metadata_refcounts[10],
+      .data.refcounted = {g_bytes + 90, 20}},
+     {.refcount = &grpc_static_metadata_refcounts[29],
+      .data.refcounted = {g_bytes + 355, 4}}},
+    {{.refcount = &grpc_static_metadata_refcounts[10],
+      .data.refcounted = {g_bytes + 90, 20}},
+     {.refcount = &grpc_static_metadata_refcounts[94],
+      .data.refcounted = {g_bytes + 974, 13}}},
+    {{.refcount = &grpc_static_metadata_refcounts[10],
+      .data.refcounted = {g_bytes + 90, 20}},
+     {.refcount = &grpc_static_metadata_refcounts[95],
+      .data.refcounted = {g_bytes + 987, 12}}},
+    {{.refcount = &grpc_static_metadata_refcounts[10],
+      .data.refcounted = {g_bytes + 90, 20}},
+     {.refcount = &grpc_static_metadata_refcounts[96],
+      .data.refcounted = {g_bytes + 999, 21}}},
+};
+const uint8_t grpc_static_accept_encoding_metadata[8] = {0,  73, 74, 75,
+                                                         76, 77, 78, 79};
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
index 28ad6f2..f9600ee 100644
--- a/src/core/lib/transport/static_metadata.h
+++ b/src/core/lib/transport/static_metadata.h
@@ -44,375 +44,514 @@
 
 #include "src/core/lib/transport/metadata.h"
 
-#define GRPC_STATIC_MDSTR_COUNT 93
-extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];
-/* "0" */
-#define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0])
-/* "1" */
-#define GRPC_MDSTR_1 (&grpc_static_mdstr_table[1])
-/* "2" */
-#define GRPC_MDSTR_2 (&grpc_static_mdstr_table[2])
-/* "200" */
-#define GRPC_MDSTR_200 (&grpc_static_mdstr_table[3])
-/* "204" */
-#define GRPC_MDSTR_204 (&grpc_static_mdstr_table[4])
-/* "206" */
-#define GRPC_MDSTR_206 (&grpc_static_mdstr_table[5])
-/* "304" */
-#define GRPC_MDSTR_304 (&grpc_static_mdstr_table[6])
-/* "400" */
-#define GRPC_MDSTR_400 (&grpc_static_mdstr_table[7])
-/* "404" */
-#define GRPC_MDSTR_404 (&grpc_static_mdstr_table[8])
-/* "500" */
-#define GRPC_MDSTR_500 (&grpc_static_mdstr_table[9])
-/* "accept" */
-#define GRPC_MDSTR_ACCEPT (&grpc_static_mdstr_table[10])
-/* "accept-charset" */
-#define GRPC_MDSTR_ACCEPT_CHARSET (&grpc_static_mdstr_table[11])
-/* "accept-encoding" */
-#define GRPC_MDSTR_ACCEPT_ENCODING (&grpc_static_mdstr_table[12])
-/* "accept-language" */
-#define GRPC_MDSTR_ACCEPT_LANGUAGE (&grpc_static_mdstr_table[13])
-/* "accept-ranges" */
-#define GRPC_MDSTR_ACCEPT_RANGES (&grpc_static_mdstr_table[14])
-/* "access-control-allow-origin" */
-#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (&grpc_static_mdstr_table[15])
-/* "age" */
-#define GRPC_MDSTR_AGE (&grpc_static_mdstr_table[16])
-/* "allow" */
-#define GRPC_MDSTR_ALLOW (&grpc_static_mdstr_table[17])
-/* "application/grpc" */
-#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (&grpc_static_mdstr_table[18])
+#define GRPC_STATIC_MDSTR_COUNT 97
+extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];
+/* ":path" */
+#define GRPC_MDSTR_PATH (grpc_static_slice_table[0])
+/* ":method" */
+#define GRPC_MDSTR_METHOD (grpc_static_slice_table[1])
+/* ":status" */
+#define GRPC_MDSTR_STATUS (grpc_static_slice_table[2])
 /* ":authority" */
-#define GRPC_MDSTR_AUTHORITY (&grpc_static_mdstr_table[19])
-/* "authorization" */
-#define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20])
-/* "cache-control" */
-#define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21])
-/* "content-disposition" */
-#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[22])
-/* "content-encoding" */
-#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[23])
-/* "content-language" */
-#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[24])
-/* "content-length" */
-#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[25])
-/* "content-location" */
-#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[26])
-/* "content-range" */
-#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[27])
-/* "content-type" */
-#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[28])
-/* "cookie" */
-#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[29])
-/* "date" */
-#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[30])
-/* "deflate" */
-#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[31])
-/* "deflate,gzip" */
-#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[32])
-/* "" */
-#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[33])
-/* "etag" */
-#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[34])
-/* "expect" */
-#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[35])
-/* "expires" */
-#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[36])
-/* "from" */
-#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[37])
-/* "GET" */
-#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[38])
-/* "grpc" */
-#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[39])
-/* "grpc-accept-encoding" */
-#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[40])
-/* "grpc-encoding" */
-#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[41])
-/* "grpc-internal-encoding-request" */
-#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[42])
+#define GRPC_MDSTR_AUTHORITY (grpc_static_slice_table[3])
+/* ":scheme" */
+#define GRPC_MDSTR_SCHEME (grpc_static_slice_table[4])
+/* "te" */
+#define GRPC_MDSTR_TE (grpc_static_slice_table[5])
 /* "grpc-message" */
-#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[43])
-/* "grpc-payload-bin" */
-#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (&grpc_static_mdstr_table[44])
-/* "grpc-stats-bin" */
-#define GRPC_MDSTR_GRPC_STATS_BIN (&grpc_static_mdstr_table[45])
+#define GRPC_MDSTR_GRPC_MESSAGE (grpc_static_slice_table[6])
 /* "grpc-status" */
-#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46])
-/* "grpc-timeout" */
-#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[47])
-/* "grpc-tracing-bin" */
-#define GRPC_MDSTR_GRPC_TRACING_BIN (&grpc_static_mdstr_table[48])
-/* "gzip" */
-#define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[49])
-/* "gzip, deflate" */
-#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (&grpc_static_mdstr_table[50])
+#define GRPC_MDSTR_GRPC_STATUS (grpc_static_slice_table[7])
+/* "grpc-payload-bin" */
+#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (grpc_static_slice_table[8])
+/* "grpc-encoding" */
+#define GRPC_MDSTR_GRPC_ENCODING (grpc_static_slice_table[9])
+/* "grpc-accept-encoding" */
+#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (grpc_static_slice_table[10])
+/* "content-type" */
+#define GRPC_MDSTR_CONTENT_TYPE (grpc_static_slice_table[11])
+/* "grpc-internal-encoding-request" */
+#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (grpc_static_slice_table[12])
+/* "user-agent" */
+#define GRPC_MDSTR_USER_AGENT (grpc_static_slice_table[13])
 /* "host" */
-#define GRPC_MDSTR_HOST (&grpc_static_mdstr_table[51])
-/* "http" */
-#define GRPC_MDSTR_HTTP (&grpc_static_mdstr_table[52])
-/* "https" */
-#define GRPC_MDSTR_HTTPS (&grpc_static_mdstr_table[53])
+#define GRPC_MDSTR_HOST (grpc_static_slice_table[14])
+/* "lb-token" */
+#define GRPC_MDSTR_LB_TOKEN (grpc_static_slice_table[15])
+/* "grpc-timeout" */
+#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[16])
+/* "grpc-tracing-bin" */
+#define GRPC_MDSTR_GRPC_TRACING_BIN (grpc_static_slice_table[17])
+/* "grpc-stats-bin" */
+#define GRPC_MDSTR_GRPC_STATS_BIN (grpc_static_slice_table[18])
+/* "" */
+#define GRPC_MDSTR_EMPTY (grpc_static_slice_table[19])
+/* "grpc.wait_for_ready" */
+#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table[20])
+/* "grpc.timeout" */
+#define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table[21])
+/* "grpc.max_request_message_bytes" */
+#define GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES \
+  (grpc_static_slice_table[22])
+/* "grpc.max_response_message_bytes" */
+#define GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES \
+  (grpc_static_slice_table[23])
+/* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */
+#define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \
+  (grpc_static_slice_table[24])
+/* "0" */
+#define GRPC_MDSTR_0 (grpc_static_slice_table[25])
+/* "1" */
+#define GRPC_MDSTR_1 (grpc_static_slice_table[26])
+/* "2" */
+#define GRPC_MDSTR_2 (grpc_static_slice_table[27])
 /* "identity" */
-#define GRPC_MDSTR_IDENTITY (&grpc_static_mdstr_table[54])
+#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[28])
+/* "gzip" */
+#define GRPC_MDSTR_GZIP (grpc_static_slice_table[29])
+/* "deflate" */
+#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[30])
+/* "trailers" */
+#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[31])
+/* "application/grpc" */
+#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[32])
+/* "POST" */
+#define GRPC_MDSTR_POST (grpc_static_slice_table[33])
+/* "200" */
+#define GRPC_MDSTR_200 (grpc_static_slice_table[34])
+/* "404" */
+#define GRPC_MDSTR_404 (grpc_static_slice_table[35])
+/* "http" */
+#define GRPC_MDSTR_HTTP (grpc_static_slice_table[36])
+/* "https" */
+#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[37])
+/* "grpc" */
+#define GRPC_MDSTR_GRPC (grpc_static_slice_table[38])
+/* "GET" */
+#define GRPC_MDSTR_GET (grpc_static_slice_table[39])
+/* "PUT" */
+#define GRPC_MDSTR_PUT (grpc_static_slice_table[40])
+/* "/" */
+#define GRPC_MDSTR_SLASH (grpc_static_slice_table[41])
+/* "/index.html" */
+#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[42])
+/* "204" */
+#define GRPC_MDSTR_204 (grpc_static_slice_table[43])
+/* "206" */
+#define GRPC_MDSTR_206 (grpc_static_slice_table[44])
+/* "304" */
+#define GRPC_MDSTR_304 (grpc_static_slice_table[45])
+/* "400" */
+#define GRPC_MDSTR_400 (grpc_static_slice_table[46])
+/* "500" */
+#define GRPC_MDSTR_500 (grpc_static_slice_table[47])
+/* "accept-charset" */
+#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[48])
+/* "accept-encoding" */
+#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[49])
+/* "gzip, deflate" */
+#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[50])
+/* "accept-language" */
+#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[51])
+/* "accept-ranges" */
+#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[52])
+/* "accept" */
+#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[53])
+/* "access-control-allow-origin" */
+#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[54])
+/* "age" */
+#define GRPC_MDSTR_AGE (grpc_static_slice_table[55])
+/* "allow" */
+#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[56])
+/* "authorization" */
+#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[57])
+/* "cache-control" */
+#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[58])
+/* "content-disposition" */
+#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[59])
+/* "content-encoding" */
+#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[60])
+/* "content-language" */
+#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[61])
+/* "content-length" */
+#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[62])
+/* "content-location" */
+#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[63])
+/* "content-range" */
+#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[64])
+/* "cookie" */
+#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[65])
+/* "date" */
+#define GRPC_MDSTR_DATE (grpc_static_slice_table[66])
+/* "etag" */
+#define GRPC_MDSTR_ETAG (grpc_static_slice_table[67])
+/* "expect" */
+#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[68])
+/* "expires" */
+#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[69])
+/* "from" */
+#define GRPC_MDSTR_FROM (grpc_static_slice_table[70])
+/* "if-match" */
+#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[71])
+/* "if-modified-since" */
+#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[72])
+/* "if-none-match" */
+#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[73])
+/* "if-range" */
+#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[74])
+/* "if-unmodified-since" */
+#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[75])
+/* "last-modified" */
+#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[76])
+/* "link" */
+#define GRPC_MDSTR_LINK (grpc_static_slice_table[77])
+/* "location" */
+#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[78])
+/* "max-forwards" */
+#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[79])
+/* "proxy-authenticate" */
+#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[80])
+/* "proxy-authorization" */
+#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[81])
+/* "range" */
+#define GRPC_MDSTR_RANGE (grpc_static_slice_table[82])
+/* "referer" */
+#define GRPC_MDSTR_REFERER (grpc_static_slice_table[83])
+/* "refresh" */
+#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[84])
+/* "retry-after" */
+#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[85])
+/* "server" */
+#define GRPC_MDSTR_SERVER (grpc_static_slice_table[86])
+/* "set-cookie" */
+#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[87])
+/* "strict-transport-security" */
+#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[88])
+/* "transfer-encoding" */
+#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[89])
+/* "vary" */
+#define GRPC_MDSTR_VARY (grpc_static_slice_table[90])
+/* "via" */
+#define GRPC_MDSTR_VIA (grpc_static_slice_table[91])
+/* "www-authenticate" */
+#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[92])
 /* "identity,deflate" */
-#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (&grpc_static_mdstr_table[55])
+#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[93])
+/* "identity,gzip" */
+#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[94])
+/* "deflate,gzip" */
+#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[95])
 /* "identity,deflate,gzip" */
 #define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
-  (&grpc_static_mdstr_table[56])
-/* "identity,gzip" */
-#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (&grpc_static_mdstr_table[57])
-/* "if-match" */
-#define GRPC_MDSTR_IF_MATCH (&grpc_static_mdstr_table[58])
-/* "if-modified-since" */
-#define GRPC_MDSTR_IF_MODIFIED_SINCE (&grpc_static_mdstr_table[59])
-/* "if-none-match" */
-#define GRPC_MDSTR_IF_NONE_MATCH (&grpc_static_mdstr_table[60])
-/* "if-range" */
-#define GRPC_MDSTR_IF_RANGE (&grpc_static_mdstr_table[61])
-/* "if-unmodified-since" */
-#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[62])
-/* "last-modified" */
-#define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[63])
-/* "lb-cost-bin" */
-#define GRPC_MDSTR_LB_COST_BIN (&grpc_static_mdstr_table[64])
-/* "lb-token" */
-#define GRPC_MDSTR_LB_TOKEN (&grpc_static_mdstr_table[65])
-/* "link" */
-#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[66])
-/* "location" */
-#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[67])
-/* "max-forwards" */
-#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[68])
-/* ":method" */
-#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[69])
-/* ":path" */
-#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[70])
-/* "POST" */
-#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[71])
-/* "proxy-authenticate" */
-#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[72])
-/* "proxy-authorization" */
-#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[73])
-/* "PUT" */
-#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[74])
-/* "range" */
-#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[75])
-/* "referer" */
-#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[76])
-/* "refresh" */
-#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[77])
-/* "retry-after" */
-#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[78])
-/* ":scheme" */
-#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[79])
-/* "server" */
-#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[80])
-/* "set-cookie" */
-#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[81])
-/* "/" */
-#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[82])
-/* "/index.html" */
-#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[83])
-/* ":status" */
-#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[84])
-/* "strict-transport-security" */
-#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[85])
-/* "te" */
-#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[86])
-/* "trailers" */
-#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[87])
-/* "transfer-encoding" */
-#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[88])
-/* "user-agent" */
-#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[89])
-/* "vary" */
-#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[90])
-/* "via" */
-#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[91])
-/* "www-authenticate" */
-#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[92])
+  (grpc_static_slice_table[96])
 
-#define GRPC_STATIC_MDELEM_COUNT 81
-extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+extern const grpc_slice_refcount_vtable grpc_static_metadata_vtable;
+extern grpc_slice_refcount
+    grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT];
+#define GRPC_IS_STATIC_METADATA_STRING(slice) \
+  ((slice).refcount != NULL &&                \
+   (slice).refcount->vtable == &grpc_static_metadata_vtable)
+
+#define GRPC_STATIC_METADATA_INDEX(static_slice) \
+  ((int)((static_slice).refcount - grpc_static_metadata_refcounts))
+
+#define GRPC_STATIC_MDELEM_COUNT 80
+extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
 extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
-/* "accept-charset": "" */
-#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY (&grpc_static_mdelem_table[0])
-/* "accept": "" */
-#define GRPC_MDELEM_ACCEPT_EMPTY (&grpc_static_mdelem_table[1])
-/* "accept-encoding": "" */
-#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY (&grpc_static_mdelem_table[2])
-/* "accept-encoding": "gzip, deflate" */
-#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \
-  (&grpc_static_mdelem_table[3])
-/* "accept-language": "" */
-#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY (&grpc_static_mdelem_table[4])
-/* "accept-ranges": "" */
-#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY (&grpc_static_mdelem_table[5])
-/* "access-control-allow-origin": "" */
-#define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \
-  (&grpc_static_mdelem_table[6])
-/* "age": "" */
-#define GRPC_MDELEM_AGE_EMPTY (&grpc_static_mdelem_table[7])
-/* "allow": "" */
-#define GRPC_MDELEM_ALLOW_EMPTY (&grpc_static_mdelem_table[8])
-/* ":authority": "" */
-#define GRPC_MDELEM_AUTHORITY_EMPTY (&grpc_static_mdelem_table[9])
-/* "authorization": "" */
-#define GRPC_MDELEM_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[10])
-/* "cache-control": "" */
-#define GRPC_MDELEM_CACHE_CONTROL_EMPTY (&grpc_static_mdelem_table[11])
-/* "content-disposition": "" */
-#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY (&grpc_static_mdelem_table[12])
-/* "content-encoding": "" */
-#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY (&grpc_static_mdelem_table[13])
-/* "content-language": "" */
-#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY (&grpc_static_mdelem_table[14])
-/* "content-length": "" */
-#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY (&grpc_static_mdelem_table[15])
-/* "content-location": "" */
-#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY (&grpc_static_mdelem_table[16])
-/* "content-range": "" */
-#define GRPC_MDELEM_CONTENT_RANGE_EMPTY (&grpc_static_mdelem_table[17])
+/* "grpc-status": "0" */
+#define GRPC_MDELEM_GRPC_STATUS_0 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[0], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-status": "1" */
+#define GRPC_MDELEM_GRPC_STATUS_1 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[1], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-status": "2" */
+#define GRPC_MDELEM_GRPC_STATUS_2 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[2], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-encoding": "identity" */
+#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[3], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-encoding": "gzip" */
+#define GRPC_MDELEM_GRPC_ENCODING_GZIP \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[4], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-encoding": "deflate" */
+#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[5], GRPC_MDELEM_STORAGE_STATIC))
+/* "te": "trailers" */
+#define GRPC_MDELEM_TE_TRAILERS \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[6], GRPC_MDELEM_STORAGE_STATIC))
 /* "content-type": "application/grpc" */
 #define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \
-  (&grpc_static_mdelem_table[18])
-/* "content-type": "" */
-#define GRPC_MDELEM_CONTENT_TYPE_EMPTY (&grpc_static_mdelem_table[19])
-/* "cookie": "" */
-#define GRPC_MDELEM_COOKIE_EMPTY (&grpc_static_mdelem_table[20])
-/* "date": "" */
-#define GRPC_MDELEM_DATE_EMPTY (&grpc_static_mdelem_table[21])
-/* "etag": "" */
-#define GRPC_MDELEM_ETAG_EMPTY (&grpc_static_mdelem_table[22])
-/* "expect": "" */
-#define GRPC_MDELEM_EXPECT_EMPTY (&grpc_static_mdelem_table[23])
-/* "expires": "" */
-#define GRPC_MDELEM_EXPIRES_EMPTY (&grpc_static_mdelem_table[24])
-/* "from": "" */
-#define GRPC_MDELEM_FROM_EMPTY (&grpc_static_mdelem_table[25])
-/* "grpc-accept-encoding": "deflate" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE (&grpc_static_mdelem_table[26])
-/* "grpc-accept-encoding": "deflate,gzip" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
-  (&grpc_static_mdelem_table[27])
-/* "grpc-accept-encoding": "gzip" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP (&grpc_static_mdelem_table[28])
-/* "grpc-accept-encoding": "identity" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
-  (&grpc_static_mdelem_table[29])
-/* "grpc-accept-encoding": "identity,deflate" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
-  (&grpc_static_mdelem_table[30])
-/* "grpc-accept-encoding": "identity,deflate,gzip" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
-  (&grpc_static_mdelem_table[31])
-/* "grpc-accept-encoding": "identity,gzip" */
-#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
-  (&grpc_static_mdelem_table[32])
-/* "grpc-encoding": "deflate" */
-#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE (&grpc_static_mdelem_table[33])
-/* "grpc-encoding": "gzip" */
-#define GRPC_MDELEM_GRPC_ENCODING_GZIP (&grpc_static_mdelem_table[34])
-/* "grpc-encoding": "identity" */
-#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY (&grpc_static_mdelem_table[35])
-/* "grpc-status": "0" */
-#define GRPC_MDELEM_GRPC_STATUS_0 (&grpc_static_mdelem_table[36])
-/* "grpc-status": "1" */
-#define GRPC_MDELEM_GRPC_STATUS_1 (&grpc_static_mdelem_table[37])
-/* "grpc-status": "2" */
-#define GRPC_MDELEM_GRPC_STATUS_2 (&grpc_static_mdelem_table[38])
-/* "host": "" */
-#define GRPC_MDELEM_HOST_EMPTY (&grpc_static_mdelem_table[39])
-/* "if-match": "" */
-#define GRPC_MDELEM_IF_MATCH_EMPTY (&grpc_static_mdelem_table[40])
-/* "if-modified-since": "" */
-#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[41])
-/* "if-none-match": "" */
-#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY (&grpc_static_mdelem_table[42])
-/* "if-range": "" */
-#define GRPC_MDELEM_IF_RANGE_EMPTY (&grpc_static_mdelem_table[43])
-/* "if-unmodified-since": "" */
-#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[44])
-/* "last-modified": "" */
-#define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[45])
-/* "lb-cost-bin": "" */
-#define GRPC_MDELEM_LB_COST_BIN_EMPTY (&grpc_static_mdelem_table[46])
-/* "lb-token": "" */
-#define GRPC_MDELEM_LB_TOKEN_EMPTY (&grpc_static_mdelem_table[47])
-/* "link": "" */
-#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[48])
-/* "location": "" */
-#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[49])
-/* "max-forwards": "" */
-#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[50])
-/* ":method": "GET" */
-#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[51])
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[7], GRPC_MDELEM_STORAGE_STATIC))
 /* ":method": "POST" */
-#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[52])
-/* ":method": "PUT" */
-#define GRPC_MDELEM_METHOD_PUT (&grpc_static_mdelem_table[53])
-/* ":path": "/" */
-#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[54])
-/* ":path": "/index.html" */
-#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[55])
-/* "proxy-authenticate": "" */
-#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[56])
-/* "proxy-authorization": "" */
-#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[57])
-/* "range": "" */
-#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[58])
-/* "referer": "" */
-#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[59])
-/* "refresh": "" */
-#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[60])
-/* "retry-after": "" */
-#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[61])
-/* ":scheme": "grpc" */
-#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[62])
-/* ":scheme": "http" */
-#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[63])
-/* ":scheme": "https" */
-#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[64])
-/* "server": "" */
-#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[65])
-/* "set-cookie": "" */
-#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[66])
+#define GRPC_MDELEM_METHOD_POST \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[8], GRPC_MDELEM_STORAGE_STATIC))
 /* ":status": "200" */
-#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[67])
-/* ":status": "204" */
-#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[68])
-/* ":status": "206" */
-#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[69])
-/* ":status": "304" */
-#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[70])
-/* ":status": "400" */
-#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[71])
+#define GRPC_MDELEM_STATUS_200 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[9], GRPC_MDELEM_STORAGE_STATIC))
 /* ":status": "404" */
-#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[72])
+#define GRPC_MDELEM_STATUS_404 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[10], GRPC_MDELEM_STORAGE_STATIC))
+/* ":scheme": "http" */
+#define GRPC_MDELEM_SCHEME_HTTP \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[11], GRPC_MDELEM_STORAGE_STATIC))
+/* ":scheme": "https" */
+#define GRPC_MDELEM_SCHEME_HTTPS \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[12], GRPC_MDELEM_STORAGE_STATIC))
+/* ":scheme": "grpc" */
+#define GRPC_MDELEM_SCHEME_GRPC \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[13], GRPC_MDELEM_STORAGE_STATIC))
+/* ":authority": "" */
+#define GRPC_MDELEM_AUTHORITY_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[14], GRPC_MDELEM_STORAGE_STATIC))
+/* ":method": "GET" */
+#define GRPC_MDELEM_METHOD_GET \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[15], GRPC_MDELEM_STORAGE_STATIC))
+/* ":method": "PUT" */
+#define GRPC_MDELEM_METHOD_PUT \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[16], GRPC_MDELEM_STORAGE_STATIC))
+/* ":path": "/" */
+#define GRPC_MDELEM_PATH_SLASH \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[17], GRPC_MDELEM_STORAGE_STATIC))
+/* ":path": "/index.html" */
+#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[18], GRPC_MDELEM_STORAGE_STATIC))
+/* ":status": "204" */
+#define GRPC_MDELEM_STATUS_204 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[19], GRPC_MDELEM_STORAGE_STATIC))
+/* ":status": "206" */
+#define GRPC_MDELEM_STATUS_206 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[20], GRPC_MDELEM_STORAGE_STATIC))
+/* ":status": "304" */
+#define GRPC_MDELEM_STATUS_304 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[21], GRPC_MDELEM_STORAGE_STATIC))
+/* ":status": "400" */
+#define GRPC_MDELEM_STATUS_400 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[22], GRPC_MDELEM_STORAGE_STATIC))
 /* ":status": "500" */
-#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[73])
+#define GRPC_MDELEM_STATUS_500 \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[23], GRPC_MDELEM_STORAGE_STATIC))
+/* "accept-charset": "" */
+#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[24], GRPC_MDELEM_STORAGE_STATIC))
+/* "accept-encoding": "" */
+#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[25], GRPC_MDELEM_STORAGE_STATIC))
+/* "accept-encoding": "gzip, deflate" */
+#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[26], GRPC_MDELEM_STORAGE_STATIC))
+/* "accept-language": "" */
+#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[27], GRPC_MDELEM_STORAGE_STATIC))
+/* "accept-ranges": "" */
+#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[28], GRPC_MDELEM_STORAGE_STATIC))
+/* "accept": "" */
+#define GRPC_MDELEM_ACCEPT_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[29], GRPC_MDELEM_STORAGE_STATIC))
+/* "access-control-allow-origin": "" */
+#define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[30], GRPC_MDELEM_STORAGE_STATIC))
+/* "age": "" */
+#define GRPC_MDELEM_AGE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[31], GRPC_MDELEM_STORAGE_STATIC))
+/* "allow": "" */
+#define GRPC_MDELEM_ALLOW_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[32], GRPC_MDELEM_STORAGE_STATIC))
+/* "authorization": "" */
+#define GRPC_MDELEM_AUTHORIZATION_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[33], GRPC_MDELEM_STORAGE_STATIC))
+/* "cache-control": "" */
+#define GRPC_MDELEM_CACHE_CONTROL_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[34], GRPC_MDELEM_STORAGE_STATIC))
+/* "content-disposition": "" */
+#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[35], GRPC_MDELEM_STORAGE_STATIC))
+/* "content-encoding": "" */
+#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[36], GRPC_MDELEM_STORAGE_STATIC))
+/* "content-language": "" */
+#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[37], GRPC_MDELEM_STORAGE_STATIC))
+/* "content-length": "" */
+#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[38], GRPC_MDELEM_STORAGE_STATIC))
+/* "content-location": "" */
+#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[39], GRPC_MDELEM_STORAGE_STATIC))
+/* "content-range": "" */
+#define GRPC_MDELEM_CONTENT_RANGE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[40], GRPC_MDELEM_STORAGE_STATIC))
+/* "content-type": "" */
+#define GRPC_MDELEM_CONTENT_TYPE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[41], GRPC_MDELEM_STORAGE_STATIC))
+/* "cookie": "" */
+#define GRPC_MDELEM_COOKIE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[42], GRPC_MDELEM_STORAGE_STATIC))
+/* "date": "" */
+#define GRPC_MDELEM_DATE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[43], GRPC_MDELEM_STORAGE_STATIC))
+/* "etag": "" */
+#define GRPC_MDELEM_ETAG_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[44], GRPC_MDELEM_STORAGE_STATIC))
+/* "expect": "" */
+#define GRPC_MDELEM_EXPECT_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[45], GRPC_MDELEM_STORAGE_STATIC))
+/* "expires": "" */
+#define GRPC_MDELEM_EXPIRES_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[46], GRPC_MDELEM_STORAGE_STATIC))
+/* "from": "" */
+#define GRPC_MDELEM_FROM_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[47], GRPC_MDELEM_STORAGE_STATIC))
+/* "host": "" */
+#define GRPC_MDELEM_HOST_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[48], GRPC_MDELEM_STORAGE_STATIC))
+/* "if-match": "" */
+#define GRPC_MDELEM_IF_MATCH_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[49], GRPC_MDELEM_STORAGE_STATIC))
+/* "if-modified-since": "" */
+#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[50], GRPC_MDELEM_STORAGE_STATIC))
+/* "if-none-match": "" */
+#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[51], GRPC_MDELEM_STORAGE_STATIC))
+/* "if-range": "" */
+#define GRPC_MDELEM_IF_RANGE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[52], GRPC_MDELEM_STORAGE_STATIC))
+/* "if-unmodified-since": "" */
+#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[53], GRPC_MDELEM_STORAGE_STATIC))
+/* "last-modified": "" */
+#define GRPC_MDELEM_LAST_MODIFIED_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[54], GRPC_MDELEM_STORAGE_STATIC))
+/* "lb-token": "" */
+#define GRPC_MDELEM_LB_TOKEN_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC))
+/* "link": "" */
+#define GRPC_MDELEM_LINK_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC))
+/* "location": "" */
+#define GRPC_MDELEM_LOCATION_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC))
+/* "max-forwards": "" */
+#define GRPC_MDELEM_MAX_FORWARDS_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC))
+/* "proxy-authenticate": "" */
+#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC))
+/* "proxy-authorization": "" */
+#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC))
+/* "range": "" */
+#define GRPC_MDELEM_RANGE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC))
+/* "referer": "" */
+#define GRPC_MDELEM_REFERER_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC))
+/* "refresh": "" */
+#define GRPC_MDELEM_REFRESH_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC))
+/* "retry-after": "" */
+#define GRPC_MDELEM_RETRY_AFTER_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC))
+/* "server": "" */
+#define GRPC_MDELEM_SERVER_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC))
+/* "set-cookie": "" */
+#define GRPC_MDELEM_SET_COOKIE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC))
 /* "strict-transport-security": "" */
 #define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \
-  (&grpc_static_mdelem_table[74])
-/* "te": "trailers" */
-#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[75])
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC))
 /* "transfer-encoding": "" */
-#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[76])
+#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC))
 /* "user-agent": "" */
-#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[77])
+#define GRPC_MDELEM_USER_AGENT_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC))
 /* "vary": "" */
-#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[78])
+#define GRPC_MDELEM_VARY_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC))
 /* "via": "" */
-#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[79])
+#define GRPC_MDELEM_VIA_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC))
 /* "www-authenticate": "" */
-#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[80])
+#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-accept-encoding": "identity" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-accept-encoding": "deflate" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-accept-encoding": "identity,deflate" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-accept-encoding": "gzip" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[76], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-accept-encoding": "identity,gzip" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[77], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-accept-encoding": "deflate,gzip" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[78], GRPC_MDELEM_STORAGE_STATIC))
+/* "grpc-accept-encoding": "identity,deflate,gzip" */
+#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
+  (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[79], GRPC_MDELEM_STORAGE_STATIC))
 
-extern const uint8_t
-    grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2];
-extern const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT];
+grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b);
+typedef enum {
+  GRPC_BATCH_PATH,
+  GRPC_BATCH_METHOD,
+  GRPC_BATCH_STATUS,
+  GRPC_BATCH_AUTHORITY,
+  GRPC_BATCH_SCHEME,
+  GRPC_BATCH_TE,
+  GRPC_BATCH_GRPC_MESSAGE,
+  GRPC_BATCH_GRPC_STATUS,
+  GRPC_BATCH_GRPC_PAYLOAD_BIN,
+  GRPC_BATCH_GRPC_ENCODING,
+  GRPC_BATCH_GRPC_ACCEPT_ENCODING,
+  GRPC_BATCH_CONTENT_TYPE,
+  GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST,
+  GRPC_BATCH_USER_AGENT,
+  GRPC_BATCH_HOST,
+  GRPC_BATCH_LB_TOKEN,
+  GRPC_BATCH_CALLOUTS_COUNT
+} grpc_metadata_batch_callouts_index;
+
+typedef union {
+  struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT];
+  struct {
+    struct grpc_linked_mdelem *path;
+    struct grpc_linked_mdelem *method;
+    struct grpc_linked_mdelem *status;
+    struct grpc_linked_mdelem *authority;
+    struct grpc_linked_mdelem *scheme;
+    struct grpc_linked_mdelem *te;
+    struct grpc_linked_mdelem *grpc_message;
+    struct grpc_linked_mdelem *grpc_status;
+    struct grpc_linked_mdelem *grpc_payload_bin;
+    struct grpc_linked_mdelem *grpc_encoding;
+    struct grpc_linked_mdelem *grpc_accept_encoding;
+    struct grpc_linked_mdelem *content_type;
+    struct grpc_linked_mdelem *grpc_internal_encoding_request;
+    struct grpc_linked_mdelem *user_agent;
+    struct grpc_linked_mdelem *host;
+    struct grpc_linked_mdelem *lb_token;
+  } named;
+} grpc_metadata_batch_callouts;
+
+#define GRPC_BATCH_INDEX_OF(slice)                      \
+  (GRPC_IS_STATIC_METADATA_STRING((slice))              \
+       ? (grpc_metadata_batch_callouts_index)GPR_CLAMP( \
+             GRPC_STATIC_METADATA_INDEX((slice)), 0,    \
+             GRPC_BATCH_CALLOUTS_COUNT)                 \
+       : GRPC_BATCH_CALLOUTS_COUNT)
+
 extern const uint8_t grpc_static_accept_encoding_metadata[8];
-#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \
-  (&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]])
+#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs)                       \
+  (GRPC_MAKE_MDELEM(                                                           \
+      &grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]], \
+      GRPC_MDELEM_STORAGE_STATIC))
 #endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */
diff --git a/src/core/lib/transport/status_conversion.c b/src/core/lib/transport/status_conversion.c
new file mode 100644
index 0000000..af0ac89
--- /dev/null
+++ b/src/core/lib/transport/status_conversion.c
@@ -0,0 +1,113 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/transport/status_conversion.h"
+
+int grpc_status_to_http2_error(grpc_status_code status) {
+  switch (status) {
+    case GRPC_STATUS_OK:
+      return GRPC_HTTP2_NO_ERROR;
+    case GRPC_STATUS_CANCELLED:
+      return GRPC_HTTP2_CANCEL;
+    case GRPC_STATUS_DEADLINE_EXCEEDED:
+      return GRPC_HTTP2_CANCEL;
+    case GRPC_STATUS_RESOURCE_EXHAUSTED:
+      return GRPC_HTTP2_ENHANCE_YOUR_CALM;
+    case GRPC_STATUS_PERMISSION_DENIED:
+      return GRPC_HTTP2_INADEQUATE_SECURITY;
+    case GRPC_STATUS_UNAVAILABLE:
+      return GRPC_HTTP2_REFUSED_STREAM;
+    default:
+      return GRPC_HTTP2_INTERNAL_ERROR;
+  }
+}
+
+grpc_status_code grpc_http2_error_to_grpc_status(grpc_http2_error_code error,
+                                                 gpr_timespec deadline) {
+  switch (error) {
+    case GRPC_HTTP2_NO_ERROR:
+      /* should never be received */
+      return GRPC_STATUS_INTERNAL;
+    case GRPC_HTTP2_CANCEL:
+      /* http2 cancel translates to STATUS_CANCELLED iff deadline hasn't been
+       * exceeded */
+      return gpr_time_cmp(gpr_now(deadline.clock_type), deadline) >= 0
+                 ? GRPC_STATUS_DEADLINE_EXCEEDED
+                 : GRPC_STATUS_CANCELLED;
+    case GRPC_HTTP2_ENHANCE_YOUR_CALM:
+      return GRPC_STATUS_RESOURCE_EXHAUSTED;
+    case GRPC_HTTP2_INADEQUATE_SECURITY:
+      return GRPC_STATUS_PERMISSION_DENIED;
+    case GRPC_HTTP2_REFUSED_STREAM:
+      return GRPC_STATUS_UNAVAILABLE;
+    default:
+      return GRPC_STATUS_INTERNAL;
+  }
+}
+
+grpc_status_code grpc_http2_status_to_grpc_status(int status) {
+  switch (status) {
+    /* these HTTP2 status codes are called out explicitly in status.proto */
+    case 200:
+      return GRPC_STATUS_OK;
+    case 400:
+      return GRPC_STATUS_INVALID_ARGUMENT;
+    case 401:
+      return GRPC_STATUS_UNAUTHENTICATED;
+    case 403:
+      return GRPC_STATUS_PERMISSION_DENIED;
+    case 404:
+      return GRPC_STATUS_NOT_FOUND;
+    case 409:
+      return GRPC_STATUS_ABORTED;
+    case 412:
+      return GRPC_STATUS_FAILED_PRECONDITION;
+    case 429:
+      return GRPC_STATUS_RESOURCE_EXHAUSTED;
+    case 499:
+      return GRPC_STATUS_CANCELLED;
+    case 500:
+      return GRPC_STATUS_UNKNOWN;
+    case 501:
+      return GRPC_STATUS_UNIMPLEMENTED;
+    case 503:
+      return GRPC_STATUS_UNAVAILABLE;
+    case 504:
+      return GRPC_STATUS_DEADLINE_EXCEEDED;
+    /* everything else is unknown */
+    default:
+      return GRPC_STATUS_UNKNOWN;
+  }
+}
+
+int grpc_status_to_http2_status(grpc_status_code status) { return 200; }
diff --git a/src/core/lib/transport/status_conversion.h b/src/core/lib/transport/status_conversion.h
new file mode 100644
index 0000000..e6a23a6
--- /dev/null
+++ b/src/core/lib/transport/status_conversion.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H
+#define GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H
+
+#include <grpc/grpc.h>
+#include "src/core/lib/transport/http2_errors.h"
+
+/* Conversion of grpc status codes to http2 error codes (for RST_STREAM) */
+grpc_http2_error_code grpc_status_to_http2_error(grpc_status_code status);
+grpc_status_code grpc_http2_error_to_grpc_status(grpc_http2_error_code error,
+                                                 gpr_timespec deadline);
+
+/* Conversion of HTTP status codes (:status) to grpc status codes */
+grpc_status_code grpc_http2_status_to_grpc_status(int status);
+int grpc_status_to_http2_status(grpc_status_code status);
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H */
diff --git a/src/core/lib/transport/timeout_encoding.c b/src/core/lib/transport/timeout_encoding.c
index b58ebbd..0d4d7e5 100644
--- a/src/core/lib/transport/timeout_encoding.c
+++ b/src/core/lib/transport/timeout_encoding.c
@@ -131,20 +131,21 @@
   }
 }
 
-static int is_all_whitespace(const char *p) {
-  while (*p == ' ') p++;
-  return *p == 0;
+static int is_all_whitespace(const char *p, const char *end) {
+  while (p != end && *p == ' ') p++;
+  return p == end;
 }
 
-int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout) {
+int grpc_http2_decode_timeout(grpc_slice text, gpr_timespec *timeout) {
   int32_t x = 0;
-  const uint8_t *p = (const uint8_t *)buffer;
+  const uint8_t *p = GRPC_SLICE_START_PTR(text);
+  const uint8_t *end = GRPC_SLICE_END_PTR(text);
   int have_digit = 0;
   /* skip whitespace */
-  for (; *p == ' '; p++)
+  for (; p != end && *p == ' '; p++)
     ;
   /* decode numeric part */
-  for (; *p >= '0' && *p <= '9'; p++) {
+  for (; p != end && *p >= '0' && *p <= '9'; p++) {
     int32_t digit = (int32_t)(*p - (uint8_t)'0');
     have_digit = 1;
     /* spec allows max. 8 digits, but we allow values up to 1,000,000,000 */
@@ -158,8 +159,9 @@
   }
   if (!have_digit) return 0;
   /* skip whitespace */
-  for (; *p == ' '; p++)
+  for (; p != end && *p == ' '; p++)
     ;
+  if (p == end) return 0;
   /* decode unit specifier */
   switch (*p) {
     case 'n':
@@ -184,5 +186,5 @@
       return 0;
   }
   p++;
-  return is_all_whitespace((const char *)p);
+  return is_all_whitespace((const char *)p, (const char *)end);
 }
diff --git a/src/core/lib/transport/timeout_encoding.h b/src/core/lib/transport/timeout_encoding.h
index 92f02f6..4c8025d 100644
--- a/src/core/lib/transport/timeout_encoding.h
+++ b/src/core/lib/transport/timeout_encoding.h
@@ -34,7 +34,9 @@
 #ifndef GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H
 #define GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H
 
+#include <grpc/slice.h>
 #include <grpc/support/time.h>
+
 #include "src/core/lib/support/string.h"
 
 #define GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1)
@@ -42,6 +44,6 @@
 /* Encode/decode timeouts to the GRPC over HTTP/2 format;
    encoding may round up arbitrarily */
 void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer);
-int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout);
+int grpc_http2_decode_timeout(grpc_slice text, gpr_timespec *timeout);
 
 #endif /* GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H */
diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c
index 055edbb..004e748 100644
--- a/src/core/lib/transport/transport.c
+++ b/src/core/lib/transport/transport.c
@@ -40,6 +40,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 
+#include "src/core/lib/iomgr/executor.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 #include "src/core/lib/support/string.h"
@@ -69,6 +70,16 @@
                        grpc_stream_refcount *refcount) {
 #endif
   if (gpr_unref(&refcount->refs)) {
+    if (exec_ctx->flags & GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP) {
+      /* Ick.
+         The thread we're running on MAY be owned (indirectly) by a call-stack.
+         If that's the case, destroying the call-stack MAY try to destroy the
+         thread, which is a tangled mess that we just don't want to ever have to
+         cope with.
+         Throw this over to the executor (on a core-owned thread) and process it
+         there. */
+      refcount->destroy.scheduler = grpc_executor_scheduler;
+    }
     grpc_closure_sched(exec_ctx, &refcount->destroy, GRPC_ERROR_NONE);
   }
 }
@@ -173,93 +184,7 @@
   grpc_closure_sched(exec_ctx, op->recv_initial_metadata_ready,
                      GRPC_ERROR_REF(error));
   grpc_closure_sched(exec_ctx, op->on_complete, error);
-}
-
-typedef struct {
-  grpc_error *error;
-  grpc_closure *then_call;
-  grpc_closure closure;
-} close_message_data;
-
-static void free_message(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) {
-  close_message_data *cmd = p;
-  GRPC_ERROR_UNREF(cmd->error);
-  if (cmd->then_call != NULL) {
-    cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, error);
-  }
-  gpr_free(cmd);
-}
-
-static void add_error(grpc_transport_stream_op *op, grpc_error **which,
-                      grpc_error *error) {
-  close_message_data *cmd;
-  cmd = gpr_malloc(sizeof(*cmd));
-  cmd->error = error;
-  cmd->then_call = op->on_complete;
-  grpc_closure_init(&cmd->closure, free_message, cmd,
-                    grpc_schedule_on_exec_ctx);
-  op->on_complete = &cmd->closure;
-  *which = error;
-}
-
-void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
-                                               grpc_status_code status) {
-  GPR_ASSERT(status != GRPC_STATUS_OK);
-  if (op->cancel_error == GRPC_ERROR_NONE) {
-    op->cancel_error = grpc_error_set_int(GRPC_ERROR_CANCELLED,
-                                          GRPC_ERROR_INT_GRPC_STATUS, status);
-    op->close_error = GRPC_ERROR_NONE;
-  }
-}
-
-void grpc_transport_stream_op_add_cancellation_with_message(
-    grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op,
-    grpc_status_code status, grpc_slice *optional_message) {
-  GPR_ASSERT(status != GRPC_STATUS_OK);
-  if (op->cancel_error != GRPC_ERROR_NONE) {
-    if (optional_message) {
-      grpc_slice_unref_internal(exec_ctx, *optional_message);
-    }
-    return;
-  }
-  grpc_error *error;
-  if (optional_message != NULL) {
-    char *msg = grpc_dump_slice(*optional_message, GPR_DUMP_ASCII);
-    error = grpc_error_set_str(GRPC_ERROR_CREATE(msg),
-                               GRPC_ERROR_STR_GRPC_MESSAGE, msg);
-    gpr_free(msg);
-    grpc_slice_unref_internal(exec_ctx, *optional_message);
-  } else {
-    error = GRPC_ERROR_CREATE("Call cancelled");
-  }
-  error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status);
-  add_error(op, &op->cancel_error, error);
-}
-
-void grpc_transport_stream_op_add_close(grpc_exec_ctx *exec_ctx,
-                                        grpc_transport_stream_op *op,
-                                        grpc_status_code status,
-                                        grpc_slice *optional_message) {
-  GPR_ASSERT(status != GRPC_STATUS_OK);
-  if (op->cancel_error != GRPC_ERROR_NONE ||
-      op->close_error != GRPC_ERROR_NONE) {
-    if (optional_message) {
-      grpc_slice_unref_internal(exec_ctx, *optional_message);
-    }
-    return;
-  }
-  grpc_error *error;
-  if (optional_message != NULL) {
-    char *msg = grpc_dump_slice(*optional_message, GPR_DUMP_ASCII);
-    error = grpc_error_set_str(GRPC_ERROR_CREATE(msg),
-                               GRPC_ERROR_STR_GRPC_MESSAGE, msg);
-    gpr_free(msg);
-    grpc_slice_unref_internal(exec_ctx, *optional_message);
-  } else {
-    error = GRPC_ERROR_CREATE("Call force closed");
-  }
-  error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status);
-  add_error(op, &op->close_error, error);
+  GRPC_ERROR_UNREF(op->cancel_error);
 }
 
 typedef struct {
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index d128183..bb23c02 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -150,21 +150,26 @@
   /** Collect any stats into provided buffer, zero internal stat counters */
   grpc_transport_stream_stats *collect_stats;
 
-  /** If != GRPC_ERROR_NONE, cancel this stream */
+  /** If != GRPC_ERROR_NONE, forcefully close this stream.
+      The HTTP2 semantics should be:
+      - server side: if cancel_error has GRPC_ERROR_INT_GRPC_STATUS, and
+        trailing metadata has not been sent, send trailing metadata with status
+        and message from cancel_error (use grpc_error_get_status) followed by
+        a RST_STREAM with error=GRPC_CHTTP2_NO_ERROR to force a full close
+      - at all other times: use grpc_error_get_status to get a status code, and
+        convert to a HTTP2 error code using
+        grpc_chttp2_grpc_status_to_http2_error. Send a RST_STREAM with this
+        error. */
   grpc_error *cancel_error;
 
-  /** If != GRPC_ERROR_NONE, send grpc-status, grpc-message, and close this
-      stream for both reading and writing */
-  grpc_error *close_error;
-
   /* Indexes correspond to grpc_context_index enum values */
   grpc_call_context_element *context;
 
   /***************************************************************************
    * remaining fields are initialized and used at the discretion of the
-   * transport implementation */
+   * current handler of the op */
 
-  grpc_transport_private_op_data transport_private;
+  grpc_transport_private_op_data handler_private;
 } grpc_transport_stream_op;
 
 /** Transport op: a set of operations to perform on a transport as a whole */
@@ -176,13 +181,8 @@
   grpc_connectivity_state *connectivity_state;
   /** should the transport be disconnected */
   grpc_error *disconnect_with_error;
-  /** should we send a goaway?
-      after a goaway is sent, once there are no more active calls on
-      the transport, the transport should disconnect */
-  bool send_goaway;
   /** what should the goaway contain? */
-  grpc_status_code goaway_status;
-  grpc_slice *goaway_message;
+  grpc_error *goaway_error;
   /** set the callback for accepting new streams;
       this is a permanent callback, unlike the other one-shot closures.
       If true, the callback is set to set_accept_stream_fn, with its
@@ -213,6 +213,7 @@
 /* Initialize transport data for a stream.
 
    Returns 0 on success, any other (transport-defined) value for failure.
+   May assume that stream contains all-zeros.
 
    Arguments:
      transport   - the transport on which to create this stream
@@ -245,18 +246,6 @@
                                                   grpc_transport_stream_op *op,
                                                   grpc_error *error);
 
-void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
-                                               grpc_status_code status);
-
-void grpc_transport_stream_op_add_cancellation_with_message(
-    grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op,
-    grpc_status_code status, grpc_slice *optional_message);
-
-void grpc_transport_stream_op_add_close(grpc_exec_ctx *exec_ctx,
-                                        grpc_transport_stream_op *op,
-                                        grpc_status_code status,
-                                        grpc_slice *optional_message);
-
 char *grpc_transport_stream_op_string(grpc_transport_stream_op *op);
 char *grpc_transport_op_string(grpc_transport_op *op);
 
diff --git a/src/core/lib/transport/transport_op_string.c b/src/core/lib/transport/transport_op_string.c
index 58d6ad5..28360e3 100644
--- a/src/core/lib/transport/transport_op_string.c
+++ b/src/core/lib/transport/transport_op_string.c
@@ -47,14 +47,14 @@
 /* These routines are here to facilitate debugging - they produce string
    representations of various transport data structures */
 
-static void put_metadata(gpr_strvec *b, grpc_mdelem *md) {
+static void put_metadata(gpr_strvec *b, grpc_mdelem md) {
   gpr_strvec_add(b, gpr_strdup("key="));
   gpr_strvec_add(
-      b, grpc_dump_slice(md->key->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+      b, grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII));
 
   gpr_strvec_add(b, gpr_strdup(" value="));
   gpr_strvec_add(
-      b, grpc_dump_slice(md->value->slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
+      b, grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII));
 }
 
 static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) {
@@ -121,15 +121,7 @@
     gpr_strvec_add(&b, gpr_strdup(" "));
     const char *msg = grpc_error_string(op->cancel_error);
     gpr_asprintf(&tmp, "CANCEL:%s", msg);
-    grpc_error_free_string(msg);
-    gpr_strvec_add(&b, tmp);
-  }
 
-  if (op->close_error != GRPC_ERROR_NONE) {
-    gpr_strvec_add(&b, gpr_strdup(" "));
-    const char *msg = grpc_error_string(op->close_error);
-    gpr_asprintf(&tmp, "CLOSE:%s", msg);
-    grpc_error_free_string(msg);
     gpr_strvec_add(&b, tmp);
   }
 
@@ -168,18 +160,14 @@
     const char *err = grpc_error_string(op->disconnect_with_error);
     gpr_asprintf(&tmp, "DISCONNECT:%s", err);
     gpr_strvec_add(&b, tmp);
-    grpc_error_free_string(err);
   }
 
-  if (op->send_goaway) {
+  if (op->goaway_error) {
     if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
     first = false;
-    char *msg = op->goaway_message == NULL
-                    ? "null"
-                    : grpc_dump_slice(*op->goaway_message,
-                                      GPR_DUMP_ASCII | GPR_DUMP_HEX);
-    gpr_asprintf(&tmp, "SEND_GOAWAY:status=%d:msg=%s", op->goaway_status, msg);
-    if (op->goaway_message != NULL) gpr_free(msg);
+    const char *msg = grpc_error_string(op->goaway_error);
+    gpr_asprintf(&tmp, "SEND_GOAWAY:%s", msg);
+
     gpr_strvec_add(&b, tmp);
   }
 
diff --git a/src/core/lib/tsi/fake_transport_security.c b/src/core/lib/tsi/fake_transport_security.c
index 0e20d6f..bbe323d 100644
--- a/src/core/lib/tsi/fake_transport_security.c
+++ b/src/core/lib/tsi/fake_transport_security.c
@@ -502,8 +502,7 @@
 };
 
 tsi_handshaker *tsi_create_fake_handshaker(int is_client) {
-  tsi_fake_handshaker *impl = gpr_malloc(sizeof(*impl));
-  memset(impl, 0, sizeof(*impl));
+  tsi_fake_handshaker *impl = gpr_zalloc(sizeof(*impl));
   impl->base.vtable = &handshaker_vtable;
   impl->is_client = is_client;
   impl->result = TSI_HANDSHAKE_IN_PROGRESS;
@@ -519,8 +518,7 @@
 
 tsi_frame_protector *tsi_create_fake_protector(
     size_t *max_protected_frame_size) {
-  tsi_fake_frame_protector *impl = gpr_malloc(sizeof(*impl));
-  memset(impl, 0, sizeof(*impl));
+  tsi_fake_frame_protector *impl = gpr_zalloc(sizeof(*impl));
   impl->max_frame_size = (max_protected_frame_size == NULL)
                              ? TSI_FAKE_DEFAULT_FRAME_SIZE
                              : *max_protected_frame_size;
diff --git a/src/core/lib/tsi/ssl_transport_security.c b/src/core/lib/tsi/ssl_transport_security.c
index 366dca9..53aabdb 100644
--- a/src/core/lib/tsi/ssl_transport_security.c
+++ b/src/core/lib/tsi/ssl_transport_security.c
@@ -976,9 +976,7 @@
   if (alpn_selected != NULL) {
     size_t i;
     tsi_peer_property *new_properties =
-        gpr_malloc(sizeof(*new_properties) * (peer->property_count + 1));
-    memset(new_properties, 0,
-           sizeof(*new_properties) * (peer->property_count + 1));
+        gpr_zalloc(sizeof(*new_properties) * (peer->property_count + 1));
     for (i = 0; i < peer->property_count; i++) {
       new_properties[i] = peer->properties[i];
     }
@@ -1002,8 +1000,7 @@
   size_t actual_max_output_protected_frame_size =
       TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
-  tsi_ssl_frame_protector *protector_impl = gpr_malloc(sizeof(*protector_impl));
-  memset(protector_impl, 0, sizeof(*protector_impl));
+  tsi_ssl_frame_protector *protector_impl = gpr_zalloc(sizeof(*protector_impl));
 
   if (max_output_protected_frame_size != NULL) {
     if (*max_output_protected_frame_size >
@@ -1119,8 +1116,7 @@
     SSL_set_accept_state(ssl);
   }
 
-  impl = gpr_malloc(sizeof(*impl));
-  memset(impl, 0, sizeof(*impl));
+  impl = gpr_zalloc(sizeof(*impl));
   impl->ssl = ssl;
   impl->into_ssl = into_ssl;
   impl->from_ssl = from_ssl;
@@ -1338,8 +1334,7 @@
     return TSI_INVALID_ARGUMENT;
   }
 
-  impl = gpr_malloc(sizeof(*impl));
-  memset(impl, 0, sizeof(*impl));
+  impl = gpr_zalloc(sizeof(*impl));
   impl->ssl_context = ssl_context;
 
   do {
@@ -1433,17 +1428,13 @@
     return TSI_INVALID_ARGUMENT;
   }
 
-  impl = gpr_malloc(sizeof(*impl));
-  memset(impl, 0, sizeof(*impl));
+  impl = gpr_zalloc(sizeof(*impl));
   impl->base.create_handshaker =
       ssl_server_handshaker_factory_create_handshaker;
   impl->base.destroy = ssl_server_handshaker_factory_destroy;
-  impl->ssl_contexts = gpr_malloc(key_cert_pair_count * sizeof(SSL_CTX *));
-  memset(impl->ssl_contexts, 0, key_cert_pair_count * sizeof(SSL_CTX *));
+  impl->ssl_contexts = gpr_zalloc(key_cert_pair_count * sizeof(SSL_CTX *));
   impl->ssl_context_x509_subject_names =
-      gpr_malloc(key_cert_pair_count * sizeof(tsi_peer));
-  memset(impl->ssl_context_x509_subject_names, 0,
-         key_cert_pair_count * sizeof(tsi_peer));
+      gpr_zalloc(key_cert_pair_count * sizeof(tsi_peer));
   if (impl->ssl_contexts == NULL ||
       impl->ssl_context_x509_subject_names == NULL) {
     tsi_ssl_handshaker_factory_destroy(&impl->base);
diff --git a/src/core/lib/tsi/test_creds/BUILD b/src/core/lib/tsi/test_creds/BUILD
new file mode 100644
index 0000000..dcd6d93
--- /dev/null
+++ b/src/core/lib/tsi/test_creds/BUILD
@@ -0,0 +1,34 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+exports_files([
+    "ca.pem",
+    "server1.key",
+    "server1.pem",
+])
diff --git a/src/core/lib/tsi/transport_security.c b/src/core/lib/tsi/transport_security.c
index 830cf09..2cbf381 100644
--- a/src/core/lib/tsi/transport_security.c
+++ b/src/core/lib/tsi/transport_security.c
@@ -231,8 +231,7 @@
   *property = tsi_init_peer_property();
   if (name != NULL) property->name = gpr_strdup(name);
   if (value_length > 0) {
-    property->value.data = gpr_malloc(value_length);
-    memset(property->value.data, 0, value_length);
+    property->value.data = gpr_zalloc(value_length);
     property->value.length = value_length;
   }
   return TSI_OK;
@@ -260,8 +259,7 @@
 tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer) {
   memset(peer, 0, sizeof(tsi_peer));
   if (property_count > 0) {
-    peer->properties = gpr_malloc(property_count * sizeof(tsi_peer_property));
-    memset(peer->properties, 0, property_count * sizeof(tsi_peer_property));
+    peer->properties = gpr_zalloc(property_count * sizeof(tsi_peer_property));
     peer->property_count = property_count;
   }
   return TSI_OK;
diff --git a/src/core/plugin_registry/grpc_cronet_plugin_registry.c b/src/core/plugin_registry/grpc_cronet_plugin_registry.c
index d339ed3..c97f47b 100644
--- a/src/core/plugin_registry/grpc_cronet_plugin_registry.c
+++ b/src/core/plugin_registry/grpc_cronet_plugin_registry.c
@@ -37,10 +37,14 @@
 extern void grpc_chttp2_plugin_shutdown(void);
 extern void grpc_client_channel_init(void);
 extern void grpc_client_channel_shutdown(void);
+extern void grpc_load_reporting_plugin_init(void);
+extern void grpc_load_reporting_plugin_shutdown(void);
 
 void grpc_register_built_in_plugins(void) {
   grpc_register_plugin(grpc_chttp2_plugin_init,
                        grpc_chttp2_plugin_shutdown);
   grpc_register_plugin(grpc_client_channel_init,
                        grpc_client_channel_shutdown);
+  grpc_register_plugin(grpc_load_reporting_plugin_init,
+                       grpc_load_reporting_plugin_shutdown);
 }
diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc
index 357d831..c985183 100644
--- a/src/cpp/client/channel_cc.cc
+++ b/src/cpp/client/channel_cc.cc
@@ -107,10 +107,20 @@
     } else if (!host_.empty()) {
       host_str = host_.c_str();
     }
-    c_call = grpc_channel_create_call(c_channel_, context->propagate_from_call_,
-                                      context->propagation_options_.c_bitmask(),
-                                      cq->cq(), method.name(), host_str,
-                                      context->raw_deadline(), nullptr);
+    grpc_slice method_slice = SliceFromCopiedString(method.name());
+    grpc_slice host_slice;
+    if (host_str != nullptr) {
+      host_slice = SliceFromCopiedString(host_str);
+    }
+    c_call = grpc_channel_create_call(
+        c_channel_, context->propagate_from_call_,
+        context->propagation_options_.c_bitmask(), cq->cq(), method_slice,
+        host_str == nullptr ? nullptr : &host_slice, context->raw_deadline(),
+        nullptr);
+    grpc_slice_unref(method_slice);
+    if (host_str != nullptr) {
+      grpc_slice_unref(host_slice);
+    }
   }
   grpc_census_call_set_context(c_call, context->census_context());
   context->set_call(c_call, shared_from_this());
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 269c523..25f6bab 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -206,15 +206,18 @@
   std::vector<grpc_metadata> md;
   for (auto it = metadata.begin(); it != metadata.end(); ++it) {
     grpc_metadata md_entry;
-    md_entry.key = it->first.c_str();
-    md_entry.value = it->second.data();
-    md_entry.value_length = it->second.size();
+    md_entry.key = SliceFromCopiedString(it->first);
+    md_entry.value = SliceFromCopiedString(it->second);
     md_entry.flags = 0;
     md.push_back(md_entry);
   }
   cb(user_data, md.empty() ? nullptr : &md[0], md.size(),
      static_cast<grpc_status_code>(status.error_code()),
      status.error_message().c_str());
+  for (auto it = md.begin(); it != md.end(); ++it) {
+    grpc_slice_unref(it->key);
+    grpc_slice_unref(it->value);
+  }
 }
 
 MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index 281db17..713654a 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -70,7 +70,7 @@
   grpc_call_credentials* const c_creds_;
 };
 
-class MetadataCredentialsPluginWrapper final {
+class MetadataCredentialsPluginWrapper final : private GrpcLibraryCodegen {
  public:
   static void Destroy(void* wrapper);
   static void GetMetadata(void* wrapper, grpc_auth_metadata_context context,
diff --git a/src/cpp/common/channel_filter.cc b/src/cpp/common/channel_filter.cc
index c0dc9dd..253614c 100644
--- a/src/cpp/common/channel_filter.cc
+++ b/src/cpp/common/channel_filter.cc
@@ -36,6 +36,8 @@
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/cpp/common/channel_filter.h"
 
+#include <grpc++/impl/codegen/slice.h>
+
 namespace grpc {
 
 // MetadataBatch
@@ -45,8 +47,10 @@
                                                const string &value) {
   grpc_linked_mdelem *storage = new grpc_linked_mdelem;
   memset(storage, 0, sizeof(grpc_linked_mdelem));
-  storage->md = grpc_mdelem_from_strings(exec_ctx, key.c_str(), value.c_str());
-  grpc_metadata_batch_link_head(batch_, storage);
+  storage->md = grpc_mdelem_from_slices(exec_ctx, SliceFromCopiedString(key),
+                                        SliceFromCopiedString(value));
+  GRPC_LOG_IF_ERROR("MetadataBatch::AddMetadata",
+                    grpc_metadata_batch_link_head(exec_ctx, batch_, storage));
   return storage;
 }
 
diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h
index 5de8f5e..79c4bab 100644
--- a/src/cpp/common/channel_filter.h
+++ b/src/cpp/common/channel_filter.h
@@ -76,8 +76,8 @@
   class const_iterator : public std::iterator<std::bidirectional_iterator_tag,
                                               const grpc_mdelem> {
    public:
-    const grpc_mdelem &operator*() const { return *elem_->md; }
-    const grpc_mdelem *operator->() const { return elem_->md; }
+    const grpc_mdelem &operator*() const { return elem_->md; }
+    const grpc_mdelem operator->() const { return elem_->md; }
 
     const_iterator &operator++() {
       elem_ = elem_->next;
@@ -133,7 +133,7 @@
   grpc_error *disconnect_with_error() const {
     return op_->disconnect_with_error;
   }
-  bool send_goaway() const { return op_->send_goaway; }
+  bool send_goaway() const { return op_->goaway_error != GRPC_ERROR_NONE; }
 
   // TODO(roth): Add methods for additional fields as needed.
 
@@ -244,7 +244,7 @@
 
   /// Initializes the call data.
   virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, ChannelData *channel_data,
-                           grpc_call_element_args *args) {
+                           const grpc_call_element_args *args) {
     return GRPC_ERROR_NONE;
   }
 
@@ -308,7 +308,7 @@
 
   static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx,
                                      grpc_call_element *elem,
-                                     grpc_call_element_args *args) {
+                                     const grpc_call_element_args *args) {
     ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
     // Construct the object in the already-allocated memory.
     CallDataType *call_data = new (elem->call_data) CallDataType();
diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc
index a07ad54..36e4c89 100644
--- a/src/cpp/common/core_codegen.cc
+++ b/src/cpp/common/core_codegen.cc
@@ -123,6 +123,17 @@
   return ::grpc_slice_split_tail(s, split);
 }
 
+grpc_slice CoreCodegen::grpc_slice_from_static_buffer(const void* buffer,
+                                                      size_t length) {
+  return ::grpc_slice_from_static_buffer(buffer, length);
+}
+
+grpc_slice CoreCodegen::grpc_slice_from_copied_buffer(const void* buffer,
+                                                      size_t length) {
+  return ::grpc_slice_from_copied_buffer(static_cast<const char*>(buffer),
+                                         length);
+}
+
 void CoreCodegen::grpc_slice_buffer_add(grpc_slice_buffer* sb,
                                         grpc_slice slice) {
   ::grpc_slice_buffer_add(sb, slice);
@@ -152,8 +163,10 @@
   return ::gpr_time_0(type);
 }
 
-void CoreCodegen::assert_fail(const char* failed_assertion) {
-  gpr_log(GPR_ERROR, "assertion failed: %s", failed_assertion);
+void CoreCodegen::assert_fail(const char* failed_assertion, const char* file,
+                              int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "assertion failed: %s",
+          failed_assertion);
   abort();
 }
 
diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc
index fde4976..039c530 100644
--- a/src/cpp/common/version_cc.cc
+++ b/src/cpp/common/version_cc.cc
@@ -37,5 +37,5 @@
 #include <grpc++/grpc++.h>
 
 namespace grpc {
-grpc::string Version() { return "1.1.2"; }
+grpc::string Version() { return "1.2.0-dev"; }
 }
diff --git a/src/cpp/server/dynamic_thread_pool.cc b/src/cpp/server/dynamic_thread_pool.cc
index 1fdc2ed..afb5bea 100644
--- a/src/cpp/server/dynamic_thread_pool.cc
+++ b/src/cpp/server/dynamic_thread_pool.cc
@@ -31,12 +31,15 @@
  *
  */
 
+#include "src/cpp/server/dynamic_thread_pool.h"
+
 #include <mutex>
 #include <thread>
 
-#include "src/cpp/server/dynamic_thread_pool.h"
+#include <grpc/support/log.h>
 
 namespace grpc {
+
 DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool)
     : pool_(pool),
       thd_(new std::thread(&DynamicThreadPool::DynamicThread::ThreadFunc,
diff --git a/src/cpp/server/health/default_health_check_service.cc b/src/cpp/server/health/default_health_check_service.cc
new file mode 100644
index 0000000..46def70
--- /dev/null
+++ b/src/cpp/server/health/default_health_check_service.cc
@@ -0,0 +1,166 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <memory>
+#include <mutex>
+
+#include <grpc++/impl/codegen/method_handler_impl.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/cpp/server/health/default_health_check_service.h"
+#include "src/cpp/server/health/health.pb.h"
+#include "third_party/nanopb/pb_decode.h"
+#include "third_party/nanopb/pb_encode.h"
+
+namespace grpc {
+namespace {
+const char kHealthCheckMethodName[] = "/grpc.health.v1.Health/Check";
+}  // namespace
+
+DefaultHealthCheckService::HealthCheckServiceImpl::HealthCheckServiceImpl(
+    DefaultHealthCheckService* service)
+    : service_(service), method_(nullptr) {
+  MethodHandler* handler =
+      new RpcMethodHandler<HealthCheckServiceImpl, ByteBuffer, ByteBuffer>(
+          std::mem_fn(&HealthCheckServiceImpl::Check), this);
+  method_ = new RpcServiceMethod(kHealthCheckMethodName, RpcMethod::NORMAL_RPC,
+                                 handler);
+  AddMethod(method_);
+}
+
+Status DefaultHealthCheckService::HealthCheckServiceImpl::Check(
+    ServerContext* context, const ByteBuffer* request, ByteBuffer* response) {
+  // Decode request.
+  std::vector<Slice> slices;
+  request->Dump(&slices);
+  uint8_t* request_bytes = nullptr;
+  bool request_bytes_owned = false;
+  size_t request_size = 0;
+  grpc_health_v1_HealthCheckRequest request_struct;
+  if (slices.empty()) {
+    request_struct.has_service = false;
+  } else if (slices.size() == 1) {
+    request_bytes = const_cast<uint8_t*>(slices[0].begin());
+    request_size = slices[0].size();
+  } else {
+    request_bytes_owned = true;
+    request_bytes = static_cast<uint8_t*>(gpr_malloc(request->Length()));
+    uint8_t* copy_to = request_bytes;
+    for (size_t i = 0; i < slices.size(); i++) {
+      memcpy(copy_to, slices[i].begin(), slices[i].size());
+      copy_to += slices[i].size();
+    }
+  }
+
+  if (request_bytes != nullptr) {
+    pb_istream_t istream = pb_istream_from_buffer(request_bytes, request_size);
+    bool decode_status = pb_decode(
+        &istream, grpc_health_v1_HealthCheckRequest_fields, &request_struct);
+    if (request_bytes_owned) {
+      gpr_free(request_bytes);
+    }
+    if (!decode_status) {
+      return Status(StatusCode::INVALID_ARGUMENT, "");
+    }
+  }
+
+  // Check status from the associated default health checking service.
+  DefaultHealthCheckService::ServingStatus serving_status =
+      service_->GetServingStatus(
+          request_struct.has_service ? request_struct.service : "");
+  if (serving_status == DefaultHealthCheckService::NOT_FOUND) {
+    return Status(StatusCode::NOT_FOUND, "");
+  }
+
+  // Encode response
+  grpc_health_v1_HealthCheckResponse response_struct;
+  response_struct.has_status = true;
+  response_struct.status =
+      serving_status == DefaultHealthCheckService::SERVING
+          ? grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING
+          : grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING;
+  pb_ostream_t ostream;
+  memset(&ostream, 0, sizeof(ostream));
+  pb_encode(&ostream, grpc_health_v1_HealthCheckResponse_fields,
+            &response_struct);
+  grpc_slice response_slice = grpc_slice_malloc(ostream.bytes_written);
+  ostream = pb_ostream_from_buffer(GRPC_SLICE_START_PTR(response_slice),
+                                   GRPC_SLICE_LENGTH(response_slice));
+  bool encode_status = pb_encode(
+      &ostream, grpc_health_v1_HealthCheckResponse_fields, &response_struct);
+  if (!encode_status) {
+    return Status(StatusCode::INTERNAL, "Failed to encode response.");
+  }
+  Slice encoded_response(response_slice, Slice::STEAL_REF);
+  ByteBuffer response_buffer(&encoded_response, 1);
+  response->Swap(&response_buffer);
+  return Status::OK;
+}
+
+DefaultHealthCheckService::DefaultHealthCheckService() {
+  services_map_.emplace("", true);
+}
+
+void DefaultHealthCheckService::SetServingStatus(
+    const grpc::string& service_name, bool serving) {
+  std::lock_guard<std::mutex> lock(mu_);
+  services_map_[service_name] = serving;
+}
+
+void DefaultHealthCheckService::SetServingStatus(bool serving) {
+  std::lock_guard<std::mutex> lock(mu_);
+  for (auto iter = services_map_.begin(); iter != services_map_.end(); ++iter) {
+    iter->second = serving;
+  }
+}
+
+DefaultHealthCheckService::ServingStatus
+DefaultHealthCheckService::GetServingStatus(
+    const grpc::string& service_name) const {
+  std::lock_guard<std::mutex> lock(mu_);
+  const auto& iter = services_map_.find(service_name);
+  if (iter == services_map_.end()) {
+    return NOT_FOUND;
+  }
+  return iter->second ? SERVING : NOT_SERVING;
+}
+
+DefaultHealthCheckService::HealthCheckServiceImpl*
+DefaultHealthCheckService::GetHealthCheckService() {
+  GPR_ASSERT(impl_ == nullptr);
+  impl_.reset(new HealthCheckServiceImpl(this));
+  return impl_.get();
+}
+
+}  // namespace grpc
diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h
new file mode 100644
index 0000000..5c0e230
--- /dev/null
+++ b/src/cpp/server/health/default_health_check_service.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
+#define GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
+
+#include <mutex>
+
+#include <grpc++/health_check_service_interface.h>
+#include <grpc++/impl/codegen/service_type.h>
+#include <grpc++/support/byte_buffer.h>
+
+namespace grpc {
+
+// Default implementation of HealthCheckServiceInterface. Server will create and
+// own it.
+class DefaultHealthCheckService final : public HealthCheckServiceInterface {
+ public:
+  // The service impl to register with the server.
+  class HealthCheckServiceImpl : public Service {
+   public:
+    explicit HealthCheckServiceImpl(DefaultHealthCheckService* service);
+
+    Status Check(ServerContext* context, const ByteBuffer* request,
+                 ByteBuffer* response);
+
+   private:
+    const DefaultHealthCheckService* const service_;
+    RpcServiceMethod* method_;
+  };
+
+  DefaultHealthCheckService();
+  void SetServingStatus(const grpc::string& service_name,
+                        bool serving) override;
+  void SetServingStatus(bool serving) override;
+  enum ServingStatus { NOT_FOUND, SERVING, NOT_SERVING };
+  ServingStatus GetServingStatus(const grpc::string& service_name) const;
+  HealthCheckServiceImpl* GetHealthCheckService();
+
+ private:
+  mutable std::mutex mu_;
+  std::map<grpc::string, bool> services_map_;
+  std::unique_ptr<HealthCheckServiceImpl> impl_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
diff --git a/src/cpp/server/health/health.pb.c b/src/cpp/server/health/health.pb.c
new file mode 100644
index 0000000..09bd98a
--- /dev/null
+++ b/src/cpp/server/health/health.pb.c
@@ -0,0 +1,24 @@
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-0.3.7-dev */
+
+#include "src/cpp/server/health/health.pb.h"
+
+/* @@protoc_insertion_point(includes) */
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+
+
+const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_health_v1_HealthCheckRequest, service, service, 0),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2] = {
+    PB_FIELD(  1, UENUM   , OPTIONAL, STATIC  , FIRST, grpc_health_v1_HealthCheckResponse, status, status, 0),
+    PB_LAST_FIELD
+};
+
+
+/* @@protoc_insertion_point(eof) */
diff --git a/src/cpp/server/health/health.pb.h b/src/cpp/server/health/health.pb.h
new file mode 100644
index 0000000..7051b32
--- /dev/null
+++ b/src/cpp/server/health/health.pb.h
@@ -0,0 +1,72 @@
+/* Automatically generated nanopb header */
+/* Generated by nanopb-0.3.7-dev */
+
+#ifndef PB_GRPC_HEALTH_V1_HEALTH_PB_H_INCLUDED
+#define PB_GRPC_HEALTH_V1_HEALTH_PB_H_INCLUDED
+#include "third_party/nanopb/pb.h"
+/* @@protoc_insertion_point(includes) */
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enum definitions */
+typedef enum _grpc_health_v1_HealthCheckResponse_ServingStatus {
+    grpc_health_v1_HealthCheckResponse_ServingStatus_UNKNOWN = 0,
+    grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING = 1,
+    grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING = 2
+} grpc_health_v1_HealthCheckResponse_ServingStatus;
+#define _grpc_health_v1_HealthCheckResponse_ServingStatus_MIN grpc_health_v1_HealthCheckResponse_ServingStatus_UNKNOWN
+#define _grpc_health_v1_HealthCheckResponse_ServingStatus_MAX grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING
+#define _grpc_health_v1_HealthCheckResponse_ServingStatus_ARRAYSIZE ((grpc_health_v1_HealthCheckResponse_ServingStatus)(grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING+1))
+
+/* Struct definitions */
+typedef struct _grpc_health_v1_HealthCheckRequest {
+    bool has_service;
+    char service[200];
+/* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckRequest) */
+} grpc_health_v1_HealthCheckRequest;
+
+typedef struct _grpc_health_v1_HealthCheckResponse {
+    bool has_status;
+    grpc_health_v1_HealthCheckResponse_ServingStatus status;
+/* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckResponse) */
+} grpc_health_v1_HealthCheckResponse;
+
+/* Default values for struct fields */
+
+/* Initializer values for message structs */
+#define grpc_health_v1_HealthCheckRequest_init_default {false, ""}
+#define grpc_health_v1_HealthCheckResponse_init_default {false, (grpc_health_v1_HealthCheckResponse_ServingStatus)0}
+#define grpc_health_v1_HealthCheckRequest_init_zero {false, ""}
+#define grpc_health_v1_HealthCheckResponse_init_zero {false, (grpc_health_v1_HealthCheckResponse_ServingStatus)0}
+
+/* Field tags (for use in manual encoding/decoding) */
+#define grpc_health_v1_HealthCheckRequest_service_tag 1
+#define grpc_health_v1_HealthCheckResponse_status_tag 1
+
+/* Struct field encoding specification for nanopb */
+extern const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2];
+extern const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2];
+
+/* Maximum encoded size of messages (where known) */
+#define grpc_health_v1_HealthCheckRequest_size   203
+#define grpc_health_v1_HealthCheckResponse_size  2
+
+/* Message IDs (where set with "msgid" option) */
+#ifdef PB_MSGID
+
+#define HEALTH_MESSAGES \
+
+
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+/* @@protoc_insertion_point(eof) */
+
+#endif
diff --git a/src/cpp/server/health/health_check_service.cc b/src/cpp/server/health/health_check_service.cc
new file mode 100644
index 0000000..cca68c5
--- /dev/null
+++ b/src/cpp/server/health/health_check_service.cc
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc++/health_check_service_interface.h>
+
+namespace grpc {
+namespace {
+bool g_grpc_default_health_check_service_enabled = false;
+}  // namesapce
+
+bool DefaultHealthCheckServiceEnabled() {
+  return g_grpc_default_health_check_service_enabled;
+}
+
+void EnableDefaultHealthCheckService(bool enable) {
+  g_grpc_default_health_check_service_enabled = enable;
+}
+
+}  // namespace grpc
diff --git a/src/cpp/server/health/health_check_service_server_builder_option.cc b/src/cpp/server/health/health_check_service_server_builder_option.cc
new file mode 100644
index 0000000..2426420
--- /dev/null
+++ b/src/cpp/server/health/health_check_service_server_builder_option.cc
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc++/ext/health_check_service_server_builder_option.h>
+
+namespace grpc {
+
+HealthCheckServiceServerBuilderOption::HealthCheckServiceServerBuilderOption(
+    std::unique_ptr<HealthCheckServiceInterface> hc)
+    : hc_(std::move(hc)) {}
+// Hand over hc_ to the server.
+void HealthCheckServiceServerBuilderOption::UpdateArguments(
+    ChannelArguments* args) {
+  args->SetPointer(kHealthCheckServiceInterfaceArg, hc_.release());
+}
+
+void HealthCheckServiceServerBuilderOption::UpdatePlugins(
+    std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) {}
+
+}  // namespace grpc
diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc
index 33bdc2a..10f662c 100644
--- a/src/cpp/server/secure_server_credentials.cc
+++ b/src/cpp/server/secure_server_credentials.cc
@@ -35,11 +35,12 @@
 #include <map>
 #include <memory>
 
+#include <grpc++/impl/codegen/slice.h>
+#include <grpc++/security/auth_metadata_processor.h>
+
 #include "src/cpp/common/secure_auth_context.h"
 #include "src/cpp/server/secure_server_credentials.h"
 
-#include <grpc++/security/auth_metadata_processor.h>
-
 namespace grpc {
 
 void AuthMetadataProcessorAyncWrapper::Destroy(void* wrapper) {
@@ -71,8 +72,8 @@
     grpc_process_auth_metadata_done_cb cb, void* user_data) {
   AuthMetadataProcessor::InputMetadata metadata;
   for (size_t i = 0; i < num_md; i++) {
-    metadata.insert(std::make_pair(
-        md[i].key, grpc::string_ref(md[i].value, md[i].value_length)));
+    metadata.insert(std::make_pair(StringRefFromSlice(&md[i].key),
+                                   StringRefFromSlice(&md[i].value)));
   }
   SecureAuthContext context(ctx, false);
   AuthMetadataProcessor::OutputMetadata consumed_metadata;
@@ -85,9 +86,8 @@
   for (auto it = consumed_metadata.begin(); it != consumed_metadata.end();
        ++it) {
     grpc_metadata md_entry;
-    md_entry.key = it->first.c_str();
-    md_entry.value = it->second.data();
-    md_entry.value_length = it->second.size();
+    md_entry.key = SliceReferencingString(it->first);
+    md_entry.value = SliceReferencingString(it->second);
     md_entry.flags = 0;
     consumed_md.push_back(md_entry);
   }
@@ -95,9 +95,8 @@
   for (auto it = response_metadata.begin(); it != response_metadata.end();
        ++it) {
     grpc_metadata md_entry;
-    md_entry.key = it->first.c_str();
-    md_entry.value = it->second.data();
-    md_entry.value_length = it->second.size();
+    md_entry.key = SliceReferencingString(it->first);
+    md_entry.value = SliceReferencingString(it->second);
     md_entry.flags = 0;
     response_md.push_back(md_entry);
   }
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index 817d85a..9e11a8a 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -37,6 +37,7 @@
 
 #include <grpc++/completion_queue.h>
 #include <grpc++/generic/async_generic_service.h>
+#include <grpc++/impl/codegen/async_unary_call.h>
 #include <grpc++/impl/codegen/completion_queue_tag.h>
 #include <grpc++/impl/grpc_library.h>
 #include <grpc++/impl/method_handler_impl.h>
@@ -51,6 +52,7 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/profiling/timers.h"
+#include "src/cpp/server/health/default_health_check_service.h"
 #include "src/cpp/thread_manager/thread_manager.h"
 
 namespace grpc {
@@ -186,9 +188,8 @@
    public:
     explicit CallData(Server* server, SyncRequest* mrd)
         : cq_(mrd->cq_),
-          call_(mrd->call_, server, &cq_, server->max_receive_message_size_),
-          ctx_(mrd->deadline_, mrd->request_metadata_.metadata,
-               mrd->request_metadata_.count),
+          call_(mrd->call_, server, &cq_, server->max_receive_message_size()),
+          ctx_(mrd->deadline_, &mrd->request_metadata_),
           has_request_payload_(mrd->has_request_payload_),
           request_payload_(mrd->request_payload_),
           method_(mrd->method_) {
@@ -208,8 +209,8 @@
     void Run(std::shared_ptr<GlobalCallbacks> global_callbacks) {
       ctx_.BeginCompletionOp(&call_);
       global_callbacks->PreSynchronousRequest(&ctx_);
-      method_->handler()->RunHandler(MethodHandler::HandlerParameter(
-          &call_, &ctx_, request_payload_, call_.max_receive_message_size()));
+      method_->handler()->RunHandler(
+          MethodHandler::HandlerParameter(&call_, &ctx_, request_payload_));
       global_callbacks->PostSynchronousRequest(&ctx_);
       request_payload_ = nullptr;
       void* ignored_tag;
@@ -342,6 +343,7 @@
   int cq_timeout_msec_;
   std::vector<std::unique_ptr<SyncRequest>> sync_requests_;
   std::unique_ptr<RpcServiceMethod> unknown_method_;
+  std::unique_ptr<RpcServiceMethod> health_check_;
   std::shared_ptr<Server::GlobalCallbacks> global_callbacks_;
 };
 
@@ -358,7 +360,8 @@
       shutdown_notified_(false),
       has_generic_service_(false),
       server_(nullptr),
-      server_initializer_(new ServerInitializer(this)) {
+      server_initializer_(new ServerInitializer(this)),
+      health_check_service_disabled_(false) {
   g_gli_initializer.summon();
   gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
   global_callbacks_ = g_callbacks;
@@ -374,6 +377,19 @@
   grpc_channel_args channel_args;
   args->SetChannelArgs(&channel_args);
 
+  for (size_t i = 0; i < channel_args.num_args; i++) {
+    if (0 ==
+        strcmp(channel_args.args[i].key, kHealthCheckServiceInterfaceArg)) {
+      if (channel_args.args[i].value.pointer.p == nullptr) {
+        health_check_service_disabled_ = true;
+      } else {
+        health_check_service_.reset(static_cast<HealthCheckServiceInterface*>(
+            channel_args.args[i].value.pointer.p));
+      }
+      break;
+    }
+  }
+
   server_ = grpc_server_create(&channel_args, nullptr);
 }
 
@@ -478,7 +494,23 @@
 
 bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
   GPR_ASSERT(!started_);
+  global_callbacks_->PreServerStart(this);
   started_ = true;
+
+  // Only create default health check service when user did not provide an
+  // explicit one.
+  if (health_check_service_ == nullptr && !health_check_service_disabled_ &&
+      DefaultHealthCheckServiceEnabled()) {
+    if (sync_server_cqs_->empty()) {
+      gpr_log(GPR_ERROR,
+              "Default health check service disabled at async-only server.");
+    } else {
+      auto* default_hc_service = new DefaultHealthCheckService;
+      health_check_service_.reset(default_hc_service);
+      RegisterService(nullptr, default_hc_service->GetHealthCheckService());
+    }
+  }
+
   grpc_server_start(server_);
 
   if (!has_generic_service_) {
@@ -576,7 +608,6 @@
       delete_on_finalize_(delete_on_finalize),
       call_(nullptr) {
   call_cq_->RegisterAvalanching();  // This op will trigger more ops
-  memset(&initial_metadata_array_, 0, sizeof(initial_metadata_array_));
 }
 
 ServerInterface::BaseAsyncRequest::~BaseAsyncRequest() {
@@ -586,16 +617,8 @@
 bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag,
                                                        bool* status) {
   if (*status) {
-    for (size_t i = 0; i < initial_metadata_array_.count; i++) {
-      context_->client_metadata_.insert(
-          std::pair<grpc::string_ref, grpc::string_ref>(
-              initial_metadata_array_.metadata[i].key,
-              grpc::string_ref(
-                  initial_metadata_array_.metadata[i].value,
-                  initial_metadata_array_.metadata[i].value_length)));
-    }
+    context_->client_metadata_.FillMap();
   }
-  grpc_metadata_array_destroy(&initial_metadata_array_);
   context_->set_call(call_);
   context_->cq_ = call_cq_;
   Call call(call_, server_, call_cq_, server_->max_receive_message_size());
@@ -621,8 +644,8 @@
     ServerCompletionQueue* notification_cq) {
   grpc_server_request_registered_call(
       server_->server(), registered_method, &call_, &context_->deadline_,
-      &initial_metadata_array_, payload, call_cq_->cq(), notification_cq->cq(),
-      this);
+      context_->client_metadata_.arr(), payload, call_cq_->cq(),
+      notification_cq->cq(), this);
 }
 
 ServerInterface::GenericAsyncRequest::GenericAsyncRequest(
@@ -635,7 +658,7 @@
   GPR_ASSERT(notification_cq);
   GPR_ASSERT(call_cq);
   grpc_server_request_call(server->server(), &call_, &call_details_,
-                           &initial_metadata_array_, call_cq->cq(),
+                           context->client_metadata_.arr(), call_cq->cq(),
                            notification_cq->cq(), this);
 }
 
@@ -644,11 +667,12 @@
   // TODO(yangg) remove the copy here.
   if (*status) {
     static_cast<GenericServerContext*>(context_)->method_ =
-        call_details_.method;
-    static_cast<GenericServerContext*>(context_)->host_ = call_details_.host;
+        StringFromCopiedSlice(call_details_.method);
+    static_cast<GenericServerContext*>(context_)->host_ =
+        StringFromCopiedSlice(call_details_.host);
   }
-  gpr_free(call_details_.method);
-  gpr_free(call_details_.host);
+  grpc_slice_unref(call_details_.method);
+  grpc_slice_unref(call_details_.host);
   return BaseAsyncRequest::FinalizeResult(tag, status);
 }
 
diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc
index a66ec4a..05c05c8 100644
--- a/src/cpp/server/server_context.cc
+++ b/src/cpp/server/server_context.cc
@@ -33,7 +33,9 @@
 
 #include <grpc++/server_context.h>
 
+#include <algorithm>
 #include <mutex>
+#include <utility>
 
 #include <grpc++/completion_queue.h>
 #include <grpc++/impl/call.h>
@@ -133,8 +135,7 @@
       sent_initial_metadata_(false),
       compression_level_set_(false) {}
 
-ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
-                             size_t metadata_count)
+ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata_array* arr)
     : completion_op_(nullptr),
       has_notify_when_done_tag_(false),
       async_notify_when_done_tag_(nullptr),
@@ -143,11 +144,8 @@
       cq_(nullptr),
       sent_initial_metadata_(false),
       compression_level_set_(false) {
-  for (size_t i = 0; i < metadata_count; i++) {
-    client_metadata_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
-        metadata[i].key,
-        grpc::string_ref(metadata[i].value, metadata[i].value_length)));
-  }
+  std::swap(*client_metadata_.arr(), *arr);
+  client_metadata_.FillMap();
 }
 
 ServerContext::~ServerContext() {
@@ -223,4 +221,20 @@
   return grpc_census_call_get_context(call_);
 }
 
+void ServerContext::SetLoadReportingCosts(
+    const std::vector<grpc::string>& cost_data) {
+  if (call_ == nullptr) return;
+  grpc_load_reporting_cost_context* cost_ctx =
+      static_cast<grpc_load_reporting_cost_context*>(
+          gpr_malloc(sizeof(*cost_ctx)));
+  cost_ctx->values_count = cost_data.size();
+  cost_ctx->values = static_cast<grpc_slice*>(
+      gpr_malloc(sizeof(*cost_ctx->values) * cost_ctx->values_count));
+  for (size_t i = 0; i < cost_ctx->values_count; ++i) {
+    cost_ctx->values[i] =
+        grpc_slice_from_copied_buffer(cost_data[i].data(), cost_data[i].size());
+  }
+  grpc_call_set_load_reporting_cost_context(call_, cost_ctx);
+}
+
 }  // namespace grpc
diff --git a/src/cpp/test/server_context_test_spouse.cc b/src/cpp/test/server_context_test_spouse.cc
deleted file mode 100644
index b93152e..0000000
--- a/src/cpp/test/server_context_test_spouse.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- * Copyright 2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/test/server_context_test_spouse.h>
-
-namespace grpc {
-namespace testing {
-
-void ServerContextTestSpouse::AddClientMetadata(const grpc::string& key,
-                                                const grpc::string& value) {
-  client_metadata_storage_.insert(
-      std::pair<grpc::string, grpc::string>(key, value));
-  ctx_->client_metadata_.clear();
-  for (auto iter = client_metadata_storage_.begin();
-       iter != client_metadata_storage_.end(); ++iter) {
-    ctx_->client_metadata_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
-        iter->first.c_str(), iter->second.c_str()));
-  }
-}
-
-}  // namespace testing
-}  // namespace grpc
diff --git a/src/cpp/util/slice_cc.cc b/src/cpp/util/slice_cc.cc
index c05f1cf..6efb68e 100644
--- a/src/cpp/util/slice_cc.cc
+++ b/src/cpp/util/slice_cc.cc
@@ -35,7 +35,7 @@
 
 namespace grpc {
 
-Slice::Slice() : slice_(gpr_empty_slice()) {}
+Slice::Slice() : slice_(grpc_empty_slice()) {}
 
 Slice::~Slice() { grpc_slice_unref(slice_); }
 
diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json
index cb865ed..3805f47 100644
--- a/src/csharp/Grpc.Auth/project.json
+++ b/src/csharp/Grpc.Auth/project.json
@@ -1,5 +1,5 @@
 {
-  "version": "1.1.2",
+  "version": "1.2.0-dev",
   "title": "gRPC C# Auth",
   "authors": [ "Google Inc." ],
   "copyright": "Copyright 2015, Google Inc.",
@@ -21,7 +21,7 @@
     }
   },
   "dependencies": {
-    "Grpc.Core": "1.1.2",
+    "Grpc.Core": "1.2.0-dev",
     "Google.Apis.Auth": "1.16.0"
   },
   "frameworks": {
diff --git a/src/csharp/Grpc.Core.Testing/.gitignore b/src/csharp/Grpc.Core.Testing/.gitignore
new file mode 100644
index 0000000..1746e32
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/.gitignore
@@ -0,0 +1,2 @@
+bin
+obj
diff --git a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj
new file mode 100644
index 0000000..9b0b3ab
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Grpc.Core.Testing</RootNamespace>
+    <AssemblyName>Grpc.Core.Testing</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <DocumentationFile>bin\$(Configuration)\Grpc.Core.Testing.Xml</DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Interactive.Async">
+      <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Grpc.Core\Version.cs">
+      <Link>Version.cs</Link>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TestCalls.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Grpc.Core.Testing.project.json" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
+      <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
+      <Name>Grpc.Core</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.project.json b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.project.json
new file mode 100644
index 0000000..c2f5bcb
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.project.json
@@ -0,0 +1,8 @@
+{
+  "frameworks": {
+    "net45": { }
+  },
+  "runtimes": {
+    "win": { }
+  }
+}
diff --git a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.xproj b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.xproj
new file mode 100644
index 0000000..c972387
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.xproj
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion>
+    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+  </PropertyGroup>
+  <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>2b372155-80ba-4cf9-82d6-4b938e8ec3a0</ProjectGuid>
+    <RootNamespace>Grpc.Core.Testing</RootNamespace>
+    <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
+    <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+  <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
+</Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d3ca0c4
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs
@@ -0,0 +1,44 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.Core.Testing")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
diff --git a/src/csharp/Grpc.Core.Testing/Settings.StyleCop b/src/csharp/Grpc.Core.Testing/Settings.StyleCop
new file mode 100644
index 0000000..2942add
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/Settings.StyleCop
@@ -0,0 +1,10 @@
+<StyleCopSettings Version="105">
+  <SourceFileList>
+    <SourceFile>Health.cs</SourceFile>
+    <Settings>
+    <GlobalSettings>
+      <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
+    </GlobalSettings>
+    </Settings>
+  </SourceFileList>
+</StyleCopSettings>
diff --git a/src/csharp/Grpc.Core.Testing/TestCalls.cs b/src/csharp/Grpc.Core.Testing/TestCalls.cs
new file mode 100644
index 0000000..d8c36f2
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/TestCalls.cs
@@ -0,0 +1,91 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Core.Testing
+{
+    /// <summary>
+    /// Test doubles for client-side call objects.
+    /// </summary>
+    public static class TestCalls
+    {
+        /// <summary>
+        /// Creates a test double for <c>AsyncUnaryCall</c>. Only for testing.
+        /// Note: experimental API that can change or be removed without any prior notice.
+        /// </summary>
+        public static AsyncUnaryCall<TResponse> AsyncUnaryCall<TResponse> (
+            Task<TResponse> responseAsync, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc,
+            Func<Metadata> getTrailersFunc, Action disposeAction)
+        {
+            return new AsyncUnaryCall<TResponse>(responseAsync, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction);
+        }
+
+        /// <summary>
+        /// Creates a test double for <c>AsyncClientStreamingCall</c>. Only for testing.
+        /// Note: experimental API that can change or be removed without any prior notice.
+        /// </summary>
+        public static AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(
+            IClientStreamWriter<TRequest> requestStream, Task<TResponse> responseAsync,
+            Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc,
+            Func<Metadata> getTrailersFunc, Action disposeAction)
+        {
+            return new AsyncClientStreamingCall<TRequest, TResponse>(requestStream, responseAsync, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction);
+        }
+
+        /// <summary>
+        /// Creates a test double for <c>AsyncServerStreamingCall</c>. Only for testing.
+        /// Note: experimental API that can change or be removed without any prior notice.
+        /// </summary>
+        public static AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TResponse>(
+            IAsyncStreamReader<TResponse> responseStream, Task<Metadata> responseHeadersAsync, 
+            Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)
+        {
+            return new AsyncServerStreamingCall<TResponse>(responseStream, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction);
+        }
+
+        /// <summary>
+        /// Creates a test double for <c>AsyncDuplexStreamingCall</c>. Only for testing.
+        /// Note: experimental API that can change or be removed without any prior notice.
+        /// </summary>
+        public static AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TResponse, TRequest>(
+            IClientStreamWriter<TRequest> requestStream, IAsyncStreamReader<TResponse> responseStream,
+            Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc,
+            Func<Metadata> getTrailersFunc, Action disposeAction)
+        {
+            return new AsyncDuplexStreamingCall<TRequest, TResponse>(requestStream, responseStream, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core.Testing/packages.config b/src/csharp/Grpc.Core.Testing/packages.config
new file mode 100644
index 0000000..53cfad5
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
+</packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Core.Testing/project.json b/src/csharp/Grpc.Core.Testing/project.json
new file mode 100644
index 0000000..02be957
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/project.json
@@ -0,0 +1,39 @@
+{
+  "version": "1.2.0-dev",
+  "title": "gRPC C# Core Testing",
+  "authors": [ "Google Inc." ],
+  "copyright": "Copyright 2017, Google Inc.",
+  "packOptions": {
+    "summary": "Testing support for gRPC C#",
+    "description": "Useful when testing code that uses gRPC.",
+    "owners": [ "grpc-packages" ],
+    "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
+    "projectUrl": "https://github.com/grpc/grpc",
+    "requireLicenseAcceptance": false,
+    "tags": [ "gRPC test testing" ]
+  },
+  "buildOptions": {
+    "define": [ "SIGNED" ],
+    "keyFile": "../keys/Grpc.snk",
+    "xmlDoc": true,
+    "compile": {
+      "includeFiles": [ "../Grpc.Core/Version.cs" ]
+    }
+  },
+  "dependencies": {
+    "Grpc.Core": "1.2.0-dev"
+  },
+  "frameworks": {
+    "net45": {
+      "frameworkAssemblies": {
+        "System.Runtime": "",
+        "System.IO": ""
+      }
+    },
+    "netstandard1.5": {
+      "dependencies": {
+        "NETStandard.Library": "1.6.0"
+      }
+    }
+  }
+}
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index dcdddc7..6bf9756 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -336,6 +336,22 @@
         }
 
         [Test]
+        public void StatusDetailIsUtf8()
+        {
+            // some japanese and chinese characters
+            var nonAsciiString = "\u30a1\u30a2\u30a3 \u62b5\u6297\u662f\u5f92\u52b3\u7684";
+            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
+            {
+                context.Status = new Status(StatusCode.Unknown, nonAsciiString);
+                return "";
+            });
+
+            var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
+            Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode);
+            Assert.AreEqual(nonAsciiString, ex.Status.Detail);
+        }
+
+        [Test]
         public void ServerCallContext_PeerInfoPresent()
         {
             helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
diff --git a/src/csharp/Grpc.Core.Tests/project.json b/src/csharp/Grpc.Core.Tests/project.json
index 509084a..045207a 100644
--- a/src/csharp/Grpc.Core.Tests/project.json
+++ b/src/csharp/Grpc.Core.Tests/project.json
@@ -13,8 +13,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -31,8 +31,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
index 26449ee..efae149 100644
--- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
@@ -33,6 +33,7 @@
 
 using System;
 using System.Runtime.InteropServices;
+using System.Text;
 using Grpc.Core;
 
 namespace Grpc.Core.Internal
@@ -42,6 +43,7 @@
     /// </summary>
     internal class BatchContextSafeHandle : SafeHandleZeroIsInvalid
     {
+        static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8;
         static readonly NativeMethods Native = NativeMethods.Get();
 
         private BatchContextSafeHandle()
@@ -71,7 +73,9 @@
         // Gets data of recv_status_on_client completion.
         public ClientSideStatus GetReceivedStatusOnClient()
         {
-            string details = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_recv_status_on_client_details(this));
+            UIntPtr detailsLength;
+            IntPtr detailsPtr = Native.grpcsharp_batch_context_recv_status_on_client_details(this, out detailsLength);
+            string details = PtrToStringUtf8(detailsPtr, (int) detailsLength.ToUInt32());
             var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details);
 
             IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this);
@@ -104,5 +108,12 @@
             Native.grpcsharp_batch_context_destroy(handle);
             return true;
         }
+
+        string PtrToStringUtf8(IntPtr ptr, int len)
+        {
+            var bytes = new byte[len];
+            Marshal.Copy(ptr, bytes, 0, len);
+            return EncodingUTF8.GetString(bytes);
+        }
     }
 }
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 6bfcc7f..710ca48 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -32,6 +32,7 @@
 using System;
 using System.Diagnostics;
 using System.Runtime.InteropServices;
+using System.Text;
 using Grpc.Core;
 using Grpc.Core.Utils;
 using Grpc.Core.Profiling;
@@ -44,6 +45,7 @@
     internal class CallSafeHandle : SafeHandleZeroIsInvalid, INativeCall
     {
         public static readonly CallSafeHandle NullInstance = new CallSafeHandle();
+        static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8;
         static readonly NativeMethods Native = NativeMethods.Get();
 
         const uint GRPC_WRITE_BUFFER_HINT = 1;
@@ -138,7 +140,8 @@
                 var ctx = BatchContextSafeHandle.Create();
                 var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero;
                 completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
-                Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, status.Detail, metadataArray, sendEmptyInitialMetadata,
+                var statusDetailBytes = EncodingUTF8.GetBytes(status.Detail);
+                Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, statusDetailBytes, new UIntPtr((ulong)statusDetailBytes.Length), metadataArray, sendEmptyInitialMetadata,
                     optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
             }
         }
diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
index 05dda5b..d5b87a6 100644
--- a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
@@ -79,9 +79,13 @@
             for (ulong i = 0; i < count; i++)
             {
                 var index = new UIntPtr(i);
-                string key = Marshal.PtrToStringAnsi(Native.grpcsharp_metadata_array_get_key(metadataArray, index));
-                var bytes = new byte[Native.grpcsharp_metadata_array_get_value_length(metadataArray, index).ToUInt64()];
-                Marshal.Copy(Native.grpcsharp_metadata_array_get_value(metadataArray, index), bytes, 0, bytes.Length);
+                UIntPtr keyLen;
+                IntPtr keyPtr = Native.grpcsharp_metadata_array_get_key(metadataArray, index, out keyLen);
+                string key = Marshal.PtrToStringAnsi(keyPtr, (int)keyLen.ToUInt32());
+                UIntPtr valueLen;
+                IntPtr valuePtr = Native.grpcsharp_metadata_array_get_value(metadataArray, index, out valueLen);
+                var bytes = new byte[valueLen.ToUInt64()];
+                Marshal.Copy(valuePtr, bytes, 0, bytes.Length);
                 metadata.Add(Metadata.Entry.CreateUnsafe(key, bytes));
             }
             return metadata;
diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
index ce38e37..aff9550 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
@@ -128,7 +128,6 @@
         public readonly Delegates.grpcsharp_metadata_array_count_delegate grpcsharp_metadata_array_count;
         public readonly Delegates.grpcsharp_metadata_array_get_key_delegate grpcsharp_metadata_array_get_key;
         public readonly Delegates.grpcsharp_metadata_array_get_value_delegate grpcsharp_metadata_array_get_value;
-        public readonly Delegates.grpcsharp_metadata_array_get_value_length_delegate grpcsharp_metadata_array_get_value_length;
         public readonly Delegates.grpcsharp_metadata_array_destroy_full_delegate grpcsharp_metadata_array_destroy_full;
 
         public readonly Delegates.grpcsharp_redirect_log_delegate grpcsharp_redirect_log;
@@ -237,7 +236,6 @@
             this.grpcsharp_metadata_array_count = GetMethodDelegate<Delegates.grpcsharp_metadata_array_count_delegate>(library);
             this.grpcsharp_metadata_array_get_key = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_key_delegate>(library);
             this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library);
-            this.grpcsharp_metadata_array_get_value_length = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_length_delegate>(library);
             this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library);
 
             this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library);
@@ -306,15 +304,15 @@
             public delegate IntPtr grpcsharp_batch_context_recv_message_length_delegate(BatchContextSafeHandle ctx);
             public delegate void grpcsharp_batch_context_recv_message_to_buffer_delegate(BatchContextSafeHandle ctx, byte[] buffer, UIntPtr bufferLen);
             public delegate StatusCode grpcsharp_batch_context_recv_status_on_client_status_delegate(BatchContextSafeHandle ctx);
-            public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_details_delegate(BatchContextSafeHandle ctx);  // returns const char*
+            public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_details_delegate(BatchContextSafeHandle ctx, out UIntPtr detailsLength);
             public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate(BatchContextSafeHandle ctx);
             public delegate int grpcsharp_batch_context_recv_close_on_server_cancelled_delegate(BatchContextSafeHandle ctx);
             public delegate void grpcsharp_batch_context_destroy_delegate(IntPtr ctx);
 
             public delegate RequestCallContextSafeHandle grpcsharp_request_call_context_create_delegate();
             public delegate CallSafeHandle grpcsharp_request_call_context_call_delegate(RequestCallContextSafeHandle ctx);
-            public delegate IntPtr grpcsharp_request_call_context_method_delegate(RequestCallContextSafeHandle ctx);  // returns const char*
-            public delegate IntPtr grpcsharp_request_call_context_host_delegate(RequestCallContextSafeHandle ctx);  // returns const char*
+            public delegate IntPtr grpcsharp_request_call_context_method_delegate(RequestCallContextSafeHandle ctx, out UIntPtr methodLength);
+            public delegate IntPtr grpcsharp_request_call_context_host_delegate(RequestCallContextSafeHandle ctx, out UIntPtr hostLength);
             public delegate Timespec grpcsharp_request_call_context_deadline_delegate(RequestCallContextSafeHandle ctx);
             public delegate IntPtr grpcsharp_request_call_context_request_metadata_delegate(RequestCallContextSafeHandle ctx);
             public delegate void grpcsharp_request_call_context_destroy_delegate(IntPtr ctx);
@@ -338,7 +336,7 @@
             public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
             public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call,
-                BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
+                BatchContextSafeHandle ctx, StatusCode statusCode, byte[] statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
                 byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
             public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
@@ -384,9 +382,8 @@
             public delegate MetadataArraySafeHandle grpcsharp_metadata_array_create_delegate(UIntPtr capacity);
             public delegate void grpcsharp_metadata_array_add_delegate(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength);
             public delegate UIntPtr grpcsharp_metadata_array_count_delegate(IntPtr metadataArray);
-            public delegate IntPtr grpcsharp_metadata_array_get_key_delegate(IntPtr metadataArray, UIntPtr index);
-            public delegate IntPtr grpcsharp_metadata_array_get_value_delegate(IntPtr metadataArray, UIntPtr index);
-            public delegate UIntPtr grpcsharp_metadata_array_get_value_length_delegate(IntPtr metadataArray, UIntPtr index);
+            public delegate IntPtr grpcsharp_metadata_array_get_key_delegate(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength);
+            public delegate IntPtr grpcsharp_metadata_array_get_value_delegate(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength);
             public delegate void grpcsharp_metadata_array_destroy_full_delegate(IntPtr array);
 
             public delegate void grpcsharp_redirect_log_delegate(GprLogDelegate callback);
diff --git a/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs
index ea7819d..c1560bc 100644
--- a/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs
@@ -66,8 +66,14 @@
         {
             var call = Native.grpcsharp_request_call_context_call(this);
 
-            var method = Marshal.PtrToStringAnsi(Native.grpcsharp_request_call_context_method(this));
-            var host = Marshal.PtrToStringAnsi(Native.grpcsharp_request_call_context_host(this));
+            UIntPtr methodLen;
+            IntPtr methodPtr = Native.grpcsharp_request_call_context_method(this, out methodLen);
+            var method = Marshal.PtrToStringAnsi(methodPtr, (int) methodLen.ToUInt32());
+
+            UIntPtr hostLen;
+            IntPtr hostPtr = Native.grpcsharp_request_call_context_host(this, out hostLen);
+            var host = Marshal.PtrToStringAnsi(hostPtr, (int) hostLen.ToUInt32());
+
             var deadline = Native.grpcsharp_request_call_context_deadline(this);
 
             IntPtr metadataArrayPtr = Native.grpcsharp_request_call_context_request_metadata(this);
diff --git a/src/csharp/Grpc.Core/NativeDeps.Windows.targets b/src/csharp/Grpc.Core/NativeDeps.Windows.targets
index 93db093..623f58b 100644
--- a/src/csharp/Grpc.Core/NativeDeps.Windows.targets
+++ b/src/csharp/Grpc.Core/NativeDeps.Windows.targets
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <Content Include="..\..\..\vsprojects\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll">
+    <Content Include="..\..\..\cmake\build\Win32\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       <Link>grpc_csharp_ext.x86.dll</Link>
     </Content>
diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
index 99158fb..77ac347 100644
--- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
@@ -49,6 +49,11 @@
     "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
     "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
     "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
+[assembly: InternalsVisibleTo("Grpc.Core.Testing,PublicKey=" +
+    "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" +
+    "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
+    "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
+    "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
 [assembly: InternalsVisibleTo("Grpc.IntegrationTesting,PublicKey=" +
     "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" +
     "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
@@ -56,5 +61,6 @@
     "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
 #else
 [assembly: InternalsVisibleTo("Grpc.Core.Tests")]
+[assembly: InternalsVisibleTo("Grpc.Core.Testing")]
 [assembly: InternalsVisibleTo("Grpc.IntegrationTesting")]
 #endif
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index b6612dc..f01a024 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -48,11 +48,11 @@
         /// <summary>
         /// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
         /// </summary>
-        public const string CurrentAssemblyFileVersion = "1.1.2.0";
+        public const string CurrentAssemblyFileVersion = "1.2.0.0";
 
         /// <summary>
         /// Current version of gRPC C#
         /// </summary>
-        public const string CurrentVersion = "1.1.2";
+        public const string CurrentVersion = "1.2.0-dev";
     }
 }
diff --git a/src/csharp/Grpc.Core/project.json b/src/csharp/Grpc.Core/project.json
index 9bcda45..0e37ec8 100644
--- a/src/csharp/Grpc.Core/project.json
+++ b/src/csharp/Grpc.Core/project.json
@@ -1,5 +1,5 @@
 {
-  "version": "1.1.2",
+  "version": "1.2.0-dev",
   "title": "gRPC C# Core",
   "authors": [ "Google Inc." ],
   "copyright": "Copyright 2015, Google Inc.",
diff --git a/src/csharp/Grpc.Examples.MathClient/project.json b/src/csharp/Grpc.Examples.MathClient/project.json
index 9a8880b..81c1715 100644
--- a/src/csharp/Grpc.Examples.MathClient/project.json
+++ b/src/csharp/Grpc.Examples.MathClient/project.json
@@ -13,8 +13,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -31,8 +31,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.Examples.MathServer/project.json b/src/csharp/Grpc.Examples.MathServer/project.json
index 9a8880b..81c1715 100644
--- a/src/csharp/Grpc.Examples.MathServer/project.json
+++ b/src/csharp/Grpc.Examples.MathServer/project.json
@@ -13,8 +13,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -31,8 +31,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.Examples.Tests/project.json b/src/csharp/Grpc.Examples.Tests/project.json
index 3e130be..e509621 100644
--- a/src/csharp/Grpc.Examples.Tests/project.json
+++ b/src/csharp/Grpc.Examples.Tests/project.json
@@ -13,8 +13,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -31,8 +31,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.HealthCheck.Tests/project.json b/src/csharp/Grpc.HealthCheck.Tests/project.json
index addc782..654454d 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/project.json
+++ b/src/csharp/Grpc.HealthCheck.Tests/project.json
@@ -13,8 +13,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -31,8 +31,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.HealthCheck/project.json b/src/csharp/Grpc.HealthCheck/project.json
index dd5f109..5d3b2f5 100644
--- a/src/csharp/Grpc.HealthCheck/project.json
+++ b/src/csharp/Grpc.HealthCheck/project.json
@@ -1,5 +1,5 @@
 {
-  "version": "1.1.2",
+  "version": "1.2.0-dev",
   "title": "gRPC C# Healthchecking",
   "authors": [ "Google Inc." ],
   "copyright": "Copyright 2015, Google Inc.",
@@ -21,7 +21,7 @@
     }
   },
   "dependencies": {
-    "Grpc.Core": "1.1.2",
+    "Grpc.Core": "1.2.0-dev",
     "Google.Protobuf": "3.0.0"
   },
   "frameworks": {
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/project.json b/src/csharp/Grpc.IntegrationTesting.Client/project.json
index ad81cbc..f905281 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.Client/project.json
@@ -16,8 +16,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -37,8 +37,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
index 2c7643b..161e602 100644
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
@@ -16,8 +16,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -37,8 +37,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/project.json b/src/csharp/Grpc.IntegrationTesting.Server/project.json
index ad81cbc..f905281 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.Server/project.json
@@ -16,8 +16,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -37,8 +37,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
index ad81cbc..f905281 100644
--- a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
@@ -16,8 +16,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -37,8 +37,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 5ba83b1..32a52ee 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -45,6 +45,7 @@
 using Google.Protobuf;
 using Grpc.Auth;
 using Grpc.Core;
+using Grpc.Core.Logging;
 using Grpc.Core.Utils;
 using Grpc.Testing;
 using Newtonsoft.Json.Linq;
@@ -56,7 +57,7 @@
     {
         private class ClientOptions
         {
-            [Option("server_host", Default = "127.0.0.1")]
+            [Option("server_host", Default = "localhost")]
             public string ServerHost { get; set; }
 
             [Option("server_host_override", Default = TestCredentials.DefaultHostOverride)]
@@ -95,6 +96,7 @@
 
         public static void Run(string[] args)
         {
+            GrpcEnvironment.SetLogger(new ConsoleLogger());
             var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
                 .WithNotParsed(errors => Environment.Exit(1))
                 .WithParsed(options =>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index 4118f99..be99f92 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -41,6 +41,7 @@
 using CommandLine;
 using CommandLine.Text;
 using Grpc.Core;
+using Grpc.Core.Logging;
 using Grpc.Core.Utils;
 using Grpc.Testing;
 using NUnit.Framework;
@@ -68,6 +69,7 @@
 
         public static void Run(string[] args)
         {
+            GrpcEnvironment.SetLogger(new ConsoleLogger());
             var parserResult = Parser.Default.ParseArguments<ServerOptions>(args)
                 .WithNotParsed(errors => Environment.Exit(1))
                 .WithParsed(options =>
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
index 62a7347..b17b2c2 100644
--- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -42,6 +42,7 @@
 using CommandLine;
 using CommandLine.Text;
 using Grpc.Core;
+using Grpc.Core.Logging;
 using Grpc.Core.Utils;
 using Grpc.Testing;
 using NUnit.Framework;
@@ -65,6 +66,7 @@
 
         public static void Run(string[] args)
         {
+            GrpcEnvironment.SetLogger(new ConsoleLogger());
             var parserResult = Parser.Default.ParseArguments<ServerOptions>(args)
                 .WithNotParsed((x) => Environment.Exit(1))
                 .WithParsed(options =>
diff --git a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
index 750613b..dbf8844 100644
--- a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
@@ -92,6 +92,7 @@
 
         public static void Run(string[] args)
         {
+            GrpcEnvironment.SetLogger(new ConsoleLogger());
             var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
                 .WithNotParsed((x) => Environment.Exit(1))
                 .WithParsed(options => {
diff --git a/src/csharp/Grpc.IntegrationTesting/project.json b/src/csharp/Grpc.IntegrationTesting/project.json
index e47b595..eba5431 100644
--- a/src/csharp/Grpc.IntegrationTesting/project.json
+++ b/src/csharp/Grpc.IntegrationTesting/project.json
@@ -16,8 +16,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -37,8 +37,8 @@
             "data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.Reflection.Tests/project.json b/src/csharp/Grpc.Reflection.Tests/project.json
index 61d3b7e..b90834a 100644
--- a/src/csharp/Grpc.Reflection.Tests/project.json
+++ b/src/csharp/Grpc.Reflection.Tests/project.json
@@ -13,8 +13,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -31,8 +31,8 @@
         },
         "copyToOutput": {
           "mappings": {
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/src/csharp/Grpc.Reflection/project.json b/src/csharp/Grpc.Reflection/project.json
index ee951cf..bfc5766 100644
--- a/src/csharp/Grpc.Reflection/project.json
+++ b/src/csharp/Grpc.Reflection/project.json
@@ -1,5 +1,5 @@
 {
-  "version": "1.1.2",
+  "version": "1.2.0-dev",
   "title": "gRPC C# Reflection",
   "authors": [ "Google Inc." ],
   "copyright": "Copyright 2016, Google Inc.",
@@ -21,7 +21,7 @@
     }
   },
   "dependencies": {
-    "Grpc.Core": "1.1.2",
+    "Grpc.Core": "1.2.0-dev",
     "Google.Protobuf": "3.0.0"
   },
   "frameworks": {
diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln
index 179e731..84ba460 100644
--- a/src/csharp/Grpc.sln
+++ b/src/csharp/Grpc.sln
@@ -40,6 +40,8 @@
 EndProject

 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{B88F91D6-436D-4C78-8B99-47800FA8DE03}"

 EndProject

+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Core.Testing", "Grpc.Core.Testing\Grpc.Core.Testing.csproj", "{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}"

+EndProject

 Global

 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

 		Debug|Any CPU = Debug|Any CPU

@@ -110,6 +112,10 @@
 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.Build.0 = Debug|Any CPU

 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.ActiveCfg = Release|Any CPU

 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.Build.0 = Release|Any CPU

+		{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}.Release|Any CPU.Build.0 = Release|Any CPU

 	EndGlobalSection

 	GlobalSection(NestedProjects) = preSolution

 	EndGlobalSection

diff --git a/src/csharp/README.md b/src/csharp/README.md
index 34590b9..a21b72f 100644
--- a/src/csharp/README.md
+++ b/src/csharp/README.md
@@ -37,23 +37,15 @@
 You only need to go through these steps if you are planning to develop gRPC C#.
 If you are a user of gRPC C#, go to Usage section above.
 
-**Windows**
+**Windows, Linux or Mac OS X**
 
-- The grpc_csharp_ext native library needs to be built so you can build the gRPC C# solution. Open the
-  solution `vsprojects/grpc_csharp_ext.sln` in Visual Studio and build it.
-
-- Open `src\csharp\Grpc.sln` (path is relative to gRPC repository root)
-  using Visual Studio
-
-**Linux and Mac OS X**
-
-- The grpc_csharp_ext native library needs to be built so you can build the gRPC C# solution:
-  ```sh
+- The easiest way to build is using the `run_tests.py` script that will take care of building the `grpc_csharp_ext` native library:
+  ```
   # from the gRPC repository root
-  $ tools/run_tests/run_tests.py -c dbg -l csharp --build_only
+  $ python tools/run_tests/run_tests.py -c dbg -l csharp --build_only
   ```
 
-- Use MonoDevelop / Xamarin Studio to open the solution Grpc.sln
+- Use Visual Studio / MonoDevelop / Xamarin Studio to open the solution Grpc.sln
 
 RUNNING TESTS
 -------------
diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat
index fac1419..b99fdcb 100755
--- a/src/csharp/build_packages_dotnetcli.bat
+++ b/src/csharp/build_packages_dotnetcli.bat
@@ -28,7 +28,7 @@
 @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 @rem Current package versions
-set VERSION=1.1.2
+set VERSION=1.2.0-dev
 set PROTOBUF_VERSION=3.0.0
 
 @rem Adjust the location of nuget.exe
@@ -59,6 +59,7 @@
 %DOTNET% restore . || goto :error
 
 %DOTNET% pack --configuration Release Grpc.Core\project.json --output ..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release Grpc.Core.Testing\project.json --output ..\..\artifacts || goto :error
 %DOTNET% pack --configuration Release Grpc.Auth\project.json --output ..\..\artifacts || goto :error
 %DOTNET% pack --configuration Release Grpc.HealthCheck\project.json --output ..\..\artifacts || goto :error
 %DOTNET% pack --configuration Release Grpc.Reflection\project.json --output ..\..\artifacts || goto :error
diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh
index 03f53af..442e3ac 100755
--- a/src/csharp/build_packages_dotnetcli.sh
+++ b/src/csharp/build_packages_dotnetcli.sh
@@ -61,11 +61,12 @@
 dotnet restore .
 
 dotnet pack --configuration Release Grpc.Core/project.json --output ../../artifacts
+dotnet pack --configuration Release Grpc.Core.Testing/project.json --output ../../artifacts
 dotnet pack --configuration Release Grpc.Auth/project.json --output ../../artifacts
 dotnet pack --configuration Release Grpc.HealthCheck/project.json --output ../../artifacts
 dotnet pack --configuration Release Grpc.Reflection/project.json --output ../../artifacts
 
-nuget pack Grpc.nuspec -Version "1.1.2" -OutputDirectory ../../artifacts
-nuget pack Grpc.Tools.nuspec -Version "1.1.2" -OutputDirectory ../../artifacts
+nuget pack Grpc.nuspec -Version "1.2.0-dev" -OutputDirectory ../../artifacts
+nuget pack Grpc.Tools.nuspec -Version "1.2.0-dev" -OutputDirectory ../../artifacts
 
 (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg)
diff --git a/src/csharp/buildall.bat b/src/csharp/buildall.bat
deleted file mode 100644
index 0beb30c..0000000
--- a/src/csharp/buildall.bat
+++ /dev/null
@@ -1,59 +0,0 @@
-@rem Copyright 2016, Google Inc.
-@rem All rights reserved.
-@rem
-@rem Redistribution and use in source and binary forms, with or without
-@rem modification, are permitted provided that the following conditions are
-@rem met:
-@rem
-@rem     * Redistributions of source code must retain the above copyright
-@rem notice, this list of conditions and the following disclaimer.
-@rem     * Redistributions in binary form must reproduce the above
-@rem copyright notice, this list of conditions and the following disclaimer
-@rem in the documentation and/or other materials provided with the
-@rem distribution.
-@rem     * Neither the name of Google Inc. nor the names of its
-@rem contributors may be used to endorse or promote products derived from
-@rem this software without specific prior written permission.
-@rem
-@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-@rem Convenience script to build gRPC C# from command line
-
-setlocal
-
-@rem enter this directory
-cd /d %~dp0
-
-@rem Set VS variables (uses Visual Studio 2013)
-@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
-
-@rem Fetch all dependencies
-nuget restore ..\..\vsprojects\grpc.sln || goto :error
-nuget restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
-nuget restore ..\..\vsprojects\grpc_protoc_plugins.sln || goto :error
-nuget restore Grpc.sln || goto :error
-
-@rem Build the C# native extension
-msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Debug /p:PlatformToolset=v120 || goto :error
-msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error
-
-msbuild Grpc.sln /p:Configuration=Debug || goto :error
-msbuild Grpc.sln /p:Configuration=Release || goto :error
-
-endlocal
-
-goto :EOF
-
-:error
-echo Failed!
-exit /b %errorlevel%
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 7239606..6a24119 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -73,15 +73,13 @@
   grpc_byte_buffer *send_message;
   struct {
     grpc_metadata_array trailing_metadata;
-    char *status_details;
   } send_status_from_server;
   grpc_metadata_array recv_initial_metadata;
   grpc_byte_buffer *recv_message;
   struct {
     grpc_metadata_array trailing_metadata;
     grpc_status_code status;
-    char *status_details;
-    size_t status_details_capacity;
+    grpc_slice status_details;
   } recv_status_on_client;
   int recv_close_on_server_cancelled;
 } grpcsharp_batch_context;
@@ -122,8 +120,8 @@
   size_t i;
   if (array->metadata) {
     for (i = 0; i < array->count; i++) {
-      gpr_free((void *)array->metadata[i].key);
-      gpr_free((void *)array->metadata[i].value);
+      grpc_slice_unref(array->metadata[i].key);
+      grpc_slice_unref(array->metadata[i].value);
     }
   }
   gpr_free(array->metadata);
@@ -167,10 +165,8 @@
                              const char *value, size_t value_length) {
   size_t i = array->count;
   GPR_ASSERT(array->count < array->capacity);
-  array->metadata[i].key = gpr_strdup(key);
-  array->metadata[i].value = (char *)gpr_malloc(value_length);
-  memcpy((void *)array->metadata[i].value, value, value_length);
-  array->metadata[i].value_length = value_length;
+  array->metadata[i].key = grpc_slice_from_copied_string(key);
+  array->metadata[i].value = grpc_slice_from_copied_buffer(value, value_length);
   array->count++;
 }
 
@@ -180,21 +176,17 @@
 }
 
 GPR_EXPORT const char *GPR_CALLTYPE
-grpcsharp_metadata_array_get_key(grpc_metadata_array *array, size_t index) {
+grpcsharp_metadata_array_get_key(grpc_metadata_array *array, size_t index, size_t *key_length) {
   GPR_ASSERT(index < array->count);
-  return array->metadata[index].key;
+  *key_length = GRPC_SLICE_LENGTH(array->metadata[index].key);
+  return (char *)GRPC_SLICE_START_PTR(array->metadata[index].key);
 }
 
 GPR_EXPORT const char *GPR_CALLTYPE
-grpcsharp_metadata_array_get_value(grpc_metadata_array *array, size_t index) {
+grpcsharp_metadata_array_get_value(grpc_metadata_array *array, size_t index, size_t *value_length) {
   GPR_ASSERT(index < array->count);
-  return array->metadata[index].value;
-}
-
-GPR_EXPORT intptr_t GPR_CALLTYPE grpcsharp_metadata_array_get_value_length(
-    grpc_metadata_array *array, size_t index) {
-  GPR_ASSERT(index < array->count);
-  return (intptr_t)array->metadata[index].value_length;
+  *value_length = GRPC_SLICE_LENGTH(array->metadata[index].value);
+  return (char *)GRPC_SLICE_START_PTR(array->metadata[index].value);
 }
 
 /* Move contents of metadata array */
@@ -227,7 +219,6 @@
 
   grpcsharp_metadata_array_destroy_metadata_including_entries(
       &(ctx->send_status_from_server.trailing_metadata));
-  gpr_free(ctx->send_status_from_server.status_details);
 
   grpcsharp_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata));
 
@@ -235,7 +226,7 @@
 
   grpcsharp_metadata_array_destroy_metadata_only(
       &(ctx->recv_status_on_client.trailing_metadata));
-  gpr_free((void *)ctx->recv_status_on_client.status_details);
+  grpc_slice_unref(ctx->recv_status_on_client.status_details);
 
   gpr_free(ctx);
 }
@@ -307,8 +298,9 @@
 
 GPR_EXPORT const char *GPR_CALLTYPE
 grpcsharp_batch_context_recv_status_on_client_details(
-    const grpcsharp_batch_context *ctx) {
-  return ctx->recv_status_on_client.status_details;
+    const grpcsharp_batch_context *ctx, size_t *details_length) {
+  *details_length = GRPC_SLICE_LENGTH(ctx->recv_status_on_client.status_details);
+  return (char *)GRPC_SLICE_START_PTR(ctx->recv_status_on_client.status_details);
 }
 
 GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE
@@ -324,13 +316,15 @@
 
 GPR_EXPORT const char *GPR_CALLTYPE
 grpcsharp_request_call_context_method(
-    const grpcsharp_request_call_context *ctx) {
-  return ctx->call_details.method;
+    const grpcsharp_request_call_context *ctx, size_t *method_length) {
+  *method_length = GRPC_SLICE_LENGTH(ctx->call_details.method);
+  return (char *)GRPC_SLICE_START_PTR(ctx->call_details.method);
 }
 
 GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_request_call_context_host(
-    const grpcsharp_request_call_context *ctx) {
-  return ctx->call_details.host;
+    const grpcsharp_request_call_context *ctx, size_t *host_length) {
+  *host_length = GRPC_SLICE_LENGTH(ctx->call_details.host);
+  return (char *)GRPC_SLICE_START_PTR(ctx->call_details.host);
 }
 
 GPR_EXPORT gpr_timespec GPR_CALLTYPE
@@ -404,8 +398,15 @@
                               grpc_completion_queue *cq,
                               const char *method, const char *host,
                               gpr_timespec deadline) {
+  grpc_slice method_slice = grpc_slice_from_copied_string(method);
+  grpc_slice *host_slice_ptr = NULL;
+  grpc_slice host_slice;
+  if (host != NULL) {
+    host_slice = grpc_slice_from_copied_string(host);
+    host_slice_ptr = &host_slice;
+  }
   return grpc_channel_create_call(channel, parent_call, propagation_mask, cq,
-                                  method, host, deadline, NULL);
+                                  method_slice, host_slice_ptr, deadline, NULL);
 }
 
 GPR_EXPORT grpc_connectivity_state GPR_CALLTYPE
@@ -561,11 +562,8 @@
       &(ctx->recv_status_on_client.trailing_metadata);
   ops[5].data.recv_status_on_client.status =
       &(ctx->recv_status_on_client.status);
-  /* not using preallocation for status_details */
   ops[5].data.recv_status_on_client.status_details =
       &(ctx->recv_status_on_client.status_details);
-  ops[5].data.recv_status_on_client.status_details_capacity =
-      &(ctx->recv_status_on_client.status_details_capacity);
   ops[5].flags = 0;
   ops[5].reserved = NULL;
 
@@ -606,11 +604,8 @@
       &(ctx->recv_status_on_client.trailing_metadata);
   ops[3].data.recv_status_on_client.status =
       &(ctx->recv_status_on_client.status);
-  /* not using preallocation for status_details */
   ops[3].data.recv_status_on_client.status_details =
       &(ctx->recv_status_on_client.status_details);
-  ops[3].data.recv_status_on_client.status_details_capacity =
-      &(ctx->recv_status_on_client.status_details_capacity);
   ops[3].flags = 0;
   ops[3].reserved = NULL;
 
@@ -649,11 +644,8 @@
       &(ctx->recv_status_on_client.trailing_metadata);
   ops[3].data.recv_status_on_client.status =
       &(ctx->recv_status_on_client.status);
-  /* not using preallocation for status_details */
   ops[3].data.recv_status_on_client.status_details =
       &(ctx->recv_status_on_client.status_details);
-  ops[3].data.recv_status_on_client.status_details_capacity =
-      &(ctx->recv_status_on_client.status_details_capacity);
   ops[3].flags = 0;
   ops[3].reserved = NULL;
 
@@ -683,11 +675,8 @@
       &(ctx->recv_status_on_client.trailing_metadata);
   ops[1].data.recv_status_on_client.status =
       &(ctx->recv_status_on_client.status);
-  /* not using preallocation for status_details */
   ops[1].data.recv_status_on_client.status_details =
       &(ctx->recv_status_on_client.status_details);
-  ops[1].data.recv_status_on_client.status_details_capacity =
-      &(ctx->recv_status_on_client.status_details_capacity);
   ops[1].flags = 0;
   ops[1].reserved = NULL;
 
@@ -745,17 +734,18 @@
 
 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
     grpc_call *call, grpcsharp_batch_context *ctx, grpc_status_code status_code,
-    const char *status_details, grpc_metadata_array *trailing_metadata,
+    const char *status_details, size_t status_details_len,
+    grpc_metadata_array *trailing_metadata,
     int32_t send_empty_initial_metadata, const char* optional_send_buffer,
     size_t optional_send_buffer_len, uint32_t write_flags) {
   /* TODO: don't use magic number */
   grpc_op ops[3];
   memset(ops, 0, sizeof(ops));
   size_t nops = 1;
+  grpc_slice status_details_slice = grpc_slice_from_copied_buffer(status_details, status_details_len);
   ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   ops[0].data.send_status_from_server.status = status_code;
-  ops[0].data.send_status_from_server.status_details =
-      gpr_strdup(status_details);
+  ops[0].data.send_status_from_server.status_details = &status_details_slice;
   grpcsharp_metadata_array_move(
       &(ctx->send_status_from_server.trailing_metadata), trailing_metadata);
   ops[0].data.send_status_from_server.trailing_metadata_count =
@@ -771,7 +761,7 @@
     ops[nops].data.send_message.send_message = ctx->send_message;
     ops[nops].flags = write_flags;
     ops[nops].reserved = NULL;
-    nops ++;
+    nops++;
   }
   if (send_empty_initial_metadata) {
     ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA;
diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc
index fc339fc..7d6fb19 100644
--- a/src/node/ext/byte_buffer.cc
+++ b/src/node/ext/byte_buffer.cc
@@ -40,6 +40,7 @@
 #include "grpc/slice.h"
 
 #include "byte_buffer.h"
+#include "slice.h"
 
 namespace grpc {
 namespace node {
@@ -54,10 +55,7 @@
 
 grpc_byte_buffer *BufferToByteBuffer(Local<Value> buffer) {
   Nan::HandleScope scope;
-  int length = ::node::Buffer::Length(buffer);
-  char *data = ::node::Buffer::Data(buffer);
-  grpc_slice slice = grpc_slice_malloc(length);
-  memcpy(GRPC_SLICE_START_PTR(slice), data, length);
+  grpc_slice slice = CreateSliceFromBuffer(buffer);
   grpc_byte_buffer *byte_buffer(grpc_raw_byte_buffer_create(&slice, 1));
   grpc_slice_unref(slice);
   return byte_buffer;
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index 96f66a4..244546d 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -48,6 +48,7 @@
 #include "completion_queue.h"
 #include "completion_queue_async_worker.h"
 #include "call_credentials.h"
+#include "slice.h"
 #include "timeval.h"
 
 using std::unique_ptr;
@@ -96,8 +97,7 @@
   return scope.Escape(err);
 }
 
-bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array,
-                         shared_ptr<Resources> resources) {
+bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) {
   HandleScope scope;
   grpc_metadata_array_init(array);
   Local<Array> keys = Nan::GetOwnPropertyNames(metadata).ToLocalChecked();
@@ -113,32 +113,25 @@
   array->metadata = reinterpret_cast<grpc_metadata*>(
       gpr_malloc(array->capacity * sizeof(grpc_metadata)));
   for (unsigned int i = 0; i < keys->Length(); i++) {
-    Local<String> current_key(keys->Get(i)->ToString());
-    Utf8String *utf8_key = new Utf8String(current_key);
-    resources->strings.push_back(unique_ptr<Utf8String>(utf8_key));
+    Local<String> current_key(Nan::To<String>(keys->Get(i)).ToLocalChecked());
     Local<Array> values = Local<Array>::Cast(
         Nan::Get(metadata, current_key).ToLocalChecked());
+    grpc_slice key_slice = grpc_slice_intern(CreateSliceFromString(current_key));
     for (unsigned int j = 0; j < values->Length(); j++) {
       Local<Value> value = Nan::Get(values, j).ToLocalChecked();
       grpc_metadata *current = &array->metadata[array->count];
-      current->key = **utf8_key;
+      current->key = key_slice;
       // Only allow binary headers for "-bin" keys
-      if (grpc_is_binary_header(current->key, strlen(current->key))) {
+      if (grpc_is_binary_header(key_slice)) {
         if (::node::Buffer::HasInstance(value)) {
-          current->value = ::node::Buffer::Data(value);
-          current->value_length = ::node::Buffer::Length(value);
-          PersistentValue *handle = new PersistentValue(value);
-          resources->handles.push_back(unique_ptr<PersistentValue>(handle));
+          current->value = CreateSliceFromBuffer(value);
         } else {
           return false;
         }
       } else {
         if (value->IsString()) {
           Local<String> string_value = Nan::To<String>(value).ToLocalChecked();
-          Utf8String *utf8_value = new Utf8String(string_value);
-          resources->strings.push_back(unique_ptr<Utf8String>(utf8_value));
-          current->value = **utf8_value;
-          current->value_length = string_value->Length();
+          current->value = CreateSliceFromString(string_value);
         } else {
           return false;
         }
@@ -153,40 +146,25 @@
   EscapableHandleScope scope;
   grpc_metadata *metadata_elements = metadata_array->metadata;
   size_t length = metadata_array->count;
-  std::map<const char*, size_t> size_map;
-  std::map<const char*, size_t> index_map;
-
-  for (unsigned int i = 0; i < length; i++) {
-    const char *key = metadata_elements[i].key;
-    if (size_map.count(key)) {
-      size_map[key] += 1;
-    } else {
-      size_map[key] = 1;
-    }
-    index_map[key] = 0;
-  }
   Local<Object> metadata_object = Nan::New<Object>();
   for (unsigned int i = 0; i < length; i++) {
     grpc_metadata* elem = &metadata_elements[i];
-    Local<String> key_string = Nan::New(elem->key).ToLocalChecked();
+    // TODO(murgatroid99): Use zero-copy string construction instead
+    Local<String> key_string = CopyStringFromSlice(elem->key);
     Local<Array> array;
     MaybeLocal<Value> maybe_array = Nan::Get(metadata_object, key_string);
     if (maybe_array.IsEmpty() || !maybe_array.ToLocalChecked()->IsArray()) {
-      array = Nan::New<Array>(size_map[elem->key]);
+      array = Nan::New<Array>(0);
       Nan::Set(metadata_object, key_string, array);
     } else {
       array = Local<Array>::Cast(maybe_array.ToLocalChecked());
     }
-    if (grpc_is_binary_header(elem->key, strlen(elem->key))) {
-      Nan::Set(array, index_map[elem->key],
-               MakeFastBuffer(
-                   Nan::CopyBuffer(elem->value,
-                                   elem->value_length).ToLocalChecked()));
+    if (grpc_is_binary_header(elem->key)) {
+      Nan::Set(array, array->Length(), CreateBufferFromSlice(elem->value));
     } else {
-      Nan::Set(array, index_map[elem->key],
-               Nan::New(elem->value).ToLocalChecked());
+      // TODO(murgatroid99): Use zero-copy string construction instead
+      Nan::Set(array, array->Length(), CopyStringFromSlice(elem->value));
     }
-    index_map[elem->key] += 1;
   }
   return scope.Escape(metadata_object);
 }
@@ -205,8 +183,7 @@
     EscapableHandleScope scope;
     return scope.Escape(Nan::True());
   }
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     if (!value->IsObject()) {
       return false;
     }
@@ -216,7 +193,7 @@
       return false;
     }
     if (!CreateMetadataArray(maybe_metadata.ToLocalChecked(),
-                             &array, resources)) {
+                             &array)) {
       return false;
     }
     out->data.send_initial_metadata.count = array.count;
@@ -246,8 +223,7 @@
     EscapableHandleScope scope;
     return scope.Escape(Nan::True());
   }
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     if (!::node::Buffer::HasInstance(value)) {
       return false;
     }
@@ -263,8 +239,6 @@
     }
     send_message = BufferToByteBuffer(value);
     out->data.send_message.send_message = send_message;
-    PersistentValue *handle = new PersistentValue(value);
-    resources->handles.push_back(unique_ptr<PersistentValue>(handle));
     return true;
   }
   bool IsFinalOp() {
@@ -284,8 +258,7 @@
     EscapableHandleScope scope;
     return scope.Escape(Nan::True());
   }
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     return true;
   }
   bool IsFinalOp() {
@@ -299,12 +272,14 @@
 
 class SendServerStatusOp : public Op {
  public:
+  ~SendServerStatusOp() {
+    grpc_slice_unref(details);
+  }
   Local<Value> GetNodeValue() const {
     EscapableHandleScope scope;
     return scope.Escape(Nan::True());
   }
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     if (!value->IsObject()) {
       return false;
     }
@@ -339,16 +314,15 @@
     Local<String> details = Nan::To<String>(
         maybe_details.ToLocalChecked()).ToLocalChecked();
     grpc_metadata_array array;
-    if (!CreateMetadataArray(metadata, &array, resources)) {
+    if (!CreateMetadataArray(metadata, &array)) {
       return false;
     }
     out->data.send_status_from_server.trailing_metadata_count = array.count;
     out->data.send_status_from_server.trailing_metadata = array.metadata;
     out->data.send_status_from_server.status =
         static_cast<grpc_status_code>(code);
-    Utf8String *str = new Utf8String(details);
-    resources->strings.push_back(unique_ptr<Utf8String>(str));
-    out->data.send_status_from_server.status_details = **str;
+    this->details = CreateSliceFromString(details);
+    out->data.send_status_from_server.status_details = &this->details;
     return true;
   }
   bool IsFinalOp() {
@@ -358,6 +332,9 @@
   std::string GetTypeString() const {
     return "send_status";
   }
+
+ private:
+  grpc_slice details;
 };
 
 class GetMetadataOp : public Op {
@@ -375,8 +352,7 @@
     return scope.Escape(ParseMetadata(&recv_metadata));
   }
 
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     out->data.recv_initial_metadata.recv_initial_metadata = &recv_metadata;
     return true;
   }
@@ -408,8 +384,7 @@
     return scope.Escape(ByteBufferToBuffer(recv_message));
   }
 
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     out->data.recv_message.recv_message = &recv_message;
     return true;
   }
@@ -430,21 +405,16 @@
  public:
   ClientStatusOp() {
     grpc_metadata_array_init(&metadata_array);
-    status_details = NULL;
-    details_capacity = 0;
   }
 
   ~ClientStatusOp() {
     grpc_metadata_array_destroy(&metadata_array);
-    gpr_free(status_details);
   }
 
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     out->data.recv_status_on_client.trailing_metadata = &metadata_array;
     out->data.recv_status_on_client.status = &status;
     out->data.recv_status_on_client.status_details = &status_details;
-    out->data.recv_status_on_client.status_details_capacity = &details_capacity;
     return true;
   }
 
@@ -453,10 +423,8 @@
     Local<Object> status_obj = Nan::New<Object>();
     Nan::Set(status_obj, Nan::New("code").ToLocalChecked(),
                     Nan::New<Number>(status));
-    if (status_details != NULL) {
-      Nan::Set(status_obj, Nan::New("details").ToLocalChecked(),
-               Nan::New(status_details).ToLocalChecked());
-    }
+    Nan::Set(status_obj, Nan::New("details").ToLocalChecked(),
+               CopyStringFromSlice(status_details));
     Nan::Set(status_obj, Nan::New("metadata").ToLocalChecked(),
              ParseMetadata(&metadata_array));
     return scope.Escape(status_obj);
@@ -471,8 +439,7 @@
  private:
   grpc_metadata_array metadata_array;
   grpc_status_code status;
-  char *status_details;
-  size_t details_capacity;
+  grpc_slice status_details;
 };
 
 class ServerCloseResponseOp : public Op {
@@ -482,8 +449,7 @@
     return scope.Escape(Nan::New<Boolean>(cancelled));
   }
 
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     out->data.recv_close_on_server.cancelled = &cancelled;
     return true;
   }
@@ -500,9 +466,8 @@
   int cancelled;
 };
 
-tag::tag(Callback *callback, OpVec *ops,
-         shared_ptr<Resources> resources, Call *call) :
-    callback(callback), ops(ops), resources(resources), call(call){
+tag::tag(Callback *callback, OpVec *ops, Call *call) :
+    callback(callback), ops(ops), call(call){
 }
 
 tag::~tag() {
@@ -650,20 +615,24 @@
       if (channel->GetWrappedChannel() == NULL) {
         return Nan::ThrowError("Call cannot be created from a closed channel");
       }
-      Utf8String method(info[1]);
       double deadline = Nan::To<double>(info[2]).FromJust();
       grpc_channel *wrapped_channel = channel->GetWrappedChannel();
       grpc_call *wrapped_call;
       if (info[3]->IsString()) {
-        Utf8String host_override(info[3]);
+        grpc_slice *host = new grpc_slice;
+        *host = CreateSliceFromString(
+            Nan::To<String>(info[3]).ToLocalChecked());
         wrapped_call = grpc_channel_create_call(
             wrapped_channel, parent_call, propagate_flags,
-            GetCompletionQueue(), *method,
-            *host_override, MillisecondsToTimespec(deadline), NULL);
+            GetCompletionQueue(), CreateSliceFromString(
+                Nan::To<String>(info[1]).ToLocalChecked()),
+            host, MillisecondsToTimespec(deadline), NULL);
+        delete host;
       } else if (info[3]->IsUndefined() || info[3]->IsNull()) {
         wrapped_call = grpc_channel_create_call(
             wrapped_channel, parent_call, propagate_flags,
-            GetCompletionQueue(), *method,
+            GetCompletionQueue(), CreateSliceFromString(
+                Nan::To<String>(info[1]).ToLocalChecked()),
             NULL, MillisecondsToTimespec(deadline), NULL);
       } else {
         return Nan::ThrowTypeError("Call's fourth argument must be a string");
@@ -700,7 +669,6 @@
   }
   Local<Function> callback_func = info[1].As<Function>();
   Call *call = ObjectWrap::Unwrap<Call>(info.This());
-  shared_ptr<Resources> resources(new Resources);
   Local<Object> obj = Nan::To<Object>(info[0]).ToLocalChecked();
   Local<Array> keys = Nan::GetOwnPropertyNames(obj).ToLocalChecked();
   size_t nops = keys->Length();
@@ -745,7 +713,7 @@
       default:
         return Nan::ThrowError("Argument object had an unrecognized key");
     }
-    if (!op->ParseOp(obj->Get(type), &ops[i], resources)) {
+    if (!op->ParseOp(obj->Get(type), &ops[i])) {
       return Nan::ThrowTypeError("Incorrectly typed arguments to startBatch");
     }
     op_vector->push_back(std::move(op));
@@ -753,7 +721,7 @@
   Callback *callback = new Callback(callback_func);
   grpc_call_error error = grpc_call_start_batch(
       call->wrapped_call, &ops[0], nops, new struct tag(
-          callback, op_vector.release(), resources, call), NULL);
+          callback, op_vector.release(), call), NULL);
   if (error != GRPC_CALL_OK) {
     return Nan::ThrowError(nanErrorWithCode("startBatch failed", error));
   }
diff --git a/src/node/ext/call.h b/src/node/ext/call.h
index 31c6566..cffff00 100644
--- a/src/node/ext/call.h
+++ b/src/node/ext/call.h
@@ -51,20 +51,12 @@
 using std::unique_ptr;
 using std::shared_ptr;
 
-typedef Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>> PersistentValue;
-
 v8::Local<v8::Value> nanErrorWithCode(const char *msg, grpc_call_error code);
 
 v8::Local<v8::Value> ParseMetadata(const grpc_metadata_array *metadata_array);
 
-struct Resources {
-  std::vector<unique_ptr<Nan::Utf8String> > strings;
-  std::vector<unique_ptr<PersistentValue> > handles;
-};
-
 bool CreateMetadataArray(v8::Local<v8::Object> metadata,
-                         grpc_metadata_array *array,
-                         shared_ptr<Resources> resources);
+                         grpc_metadata_array *array);
 
 /* Wrapper class for grpc_call structs. */
 class Call : public Nan::ObjectWrap {
@@ -106,8 +98,7 @@
 class Op {
  public:
   virtual v8::Local<v8::Value> GetNodeValue() const = 0;
-  virtual bool ParseOp(v8::Local<v8::Value> value, grpc_op *out,
-                       shared_ptr<Resources> resources) = 0;
+  virtual bool ParseOp(v8::Local<v8::Value> value, grpc_op *out) = 0;
   virtual ~Op();
   v8::Local<v8::Value> GetOpType() const;
   virtual bool IsFinalOp() = 0;
@@ -118,12 +109,10 @@
 
 typedef std::vector<unique_ptr<Op>> OpVec;
 struct tag {
-  tag(Nan::Callback *callback, OpVec *ops,
-      shared_ptr<Resources> resources, Call *call);
+  tag(Nan::Callback *callback, OpVec *ops, Call *call);
   ~tag();
   Nan::Callback *callback;
   OpVec *ops;
-  shared_ptr<Resources> resources;
   Call *call;
 };
 
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index 41f6c29..afcc363 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -206,7 +206,6 @@
     return Nan::ThrowTypeError(
         "The callback's fourth argument must be an object");
   }
-  shared_ptr<Resources> resources(new Resources);
   grpc_status_code code = static_cast<grpc_status_code>(
       Nan::To<uint32_t>(info[0]).FromJust());
   Utf8String details_utf8_str(info[1]);
@@ -214,7 +213,7 @@
   grpc_metadata_array array;
   Local<Object> callback_data = Nan::To<Object>(info[3]).ToLocalChecked();
   if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
-                           &array, resources)){
+                           &array)){
     return Nan::ThrowError("Failed to parse metadata");
   }
   grpc_credentials_plugin_metadata_cb cb =
diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc
index 5bc58b9..c795ff7 100644
--- a/src/node/ext/channel.cc
+++ b/src/node/ext/channel.cc
@@ -280,8 +280,7 @@
       channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline),
       GetCompletionQueue(),
       new struct tag(callback,
-                     ops.release(),
-                     shared_ptr<Resources>(nullptr), NULL));
+                     ops.release(), NULL));
   CompletionQueueNext();
 }
 
diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc
index 614f2e9..95e273f 100644
--- a/src/node/ext/node_grpc.cc
+++ b/src/node/ext/node_grpc.cc
@@ -56,9 +56,12 @@
 #include "server.h"
 #include "completion_queue_async_worker.h"
 #include "server_credentials.h"
+#include "slice.h"
 #include "timeval.h"
 #include "completion_queue.h"
 
+using grpc::node::CreateSliceFromString;
+
 using v8::FunctionTemplate;
 using v8::Local;
 using v8::Value;
@@ -283,10 +286,8 @@
         "headerKeyIsLegal's argument must be a string");
   }
   Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
-  Nan::Utf8String key_utf8_str(key);
-  char *key_str = *key_utf8_str;
   info.GetReturnValue().Set(static_cast<bool>(
-      grpc_header_key_is_legal(key_str, static_cast<size_t>(key->Length()))));
+      grpc_header_key_is_legal(CreateSliceFromString(key))));
 }
 
 NAN_METHOD(MetadataNonbinValueIsLegal) {
@@ -295,11 +296,8 @@
         "metadataNonbinValueIsLegal's argument must be a string");
   }
   Local<String> value = Nan::To<String>(info[0]).ToLocalChecked();
-  Nan::Utf8String value_utf8_str(value);
-  char *value_str = *value_utf8_str;
   info.GetReturnValue().Set(static_cast<bool>(
-      grpc_header_nonbin_value_is_legal(
-          value_str, static_cast<size_t>(value->Length()))));
+      grpc_header_nonbin_value_is_legal(CreateSliceFromString(value))));
 }
 
 NAN_METHOD(MetadataKeyIsBinary) {
@@ -308,10 +306,8 @@
         "metadataKeyIsLegal's argument must be a string");
   }
   Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
-  Nan::Utf8String key_utf8_str(key);
-  char *key_str = *key_utf8_str;
   info.GetReturnValue().Set(static_cast<bool>(
-      grpc_is_binary_header(key_str, static_cast<size_t>(key->Length()))));
+      grpc_is_binary_header(CreateSliceFromString(key))));
 }
 
 static grpc_ssl_roots_override_result get_ssl_roots_override(
diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc
index e83fdc4..ccb55aa 100644
--- a/src/node/ext/server.cc
+++ b/src/node/ext/server.cc
@@ -46,6 +46,7 @@
 #include "grpc/grpc_security.h"
 #include "grpc/support/log.h"
 #include "server_credentials.h"
+#include "slice.h"
 #include "timeval.h"
 
 namespace grpc {
@@ -97,10 +98,11 @@
     }
     Local<Object> obj = Nan::New<Object>();
     Nan::Set(obj, Nan::New("call").ToLocalChecked(), Call::WrapStruct(call));
+    // TODO(murgatroid99): Use zero-copy string construction instead
     Nan::Set(obj, Nan::New("method").ToLocalChecked(),
-             Nan::New(details.method).ToLocalChecked());
+             CopyStringFromSlice(details.method));
     Nan::Set(obj, Nan::New("host").ToLocalChecked(),
-             Nan::New(details.host).ToLocalChecked());
+             CopyStringFromSlice(details.host));
     Nan::Set(obj, Nan::New("deadline").ToLocalChecked(),
              Nan::New<Date>(TimespecToMilliseconds(details.deadline))
                  .ToLocalChecked());
@@ -109,8 +111,7 @@
     return scope.Escape(obj);
   }
 
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     return true;
   }
   bool IsFinalOp() {
@@ -192,7 +193,7 @@
       GetCompletionQueue(),
       GetCompletionQueue(),
       new struct tag(new Callback(info[0].As<Function>()), ops.release(),
-                     shared_ptr<Resources>(nullptr), NULL));
+                     NULL));
   if (error != GRPC_CALL_OK) {
     return Nan::ThrowError(nanErrorWithCode("requestCall failed", error));
   }
@@ -245,7 +246,7 @@
   grpc_server_shutdown_and_notify(
       server->wrapped_server, GetCompletionQueue(),
       new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(),
-                     shared_ptr<Resources>(nullptr), NULL));
+                     NULL));
   CompletionQueueNext();
 }
 
diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc
index cf801e1..bf8b609 100644
--- a/src/node/ext/server_uv.cc
+++ b/src/node/ext/server_uv.cc
@@ -70,8 +70,7 @@
     return Nan::New<External>(reinterpret_cast<void *>(server));
   }
 
-  bool ParseOp(Local<Value> value, grpc_op *out,
-               shared_ptr<Resources> resources) {
+  bool ParseOp(Local<Value> value, grpc_op *out) {
     return true;
   }
   bool IsFinalOp() {
@@ -119,8 +118,7 @@
 
     grpc_server_shutdown_and_notify(
         this->wrapped_server, GetCompletionQueue(),
-        new struct tag(new Callback(**shutdown_callback), ops.release(),
-                       shared_ptr<Resources>(nullptr), NULL));
+        new struct tag(new Callback(**shutdown_callback), ops.release(), NULL));
     grpc_server_cancel_all_calls(this->wrapped_server);
     CompletionQueueNext();
     this->wrapped_server = NULL;
diff --git a/src/node/ext/slice.cc b/src/node/ext/slice.cc
new file mode 100644
index 0000000..98a80b3
--- /dev/null
+++ b/src/node/ext/slice.cc
@@ -0,0 +1,102 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <node.h>
+#include <nan.h>
+#include <grpc/slice.h>
+#include <grpc/support/alloc.h>
+
+#include "slice.h"
+#include "byte_buffer.h"
+
+namespace grpc {
+namespace node {
+
+using Nan::Persistent;
+
+using v8::Local;
+using v8::String;
+using v8::Value;
+
+namespace {
+void SliceFreeCallback(char *data, void *hint) {
+  grpc_slice *slice = reinterpret_cast<grpc_slice*>(hint);
+  grpc_slice_unref(*slice);
+  delete slice;
+}
+
+void string_destroy_func(void *user_data) {
+  delete reinterpret_cast<Nan::Utf8String*>(user_data);
+}
+
+void buffer_destroy_func(void *user_data) {
+  delete reinterpret_cast<PersistentValue*>(user_data);
+}
+} // namespace
+
+grpc_slice CreateSliceFromString(const Local<String> source) {
+  Nan::HandleScope scope;
+  Nan::Utf8String *utf8_value = new Nan::Utf8String(source);
+  return grpc_slice_new_with_user_data(**utf8_value, source->Length(),
+                                       string_destroy_func, utf8_value);
+}
+
+grpc_slice CreateSliceFromBuffer(const Local<Value> source) {
+  // Prerequisite: ::node::Buffer::HasInstance(source)
+  Nan::HandleScope scope;
+  return grpc_slice_new_with_user_data(::node::Buffer::Data(source),
+                                       ::node::Buffer::Length(source),
+                                       buffer_destroy_func,
+                                       new PersistentValue(source));
+}
+Local<String> CopyStringFromSlice(const grpc_slice slice) {
+  Nan::EscapableHandleScope scope;
+  if (GRPC_SLICE_LENGTH(slice) == 0) {
+    return scope.Escape(Nan::EmptyString());
+  }
+  return scope.Escape(Nan::New<String>(
+      const_cast<char *>(reinterpret_cast<const char *>(GRPC_SLICE_START_PTR(slice))),
+      GRPC_SLICE_LENGTH(slice)).ToLocalChecked());
+}
+
+Local<Value> CreateBufferFromSlice(const grpc_slice slice) {
+  Nan::EscapableHandleScope scope;
+  grpc_slice *slice_ptr = new grpc_slice;
+  *slice_ptr = grpc_slice_ref(slice);
+  return scope.Escape(MakeFastBuffer(Nan::NewBuffer(
+      const_cast<char *>(reinterpret_cast<const char *>(GRPC_SLICE_START_PTR(*slice_ptr))),
+      GRPC_SLICE_LENGTH(*slice_ptr), SliceFreeCallback, slice_ptr).ToLocalChecked()));
+}
+
+}  // namespace node
+}  // namespace grpc
diff --git a/src/node/ext/slice.h b/src/node/ext/slice.h
new file mode 100644
index 0000000..7dcb1bd
--- /dev/null
+++ b/src/node/ext/slice.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <node.h>
+#include <nan.h>
+#include <grpc/slice.h>
+
+namespace grpc {
+namespace node {
+
+typedef Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>> PersistentValue;
+
+grpc_slice CreateSliceFromString(const v8::Local<v8::String> source);
+
+grpc_slice CreateSliceFromBuffer(const v8::Local<v8::Value> source);
+
+v8::Local<v8::String> CopyStringFromSlice(const grpc_slice slice);
+
+v8::Local<v8::Value> CreateBufferFromSlice(const grpc_slice slice);
+
+}  // namespace node
+}  // namespace grpc
diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json
index 812f495..8376339 100644
--- a/src/node/health_check/package.json
+++ b/src/node/health_check/package.json
@@ -1,6 +1,6 @@
 {
   "name": "grpc-health-check",
-  "version": "1.1.2",
+  "version": "1.2.0-dev",
   "author": "Google Inc.",
   "description": "Health check service for use with gRPC",
   "repository": {
@@ -15,7 +15,7 @@
     }
   ],
   "dependencies": {
-    "grpc": "^1.1.2",
+    "grpc": "^1.2.0-dev",
     "lodash": "^3.9.3",
     "google-protobuf": "^3.0.0"
   },
diff --git a/src/node/tools/package.json b/src/node/tools/package.json
index 650b06e..53dd53f 100644
--- a/src/node/tools/package.json
+++ b/src/node/tools/package.json
@@ -1,6 +1,6 @@
 {
   "name": "grpc-tools",
-  "version": "1.1.2",
+  "version": "1.2.0-dev",
   "author": "Google Inc.",
   "description": "Tools for developing with gRPC on Node.js",
   "homepage": "http://www.grpc.io/",
diff --git "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec" "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
index 8d6c408..1a3b775 100644
--- "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
+++ "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
@@ -42,7 +42,7 @@
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler-gRPCPlugin'
-  v = '1.1.2'
+  v = '1.2.0-dev'
   s.version  = v
   s.summary  = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
   s.description = <<-DESC
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m
index 2397c92..c533c5a 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.m
@@ -200,7 +200,7 @@
   return grpc_channel_create_call(_unmanagedChannel,
                                   NULL, GRPC_PROPAGATE_DEFAULTS,
                                   queue.unmanagedQueue,
-                                  path.UTF8String,
+                                  grpc_slice_from_copied_string(path.UTF8String),
                                   NULL, // Passing NULL for host
                                   gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 }
diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
index 45d0aae..9f1901a 100644
--- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
+++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
@@ -194,7 +194,7 @@
 
 @implementation GRPCOpRecvStatus{
   grpc_status_code _statusCode;
-  char *_details;
+  grpc_slice _details;
   size_t _detailsCapacity;
   grpc_metadata_array _trailers;
 }
@@ -208,7 +208,6 @@
     _op.op = GRPC_OP_RECV_STATUS_ON_CLIENT;
     _op.data.recv_status_on_client.status = &_statusCode;
     _op.data.recv_status_on_client.status_details = &_details;
-    _op.data.recv_status_on_client.status_details_capacity = &_detailsCapacity;
     grpc_metadata_array_init(&_trailers);
     _op.data.recv_status_on_client.trailing_metadata = &_trailers;
     if (handler) {
@@ -216,11 +215,15 @@
       __weak typeof(self) weakSelf = self;
       _handler = ^{
         __strong typeof(self) strongSelf = weakSelf;
-        NSError *error = [NSError grpc_errorFromStatusCode:strongSelf->_statusCode
-                                                   details:strongSelf->_details];
-        NSDictionary *trailers = [NSDictionary
-                                  grpc_dictionaryFromMetadataArray:strongSelf->_trailers];
-        handler(error, trailers);
+        if (strongSelf) {
+          char *details = grpc_slice_to_c_string(strongSelf->_details);
+          NSError *error = [NSError grpc_errorFromStatusCode:strongSelf->_statusCode
+                                                     details:details];
+          NSDictionary *trailers = [NSDictionary
+                                    grpc_dictionaryFromMetadataArray:strongSelf->_trailers];
+          handler(error, trailers);
+          gpr_free(details);
+        }
       };
     }
   }
@@ -229,7 +232,7 @@
 
 - (void)dealloc {
   grpc_metadata_array_destroy(&_trailers);
-  gpr_free(_details);
+  grpc_slice_unref(_details);
 }
 
 @end
diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
index 7477da7..feb2bb5 100644
--- a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
+++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
@@ -47,12 +47,12 @@
 @implementation NSData (GRPCMetadata)
 + (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata {
   // TODO(jcanizales): Should we use a non-copy constructor?
-  return [self dataWithBytes:metadata->value length:metadata->value_length];
+  return [self dataWithBytes:GRPC_SLICE_START_PTR(metadata->value)
+                      length:GRPC_SLICE_LENGTH(metadata->value)];
 }
 
 - (void)grpc_initMetadata:(grpc_metadata *)metadata {
-  metadata->value = self.bytes;
-  metadata->value_length = self.length;
+  metadata->value = grpc_slice_from_copied_buffer(self.bytes, self.length);
 }
 @end
 
@@ -67,15 +67,14 @@
 
 @implementation NSString (GRPCMetadata)
 + (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata {
-  return [[self alloc] initWithBytes:metadata->value
-                              length:metadata->value_length
+  return [[self alloc] initWithBytes:GRPC_SLICE_START_PTR(metadata->value)
+                              length:GRPC_SLICE_LENGTH(metadata->value)
                             encoding:NSASCIIStringEncoding];
 }
 
 // Precondition: This object contains only ASCII characters.
 - (void)grpc_initMetadata:(grpc_metadata *)metadata {
-  metadata->value = self.UTF8String;
-  metadata->value_length = self.length;
+  metadata->value = grpc_slice_from_copied_string(self.UTF8String);
 }
 @end
 
@@ -89,7 +88,10 @@
 + (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count {
   NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count];
   for (grpc_metadata *entry = entries; entry < entries + count; entry++) {
-    NSString *name = [NSString stringWithCString:entry->key encoding:NSASCIIStringEncoding];
+    char *key = grpc_slice_to_c_string(entry->key);
+    NSString *name = [NSString stringWithCString:key
+                                        encoding:NSASCIIStringEncoding];
+    gpr_free(key);
     if (!name || metadata[name]) {
       // Log if name is nil?
       continue;
@@ -112,7 +114,7 @@
   grpc_metadata *current = metadata;
   for (NSString* key in self) {
     id value = self[key];
-    current->key = key.UTF8String;
+    current->key = grpc_slice_from_copied_string(key.UTF8String);
     if ([value respondsToSelector:@selector(grpc_initMetadata:)]) {
       [value grpc_initMetadata:current];
     } else {
diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h
index f7e9604..e569faa 100644
--- a/src/objective-c/GRPCClient/private/version.h
+++ b/src/objective-c/GRPCClient/private/version.h
@@ -38,4 +38,4 @@
 // `tools/buildgen/generate_projects.sh`.
 
 
-#define GRPC_OBJC_VERSION_STRING @"1.1.2"
+#define GRPC_OBJC_VERSION_STRING @"1.2.0-dev"
diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
index 01612a8..1e0c802 100644
--- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
+++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
@@ -206,7 +206,7 @@
              inDomains:NSUserDomainMask] lastObject];
   NSLog(@"Documents directory: %@", url);
   [Cronet start];
-  [Cronet startNetLogToFile:@"Documents/cronet_netlog.json" logBytes:YES];
+  [Cronet startNetLogToFile:@"cronet_netlog.json" logBytes:YES];
 }
 
 // The tearDown() function is run after all test cases finish running
diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
index 43b91a0..e97f3d2 100644
--- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
+++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
@@ -32,13 +32,13 @@
  */
 
 #import <XCTest/XCTest.h>
-#import <sys/socket.h>
 #import <netinet/in.h>
+#import <sys/socket.h>
 
 #import <Cronet/Cronet.h>
-#import <grpc/support/host_port.h>
-#import <grpc/grpc_cronet.h>
 #import <grpc/grpc.h>
+#import <grpc/grpc_cronet.h>
+#import <grpc/support/host_port.h>
 #import "test/core/end2end/cq_verifier.h"
 #import "test/core/util/port.h"
 
@@ -49,16 +49,19 @@
 #import "src/core/lib/support/env.h"
 #import "src/core/lib/support/string.h"
 #import "src/core/lib/support/tmpfile.h"
+#import "test/core/end2end/data/ssl_test_data.h"
 #import "test/core/util/test_config.h"
 
+#import <BoringSSL/openssl/ssl.h>
+
 static void drain_cq(grpc_completion_queue *cq) {
   grpc_event ev;
   do {
-    ev = grpc_completion_queue_next(cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL);
+    ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5),
+                                    NULL);
   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
 }
 
-
 @interface CronetUnitTests : XCTestCase
 
 @end
@@ -68,47 +71,99 @@
 + (void)setUp {
   [super setUp];
 
-/***  FILE *roots_file;
-  size_t roots_size = strlen(test_root_cert);*/
-
   char *argv[] = {"CoreCronetEnd2EndTests"};
   grpc_test_init(1, argv);
 
   grpc_init();
 
   [Cronet setHttp2Enabled:YES];
+  [Cronet setSslKeyLogFileName:@"Documents/key"];
+  [Cronet enableTestCertVerifierForTesting];
   NSURL *url = [[[NSFileManager defaultManager]
-                 URLsForDirectory:NSDocumentDirectory
-                 inDomains:NSUserDomainMask] lastObject];
+      URLsForDirectory:NSDocumentDirectory
+             inDomains:NSUserDomainMask] lastObject];
   NSLog(@"Documents directory: %@", url);
   [Cronet start];
   [Cronet startNetLogToFile:@"Documents/cronet_netlog.json" logBytes:YES];
+
+  init_ssl();
 }
 
 + (void)tearDown {
   grpc_shutdown();
+  cleanup_ssl();
 
   [super tearDown];
 }
 
+void init_ssl(void) {
+  SSL_load_error_strings();
+  OpenSSL_add_ssl_algorithms();
+}
+
+void cleanup_ssl(void) { EVP_cleanup(); }
+
+int alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
+            const unsigned char *in, unsigned int inlen, void *arg) {
+  // Always select "h2" as the ALPN protocol to be used
+  *out = (const unsigned char *)"h2";
+  *outlen = 2;
+  return SSL_TLSEXT_ERR_OK;
+}
+
+void init_ctx(SSL_CTX *ctx) {
+  // Install server certificate
+  BIO *pem = BIO_new_mem_buf((void *)test_server1_cert,
+                             (int)strlen(test_server1_cert));
+  X509 *cert = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
+  SSL_CTX_use_certificate(ctx, cert);
+  X509_free(cert);
+  BIO_free(pem);
+
+  // Install server private key
+  pem =
+      BIO_new_mem_buf((void *)test_server1_key, (int)strlen(test_server1_key));
+  EVP_PKEY *key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
+  SSL_CTX_use_PrivateKey(ctx, key);
+  EVP_PKEY_free(key);
+  BIO_free(pem);
+
+  // Select cipher suite
+  SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256");
+
+  // Select ALPN protocol
+  SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, NULL);
+}
+
+unsigned int parse_h2_length(const char *field) {
+  return ((unsigned int)(unsigned char)(field[0])) * 65536 +
+         ((unsigned int)(unsigned char)(field[1])) * 256 +
+         ((unsigned int)(unsigned char)(field[2]));
+}
+
 - (void)testInternalError {
   grpc_call *c;
   grpc_slice request_payload_slice =
-  grpc_slice_from_copied_string("hello world");
+      grpc_slice_from_copied_string("hello world");
   grpc_byte_buffer *request_payload =
-  grpc_raw_byte_buffer_create(&request_payload_slice, 1);
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
-  grpc_metadata meta_c[2] = {
-    {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-    {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+      grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
 
   int port = grpc_pick_unused_port_or_die();
   char *addr;
   gpr_join_host_port(&addr, "127.0.0.1", port);
   grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
-  cronet_engine *cronetEngine = [Cronet getGlobalEngine];
-  grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr,
-                                                           NULL, NULL);
+  stream_engine *cronetEngine = [Cronet getGlobalEngine];
+  grpc_channel *client =
+      grpc_cronet_secure_channel_create(cronetEngine, addr, NULL, NULL);
 
   cq_verifier *cqv = cq_verifier_create(cq);
   grpc_op ops[6];
@@ -120,12 +175,11 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
-  c = grpc_channel_create_call(
-                               client, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo",
-                               NULL, deadline, NULL);
+  c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+                               grpc_slice_from_static_string("/foo"), NULL,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -164,35 +218,40 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
-  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void*)1, NULL);
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
   GPR_ASSERT(GRPC_CALL_OK == error);
 
-  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-    int sl = socket(AF_INET, SOCK_STREAM, 0);
-    GPR_ASSERT(sl >= 0);
-    struct sockaddr_in s_addr;
-    memset(&s_addr, 0, sizeof(s_addr));
-    s_addr.sin_family = AF_INET;
-    s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-    s_addr.sin_port = htons(port);
-    bind(sl, (struct sockaddr*)&s_addr, sizeof(s_addr));
-    listen(sl, 5);
-    int s = accept(sl, NULL, NULL);
-    sleep(1);
-    close(s);
-    close(sl);
-  });
+  dispatch_async(
+      dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        int sl = socket(AF_INET, SOCK_STREAM, 0);
+        GPR_ASSERT(sl >= 0);
 
-  CQ_EXPECT_COMPLETION(cqv, (void*)1, 1);
+        // Make and TCP endpoint to accept the connection
+        struct sockaddr_in s_addr;
+        memset(&s_addr, 0, sizeof(s_addr));
+        s_addr.sin_family = AF_INET;
+        s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+        s_addr.sin_port = htons(port);
+        GPR_ASSERT(0 == bind(sl, (struct sockaddr *)&s_addr, sizeof(s_addr)));
+        GPR_ASSERT(0 == listen(sl, 5));
+        int s = accept(sl, NULL, NULL);
+        GPR_ASSERT(s >= 0);
+
+        // Close the connection after 1 second to trigger Cronet's on_failed()
+        sleep(1);
+        close(s);
+        close(sl);
+      });
+
+  CQ_EXPECT_COMPLETION(cqv, (void *)1, 1);
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -204,11 +263,199 @@
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(response_payload_recv);
-  
+
   grpc_channel_destroy(client);
   grpc_completion_queue_shutdown(cq);
   drain_cq(cq);
   grpc_completion_queue_destroy(cq);
 }
 
+- (void)packetCoalescing:(BOOL)useCoalescing {
+  grpc_arg arg;
+  arg.key = GRPC_ARG_USE_CRONET_PACKET_COALESCING;
+  arg.type = GRPC_ARG_INTEGER;
+  arg.value.integer = useCoalescing ? 1 : 0;
+  grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
+  grpc_call *c;
+  grpc_slice request_payload_slice =
+      grpc_slice_from_copied_string("hello world");
+  grpc_byte_buffer *request_payload =
+      grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+
+  int port = grpc_pick_unused_port_or_die();
+  char *addr;
+  gpr_join_host_port(&addr, "127.0.0.1", port);
+  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+  stream_engine *cronetEngine = [Cronet getGlobalEngine];
+  grpc_channel *client =
+      grpc_cronet_secure_channel_create(cronetEngine, addr, args, NULL);
+
+  cq_verifier *cqv = cq_verifier_create(cq);
+  grpc_op ops[6];
+  grpc_op *op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_byte_buffer *response_payload_recv = NULL;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  grpc_slice details;
+
+  c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+                               grpc_slice_from_static_string("/foo"), NULL,
+                               deadline, NULL);
+  GPR_ASSERT(c);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  __weak XCTestExpectation *expectation =
+      [self expectationWithDescription:@"Coalescing"];
+
+  dispatch_async(
+      dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        int sl = socket(AF_INET, SOCK_STREAM, 0);
+        GPR_ASSERT(sl >= 0);
+        struct sockaddr_in s_addr;
+        memset(&s_addr, 0, sizeof(s_addr));
+        s_addr.sin_family = AF_INET;
+        s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+        s_addr.sin_port = htons(port);
+        GPR_ASSERT(0 == bind(sl, (struct sockaddr *)&s_addr, sizeof(s_addr)));
+        GPR_ASSERT(0 == listen(sl, 5));
+        int s = accept(sl, NULL, NULL);
+        GPR_ASSERT(s >= 0);
+        struct timeval tv;
+        tv.tv_sec = 2;
+        tv.tv_usec = 0;
+        setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+
+        // Make an TLS endpoint to receive Cronet's transmission
+        SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_server_method());
+        init_ctx(ctx);
+        SSL *ssl = SSL_new(ctx);
+        SSL_set_fd(ssl, s);
+        SSL_accept(ssl);
+
+        const char magic[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
+
+        char buf[4096];
+        long len;
+        BOOL coalesced = NO;
+        while ((len = SSL_read(ssl, buf, sizeof(buf))) > 0) {
+          gpr_log(GPR_DEBUG, "Read len: %ld", len);
+
+          // Analyze the HTTP/2 frames in the same TLS PDU to identify if
+          // coalescing is successful
+          unsigned int p = 0;
+          while (p < len) {
+            if (len - p >= 24 && 0 == memcmp(&buf[p], magic, 24)) {
+              p += 24;
+              continue;
+            }
+
+            if (buf[p + 3] == 0 &&                   // Type is DATA
+                parse_h2_length(&buf[p]) == 0x10 &&  // Length is correct
+                (buf[p + 4] & 1) != 0 &&             // EOS bit is set
+                0 == memcmp("hello world", &buf[p + 14],
+                            11)) {  // Message is correct
+              coalesced = YES;
+              break;
+            }
+            p += (parse_h2_length(&buf[p]) + 9);
+          }
+          if (coalesced) {
+            break;
+          }
+        }
+
+        XCTAssert(coalesced == useCoalescing);
+        SSL_free(ssl);
+        SSL_CTX_free(ctx);
+        close(s);
+        close(sl);
+        [expectation fulfill];
+      });
+
+  // Guarantees that server is listening to the port before client connects.
+  sleep(1);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 2;
+  op->data.send_initial_metadata.metadata = meta_c;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_MESSAGE;
+  op->data.send_message.send_message = request_payload;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_MESSAGE;
+  op->data.recv_message.recv_message = &response_payload_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, (void *)1, 1);
+  cq_verify(cqv);
+
+  grpc_slice_unref(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  grpc_call_destroy(c);
+
+  cq_verifier_destroy(cqv);
+
+  grpc_byte_buffer_destroy(request_payload);
+  grpc_byte_buffer_destroy(response_payload_recv);
+
+  grpc_channel_destroy(client);
+  grpc_completion_queue_shutdown(cq);
+  drain_cq(cq);
+  grpc_completion_queue_destroy(cq);
+
+  [self waitForExpectationsWithTimeout:4 handler:nil];
+}
+
+- (void)testPacketCoalescing {
+  [self packetCoalescing:YES];
+  [self packetCoalescing:NO];
+}
+
 @end
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index c3935ce..5584246 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -169,6 +169,8 @@
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 
+#ifndef GRPC_COMPILE_WITH_CRONET
+// TODO (mxyan): Fix this test
 - (void)testResponsesOverMaxSizeFailWithActionableMessage {
   XCTAssertNotNil(self.class.host);
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"];
@@ -189,6 +191,7 @@
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
+#endif
 
 - (void)testResponsesOver4MBAreAcceptedIfOptedIn {
   XCTAssertNotNil(self.class.host);
diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
index 4a6b332..32b35ef 100644
--- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
+++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
@@ -1474,6 +1474,7 @@
 					"$(inherited)",
 					"GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1",
 					"GRPC_COMPILE_WITH_CRONET=1",
+					"GRPC_CRONET_WITH_PACKET_COALESCING=1",
 				);
 				INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 9.3;
diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
index d1d616c..49dc3fa 100644
--- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
+++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
@@ -49,6 +49,26 @@
                </Test>
             </SkippedTests>
          </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4"
+               BuildableName = "CoreCronetEnd2EndTests.xctest"
+               BlueprintName = "CoreCronetEnd2EndTests"
+               ReferencedContainer = "container:Tests.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "5EAD6D231E27047400002378"
+               BuildableName = "CronetUnitTests.xctest"
+               BlueprintName = "CronetUnitTests"
+               ReferencedContainer = "container:Tests.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
       </Testables>
       <MacroExpansion>
          <BuildableReference
diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh
index 81c2885..677459e 100755
--- a/src/objective-c/tests/run_tests.sh
+++ b/src/objective-c/tests/run_tests.sh
@@ -61,3 +61,11 @@
     test \
     | egrep "$XCODEBUILD_FILTER" \
     | egrep -v "(GPBDictionary|GPBArray)" -
+
+xcodebuild \
+    -workspace Tests.xcworkspace \
+    -scheme InteropTestsRemoteWithCronet \
+    -destination name="iPhone 6" \
+    test \
+    | egrep "$XCODEBUILD_FILTER" \
+    | egrep -v "(GPBDictionary|GPBArray)" -
diff --git a/src/php/README.md b/src/php/README.md
index 320220d..821ea16 100644
--- a/src/php/README.md
+++ b/src/php/README.md
@@ -12,24 +12,40 @@
 * `composer`
 * `phpunit` (optional)
 
-**Ubuntu/Debian:**
+**Install PHP and PECL on Ubuntu/Debian:**
+
+For PHP5:
+
 ```sh
-$ sudo apt-get install php5 php5-dev
+$ sudo apt-get install php5 php5-dev php-pear phpunit
 ```
 
-**PEAR/PECL:**
+For PHP7:
+
+```sh
+$ sudo apt-get install php7.0 php7.0-dev php-pear phpunit
+```
+
+**Install PHP and PECL on CentOS/RHEL 7:**
+```sh
+$ sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
+$ sudo rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
+$ sudo yum install php56w php56w-devel php-pear phpunit gcc zlib-devel
+```
+
+**Install PECL on Mac:**
 ```sh
 $ curl -O http://pear.php.net/go-pear.phar
 $ sudo php -d detect_unicode=0 go-pear.phar
 ```
 
-**Composer:**
+**Install Composer (Linux or Mac):**
 ```sh
 $ curl -sS https://getcomposer.org/installer | php
 $ sudo mv composer.phar /usr/local/bin/composer
 ```
 
-**PHPUnit:**
+**Install PHPUnit (Linux or Mac):**
 ```sh
 $ wget https://phar.phpunit.de/phpunit-old.phar
 $ chmod +x phpunit-old.phar
@@ -48,6 +64,18 @@
 extension directory. You should be able to run the [unit tests](#unit-tests),
 with the PHP extension installed.
 
+Note: For users on CentOS/RHEL 6, unfortunately this step won't work. Please
+follow the instructions below to compile the extension from source.
+
+
+**Update php.ini**
+
+Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini`
+
+```sh
+extension=grpc.so
+```
+
 
 **Add the gRPC PHP library as a Composer dependency**
 
@@ -55,7 +83,7 @@
 
 ```
   "require": {
-    "grpc/grpc": "v1.0.0"
+    "grpc/grpc": "v1.1.0"
   }
 ```
 
@@ -96,14 +124,6 @@
 $ sudo make install
 ```
 
-### Update php.ini
-
-Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini`
-
-```sh
-extension=grpc.so
-```
-
 ## Unit Tests
 
 You will need the source code to run tests
@@ -138,7 +158,7 @@
 ### Protobuf compiler
 
 Again if you don't have it already, you need to install the protobuf compiler
-`protoc`, version 3.1.0+.
+`protoc`, version 3.2.0+.
 
 If `protoc` hasn't been installed, you can download the `protoc` binaries from
 [the protocol buffers Github repository](https://github.com/google/protobuf/releases).
@@ -209,6 +229,7 @@
 ```
 
 Add this line to your `php.ini` file, e.g. `/etc/php5/apache2/php.ini`
+or `/etc/php/7.0/apache2/php.ini`
 
 ```sh
 extension=grpc.so
@@ -235,7 +256,7 @@
 $ composer install
 ```
 
-Make sure you have generated the client stub `math.php`
+Make sure you have generated the client stubs
 
 ```sh
 $ ./bin/generate_proto_php.sh
@@ -247,11 +268,10 @@
 $ cp tests/generated_code/math_client.php /var/www/html
 ```
 
-You may have to fix the first two lines to point the includes to your installation:
+You may have to fix the first line to point the includes to your installation:
 
 ```php
 include 'vendor/autoload.php';
-include 'tests/generated_code/math.php';
 ```
 
 Connect to `localhost/math_client.php` in your browser, or run this from command line:
@@ -266,6 +286,10 @@
 
 ```sh
 $ sudo apt-get install nginx php5-fpm
+
+OR
+
+$ sudo apt-get install nginx php7.0-fpm
 ```
 
 Add this line to your `php.ini` file, e.g. `/etc/php5/fpm/php.ini`
@@ -305,7 +329,7 @@
 $ composer install
 ```
 
-Make sure you have generated the client stub `math.php`
+Make sure you have generated the client stubs
 
 ```sh
 $ ./bin/generate_proto_php.sh
@@ -317,11 +341,10 @@
 $ cp tests/generated_code/math_client.php /var/www/html
 ```
 
-You may have to fix the first two lines to point the includes to your installation:
+You may have to fix the first line to point the includes to your installation:
 
 ```php
 include 'vendor/autoload.php';
-include 'tests/generated_code/math.php';
 ```
 
 Connect to `localhost/math_client.php` in your browser, or run this from command line:
diff --git a/src/php/composer.json b/src/php/composer.json
index faf2049..8528304 100644
--- a/src/php/composer.json
+++ b/src/php/composer.json
@@ -1,22 +1,20 @@
 {
-  "name": "grpc/grpc",
-  "type": "library",
-  "description": "gRPC library for PHP",
-  "keywords": ["rpc"],
-  "homepage": "http://grpc.io",
+  "name": "grpc/grpc-dev",
+  "description": "gRPC library for PHP - for Developement use only",
   "license": "BSD-3-Clause",
-  "version": "1.1.2",
+  "version": "1.2.0",
   "require": {
     "php": ">=5.5.0",
-    "ext-grpc": "*",
-    "google/protobuf": "v3.1.0-alpha-1"
+    "google/protobuf": "v3.1.0"
   },
   "require-dev": {
     "google/auth": "v0.9"
   },
   "autoload": {
     "psr-4": {
-      "Grpc\\": "lib/Grpc/"
+      "Grpc\\": "lib/Grpc/",
+      "": ["tests/interop/",
+           "tests/generated_code/"]
     }
   }
 }
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index be11e63..48a374f 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -100,11 +100,12 @@
   grpc_metadata *elem;
   for (i = 0; i < count; i++) {
     elem = &elements[i];
-    key_len = strlen(elem->key);
+    key_len = GRPC_SLICE_LENGTH(elem->key);
     str_key = ecalloc(key_len + 1, sizeof(char));
-    memcpy(str_key, elem->key, key_len);
-    str_val = ecalloc(elem->value_length + 1, sizeof(char));
-    memcpy(str_val, elem->value, elem->value_length);
+    memcpy(str_key, GRPC_SLICE_START_PTR(elem->key), key_len);
+    str_val = ecalloc(GRPC_SLICE_LENGTH(elem->value) + 1, sizeof(char));
+    memcpy(str_val, GRPC_SLICE_START_PTR(elem->value),
+           GRPC_SLICE_LENGTH(elem->value));
     if (php_grpc_zend_hash_find(array_hash, str_key, key_len, (void **)&data)
         == SUCCESS) {
       if (Z_TYPE_P(data) != IS_ARRAY) {
@@ -115,13 +116,14 @@
         efree(str_val);
         return NULL;
       }
-      php_grpc_add_next_index_stringl(data, str_val, elem->value_length,
+      php_grpc_add_next_index_stringl(data, str_val,
+                                      GRPC_SLICE_LENGTH(elem->value),
                                       false);
     } else {
       PHP_GRPC_MAKE_STD_ZVAL(inner_array);
       array_init(inner_array);
       php_grpc_add_next_index_stringl(inner_array, str_val,
-                                      elem->value_length, false);
+                                      GRPC_SLICE_LENGTH(elem->value), false);
       add_assoc_zval(array, str_key, inner_array);
     }
   }
@@ -164,7 +166,7 @@
     if (key_type1 != HASH_KEY_IS_STRING) {
       return false;
     }
-    if (!grpc_header_key_is_legal(key1, strlen(key1))) {
+    if (!grpc_header_key_is_legal(grpc_slice_from_static_string(key1))) {
       return false;
     }
     inner_array_hash = Z_ARRVAL_P(inner_array);
@@ -172,9 +174,10 @@
       if (Z_TYPE_P(value) != IS_STRING) {
         return false;
       }
-      metadata->metadata[metadata->count].key = key1;
-      metadata->metadata[metadata->count].value = Z_STRVAL_P(value);
-      metadata->metadata[metadata->count].value_length = Z_STRLEN_P(value);
+      metadata->metadata[metadata->count].key =
+        grpc_slice_from_copied_string(key1);
+      metadata->metadata[metadata->count].value =
+        grpc_slice_from_copied_buffer(Z_STRVAL_P(value), Z_STRLEN_P(value));
       metadata->count += 1;
     PHP_GRPC_HASH_FOREACH_END()
   PHP_GRPC_HASH_FOREACH_END()
@@ -229,10 +232,16 @@
   }
   add_property_zval(getThis(), "channel", channel_obj);
   wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj);
+  grpc_slice method_slice = grpc_slice_from_copied_string(method);
+  grpc_slice host_slice = host_override != NULL ?
+      grpc_slice_from_copied_string(host_override) : grpc_empty_slice();
   call->wrapped =
     grpc_channel_create_call(channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS,
-                             completion_queue, method, host_override,
+                             completion_queue, method_slice,
+                             host_override != NULL ? &host_slice : NULL,
                              deadline->wrapped, NULL);
+  grpc_slice_unref(method_slice);
+  grpc_slice_unref(host_slice);
   call->owned = true;
 }
 
@@ -267,8 +276,8 @@
   grpc_metadata_array recv_metadata;
   grpc_metadata_array recv_trailing_metadata;
   grpc_status_code status;
-  char *status_details = NULL;
-  size_t status_details_capacity = 0;
+  grpc_slice recv_status_details = grpc_empty_slice();
+  grpc_slice send_status_details = grpc_empty_slice();
   grpc_byte_buffer *message;
   int cancelled;
   grpc_call_error error;
@@ -380,8 +389,10 @@
                                1 TSRMLS_CC);
           goto cleanup;
         }
+        send_status_details = grpc_slice_from_copied_string(
+          Z_STRVAL_P(inner_value));
         ops[op_num].data.send_status_from_server.status_details =
-            Z_STRVAL_P(inner_value);
+          &send_status_details;
       } else {
         zend_throw_exception(spl_ce_InvalidArgumentException,
                              "String status details is required",
@@ -401,9 +412,7 @@
           &recv_trailing_metadata;
       ops[op_num].data.recv_status_on_client.status = &status;
       ops[op_num].data.recv_status_on_client.status_details =
-          &status_details;
-      ops[op_num].data.recv_status_on_client.status_details_capacity =
-          &status_details_capacity;
+          &recv_status_details;
       break;
     case GRPC_OP_RECV_CLOSE_ON_SERVER:
       ops[op_num].data.recv_close_on_server.cancelled = &cancelled;
@@ -475,8 +484,10 @@
 #endif
       PHP_GRPC_DELREF(array);
       add_property_long(recv_status, "code", status);
-      php_grpc_add_property_string(recv_status, "details", status_details,
+      char *status_details_text = grpc_slice_to_c_string(recv_status_details);
+      php_grpc_add_property_string(recv_status, "details", status_details_text,
                                    true);
+      gpr_free(status_details_text);
       add_property_zval(result, "status", recv_status);
       PHP_GRPC_DELREF(recv_status);
       PHP_GRPC_FREE_STD_ZVAL(recv_status);
@@ -494,9 +505,8 @@
   grpc_metadata_array_destroy(&trailing_metadata);
   grpc_metadata_array_destroy(&recv_metadata);
   grpc_metadata_array_destroy(&recv_trailing_metadata);
-  if (status_details != NULL) {
-    gpr_free(status_details);
-  }
+  grpc_slice_unref(recv_status_details);
+  grpc_slice_unref(send_status_details);
   for (int i = 0; i < op_num; i++) {
     if (ops[i].op == GRPC_OP_SEND_MESSAGE) {
       grpc_byte_buffer_destroy(ops[i].data.send_message.send_message);
@@ -554,12 +564,33 @@
   RETURN_LONG(error);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 3)
+  ZEND_ARG_INFO(0, channel)
+  ZEND_ARG_INFO(0, method)
+  ZEND_ARG_INFO(0, deadline)
+  ZEND_ARG_INFO(0, host_override)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_startBatch, 0, 0, 1)
+  ZEND_ARG_INFO(0, ops)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getPeer, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_cancel, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_setCredentials, 0, 0, 1)
+  ZEND_ARG_INFO(0, credentials)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry call_methods[] = {
-  PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
-  PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Call, setCredentials, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Call, __construct, arginfo_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+  PHP_ME(Call, startBatch, arginfo_startBatch, ZEND_ACC_PUBLIC)
+  PHP_ME(Call, getPeer, arginfo_getPeer, ZEND_ACC_PUBLIC)
+  PHP_ME(Call, cancel, arginfo_cancel, ZEND_ACC_PUBLIC)
+  PHP_ME(Call, setCredentials, arginfo_setCredentials, ZEND_ACC_PUBLIC)
   PHP_FE_END
 };
 
diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c
index 043817f..625c0c6 100644
--- a/src/php/ext/grpc/call_credentials.c
+++ b/src/php/ext/grpc/call_credentials.c
@@ -212,10 +212,19 @@
   efree(state);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createComposite, 0, 0, 2)
+  ZEND_ARG_INFO(0, creds1)
+  ZEND_ARG_INFO(0, creds2)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createFromPlugin, 0, 0, 1)
+  ZEND_ARG_INFO(0, callback)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry call_credentials_methods[] = {
-  PHP_ME(CallCredentials, createComposite, NULL,
+  PHP_ME(CallCredentials, createComposite, arginfo_createComposite,
          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(CallCredentials, createFromPlugin, NULL,
+  PHP_ME(CallCredentials, createFromPlugin, arginfo_createFromPlugin,
          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
   PHP_FE_END
 };
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index 4ce4f30..c26fe4a 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -243,12 +243,37 @@
   }
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
+  ZEND_ARG_INFO(0, target)
+  ZEND_ARG_INFO(0, args)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getTarget, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getConnectivityState, 0, 0, 0)
+  ZEND_ARG_INFO(0, try_to_connect)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_watchConnectivityState, 0, 0, 2)
+  ZEND_ARG_INFO(0, last_state)
+  ZEND_ARG_INFO(0, deadline)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_close, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry channel_methods[] = {
-  PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
-  PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Channel, __construct, arginfo_construct,
+         ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+  PHP_ME(Channel, getTarget, arginfo_getTarget,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Channel, getConnectivityState, arginfo_getConnectivityState,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Channel, watchConnectivityState, arginfo_watchConnectivityState,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Channel, close, arginfo_close,
+         ZEND_ACC_PUBLIC)
   PHP_FE_END
 };
 
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index 36a8223..2160a54 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -199,16 +199,37 @@
   RETURN_NULL();
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_setDefaultRootsPem, 0, 0, 1)
+  ZEND_ARG_INFO(0, pem_roots)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createDefault, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createSsl, 0, 0, 0)
+  ZEND_ARG_INFO(0, pem_root_certs)
+  ZEND_ARG_INFO(0, pem_private_key)
+  ZEND_ARG_INFO(0, pem_cert_chain)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createComposite, 0, 0, 2)
+  ZEND_ARG_INFO(0, channel_creds)
+  ZEND_ARG_INFO(0, call_creds)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createInsecure, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry channel_credentials_methods[] = {
-  PHP_ME(ChannelCredentials, setDefaultRootsPem, NULL,
+  PHP_ME(ChannelCredentials, setDefaultRootsPem, arginfo_setDefaultRootsPem,
          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(ChannelCredentials, createDefault, NULL,
+  PHP_ME(ChannelCredentials, createDefault, arginfo_createDefault,
          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(ChannelCredentials, createSsl, NULL,
+  PHP_ME(ChannelCredentials, createSsl, arginfo_createSsl,
          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(ChannelCredentials, createComposite, NULL,
+  PHP_ME(ChannelCredentials, createComposite, arginfo_createComposite,
          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(ChannelCredentials, createInsecure, NULL,
+  PHP_ME(ChannelCredentials, createInsecure, arginfo_createInsecure,
          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
   PHP_FE_END
 };
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index 2217a4f..87780e9 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -49,6 +49,8 @@
 
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
+#include <grpc/slice.h>
+#include <grpc/support/alloc.h>
 
 #include "completion_queue.h"
 #include "server.h"
@@ -114,8 +116,6 @@
 
 /**
  * Request a call on a server. Creates a single GRPC_SERVER_RPC_NEW event.
- * @param long $tag_new The tag to associate with the new request
- * @param long $tag_cancel The tag to use if the call is cancelled
  * @return void
  */
 PHP_METHOD(Server, requestCall) {
@@ -149,8 +149,12 @@
                          1 TSRMLS_CC);
     goto cleanup;
   }
-  php_grpc_add_property_string(result, "method", details.method, true);
-  php_grpc_add_property_string(result, "host", details.host, true);
+  char *method_text = grpc_slice_to_c_string(details.method);
+  char *host_text = grpc_slice_to_c_string(details.host);
+  php_grpc_add_property_string(result, "method", method_text, true);
+  php_grpc_add_property_string(result, "host", host_text, true);
+  gpr_free(method_text);
+  gpr_free(host_text);
 #if PHP_MAJOR_VERSION < 7
   add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC));
   add_property_zval(result, "absolute_deadline",
@@ -233,12 +237,36 @@
   grpc_server_start(server->wrapped);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 0)
+  ZEND_ARG_INFO(0, args)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_requestCall, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_addHttp2Port, 0, 0, 1)
+  ZEND_ARG_INFO(0, addr)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_addSecureHttp2Port, 0, 0, 2)
+  ZEND_ARG_INFO(0, addr)
+  ZEND_ARG_INFO(0, server_creds)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_start, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry server_methods[] = {
-  PHP_ME(Server, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
-  PHP_ME(Server, requestCall, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Server, __construct, arginfo_construct,
+         ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+  PHP_ME(Server, requestCall, arginfo_requestCall,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Server, addHttp2Port, arginfo_addHttp2Port,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Server, addSecureHttp2Port, arginfo_addSecureHttp2Port,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Server, start, arginfo_start,
+         ZEND_ACC_PUBLIC)
   PHP_FE_END
 };
 
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 3e39fee..ec29dfd 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -117,8 +117,14 @@
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createSsl, 0, 0, 3)
+  ZEND_ARG_INFO(0, pem_root_certs)
+  ZEND_ARG_INFO(0, pem_private_key)
+  ZEND_ARG_INFO(0, pem_cert_chain)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry server_credentials_methods[] = {
-  PHP_ME(ServerCredentials, createSsl, NULL,
+  PHP_ME(ServerCredentials, createSsl, arginfo_createSsl,
          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
   PHP_FE_END
  };
diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c
index 7ada915..78c29e3 100644
--- a/src/php/ext/grpc/timeval.c
+++ b/src/php/ext/grpc/timeval.c
@@ -245,17 +245,65 @@
   gpr_sleep_until(this->wrapped);
 }
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1)
+  ZEND_ARG_INFO(0, microseconds)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 1)
+  ZEND_ARG_INFO(0, timeval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_compare, 0, 0, 2)
+  ZEND_ARG_INFO(0, a_timeval)
+  ZEND_ARG_INFO(0, b_timeval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_infFuture, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_infPast, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_now, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_similar, 0, 0, 3)
+  ZEND_ARG_INFO(0, a_timeval)
+  ZEND_ARG_INFO(0, b_timeval)
+  ZEND_ARG_INFO(0, threshold_timeval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sleepUntil, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_subtract, 0, 0, 1)
+  ZEND_ARG_INFO(0, timeval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zero, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry timeval_methods[] = {
-  PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
-  PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(Timeval, infFuture, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(Timeval, infPast, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-  PHP_ME(Timeval, sleepUntil, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(Timeval, __construct, arginfo_construct,
+         ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+  PHP_ME(Timeval, add, arginfo_add,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Timeval, compare, arginfo_compare,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(Timeval, infFuture, arginfo_infFuture,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(Timeval, infPast, arginfo_infPast,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(Timeval, now, arginfo_now,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(Timeval, similar, arginfo_similar,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(Timeval, sleepUntil, arginfo_sleepUntil,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Timeval, subtract, arginfo_subtract,
+         ZEND_ACC_PUBLIC)
+  PHP_ME(Timeval, zero, arginfo_zero,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
   PHP_FE_END
 };
 
diff --git a/src/php/lib/Grpc/AbstractCall.php b/src/php/lib/Grpc/AbstractCall.php
index 9f0b02b..40387ab 100644
--- a/src/php/lib/Grpc/AbstractCall.php
+++ b/src/php/lib/Grpc/AbstractCall.php
@@ -58,12 +58,11 @@
      *                              the response
      * @param array    $options     Call options (optional)
      */
-    public function __construct(
-        Channel $channel,
-        $method,
-        $deserialize,
-        array $options = []
-    ) {
+    public function __construct(Channel $channel,
+                                $method,
+                                $deserialize,
+                                array $options = [])
+    {
         if (array_key_exists('timeout', $options) &&
             is_numeric($timeout = $options['timeout'])
         ) {
@@ -127,7 +126,7 @@
      *
      * @return string The protobuf binary format
      */
-    protected function serializeMessage($data)
+    protected function _serializeMessage($data)
     {
         // Proto3 implementation
         if (method_exists($data, 'encode')) {
@@ -145,7 +144,7 @@
      *
      * @return mixed The deserialized value
      */
-    protected function deserializeResponse($value)
+    protected function _deserializeResponse($value)
     {
         if ($value === null) {
             return;
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index a9e77b9..ed504f8 100644
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -146,6 +146,14 @@
     }
 
     /**
+     * Close the communication channel associated with this stub.
+     */
+    public function close()
+    {
+        $this->channel->close();
+    }
+
+    /**
      * @param $new_state Connect state
      *
      * @return bool true if state is CHANNEL_READY
@@ -164,14 +172,6 @@
     }
 
     /**
-     * Close the communication channel associated with this stub.
-     */
-    public function close()
-    {
-        $this->channel->close();
-    }
-
-    /**
      * constructs the auth uri for the jwt.
      *
      * @param string $method The method string
@@ -235,7 +235,7 @@
      *
      * @return SimpleSurfaceActiveCall The active call object
      */
-    public function _simpleRequest($method,
+    protected function _simpleRequest($method,
                                    $argument,
                                    $deserialize,
                                    array $metadata = [],
@@ -270,7 +270,7 @@
      *
      * @return ClientStreamingSurfaceActiveCall The active call object
      */
-    public function _clientStreamRequest($method,
+    protected function _clientStreamRequest($method,
                                          $deserialize,
                                          array $metadata = [],
                                          array $options = [])
@@ -305,7 +305,7 @@
      *
      * @return ServerStreamingSurfaceActiveCall The active call object
      */
-    public function _serverStreamRequest($method,
+    protected function _serverStreamRequest($method,
                                          $argument,
                                          $deserialize,
                                          array $metadata = [],
@@ -339,7 +339,7 @@
      *
      * @return BidiStreamingSurfaceActiveCall The active call object
      */
-    public function _bidiRequest($method,
+    protected function _bidiRequest($method,
                                  $deserialize,
                                  array $metadata = [],
                                  array $options = [])
diff --git a/src/php/lib/Grpc/BidiStreamingCall.php b/src/php/lib/Grpc/BidiStreamingCall.php
index b03bbd2..7cb200d 100644
--- a/src/php/lib/Grpc/BidiStreamingCall.php
+++ b/src/php/lib/Grpc/BidiStreamingCall.php
@@ -69,7 +69,7 @@
             $this->metadata = $read_event->metadata;
         }
 
-        return $this->deserializeResponse($read_event->message);
+        return $this->_deserializeResponse($read_event->message);
     }
 
     /**
@@ -82,7 +82,7 @@
      */
     public function write($data, array $options = [])
     {
-        $message_array = ['message' => $this->serializeMessage($data)];
+        $message_array = ['message' => $this->_serializeMessage($data)];
         if (array_key_exists('flags', $options)) {
             $message_array['flags'] = $options['flags'];
         }
diff --git a/src/php/lib/Grpc/ClientStreamingCall.php b/src/php/lib/Grpc/ClientStreamingCall.php
index c542f08..6454cbc 100644
--- a/src/php/lib/Grpc/ClientStreamingCall.php
+++ b/src/php/lib/Grpc/ClientStreamingCall.php
@@ -63,7 +63,7 @@
      */
     public function write($data, array $options = [])
     {
-        $message_array = ['message' => $this->serializeMessage($data)];
+        $message_array = ['message' => $this->_serializeMessage($data)];
         if (array_key_exists('flags', $options)) {
             $message_array['flags'] = $options['flags'];
         }
@@ -90,6 +90,6 @@
         $status = $event->status;
         $this->trailing_metadata = $status->metadata;
 
-        return [$this->deserializeResponse($event->message), $status];
+        return [$this->_deserializeResponse($event->message), $status];
     }
 }
diff --git a/src/php/lib/Grpc/ServerStreamingCall.php b/src/php/lib/Grpc/ServerStreamingCall.php
index 406512b..8659f6b 100644
--- a/src/php/lib/Grpc/ServerStreamingCall.php
+++ b/src/php/lib/Grpc/ServerStreamingCall.php
@@ -51,7 +51,7 @@
      */
     public function start($data, array $metadata = [], array $options = [])
     {
-        $message_array = ['message' => $this->serializeMessage($data)];
+        $message_array = ['message' => $this->_serializeMessage($data)];
         if (array_key_exists('flags', $options)) {
             $message_array['flags'] = $options['flags'];
         }
@@ -73,7 +73,7 @@
             OP_RECV_MESSAGE => true,
         ])->message;
         while ($response !== null) {
-            yield $this->deserializeResponse($response);
+            yield $this->_deserializeResponse($response);
             $response = $this->call->startBatch([
                 OP_RECV_MESSAGE => true,
             ])->message;
diff --git a/src/php/lib/Grpc/UnaryCall.php b/src/php/lib/Grpc/UnaryCall.php
index 3c1cb15..b8b1ed6 100644
--- a/src/php/lib/Grpc/UnaryCall.php
+++ b/src/php/lib/Grpc/UnaryCall.php
@@ -51,7 +51,7 @@
      */
     public function start($data, array $metadata = [], array $options = [])
     {
-        $message_array = ['message' => $this->serializeMessage($data)];
+        $message_array = ['message' => $this->_serializeMessage($data)];
         if (isset($options['flags'])) {
             $message_array['flags'] = $options['flags'];
         }
@@ -79,6 +79,6 @@
         $status = $event->status;
         $this->trailing_metadata = $status->metadata;
 
-        return [$this->deserializeResponse($event->message), $status];
+        return [$this->_deserializeResponse($event->message), $status];
     }
 }
diff --git a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
index 8fe9bc2..c50b1c6 100644
--- a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
+++ b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
@@ -32,8 +32,11 @@
  *
  */
 require_once realpath(dirname(__FILE__).'/../../vendor/autoload.php');
-require_once dirname(__FILE__).'/math.pb.php';
-require_once dirname(__FILE__).'/math_grpc_pb.php';
+
+// The following includes are needed when using protobuf 3.1.0
+// and will suppress warnings when using protobuf 3.2.0+
+@include_once dirname(__FILE__).'/math.pb.php';
+@include_once dirname(__FILE__).'/math_grpc_pb.php';
 
 abstract class AbstractGeneratedCodeTest extends PHPUnit_Framework_TestCase
 {
@@ -70,7 +73,7 @@
     public function testClose()
     {
         self::$client->close();
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $call = self::$client->Div($div_arg);
     }
 
@@ -79,20 +82,20 @@
      */
     public function testInvalidMetadata()
     {
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $call = self::$client->Div($div_arg, [' ' => 'abc123']);
     }
 
     public function testGetCallMetadata()
     {
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $call = self::$client->Div($div_arg);
         $this->assertTrue(is_array($call->getMetadata()));
     }
 
     public function testTimeout()
     {
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $call = self::$client->Div($div_arg, [], ['timeout' => 1]);
         list($response, $status) = $call->wait();
         $this->assertSame(\Grpc\STATUS_DEADLINE_EXCEEDED, $status->code);
@@ -100,7 +103,7 @@
 
     public function testCancel()
     {
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $call = self::$client->Div($div_arg);
         $call->cancel();
         list($response, $status) = $call->wait();
@@ -109,7 +112,7 @@
 
     public function testCallCredentialsCallback()
     {
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $call = self::$client->Div($div_arg, array(), array(
             'call_credentials_callback' => function ($context) {
                 return array();
@@ -122,7 +125,7 @@
 
     public function testCallCredentialsCallback2()
     {
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $call = self::$client->Div($div_arg);
         $call_credentials = Grpc\CallCredentials::createFromPlugin(
             function ($context) {
@@ -143,7 +146,7 @@
         $invalid_client = new DummyInvalidClient('host', [
             'credentials' => Grpc\ChannelCredentials::createInsecure(),
         ]);
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $invalid_client->InvalidUnaryCall($div_arg);
     }
 
@@ -166,7 +169,7 @@
 
     public function testWriteFlags()
     {
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $div_arg->setDividend(7);
         $div_arg->setDivisor(4);
         $call = self::$client->Div($div_arg, [],
@@ -180,7 +183,7 @@
 
     public function testWriteFlagsServerStreaming()
     {
-        $fib_arg = new math\FibArgs();
+        $fib_arg = new Math\FibArgs();
         $fib_arg->setLimit(7);
         $call = self::$client->Fib($fib_arg, [],
                                    ['flags' => Grpc\WRITE_NO_COMPRESS]);
@@ -192,7 +195,7 @@
     public function testWriteFlagsClientStreaming()
     {
         $call = self::$client->Sum();
-        $num = new math\Num();
+        $num = new Math\Num();
         $num->setNum(1);
         $call->write($num, ['flags' => Grpc\WRITE_NO_COMPRESS]);
         list($response, $status) = $call->wait();
@@ -202,7 +205,7 @@
     public function testWriteFlagsBidiStreaming()
     {
         $call = self::$client->DivMany();
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $div_arg->setDividend(7);
         $div_arg->setDivisor(4);
         $call->write($div_arg, ['flags' => Grpc\WRITE_NO_COMPRESS]);
@@ -214,7 +217,7 @@
 
     public function testSimpleRequest()
     {
-        $div_arg = new math\DivArgs();
+        $div_arg = new Math\DivArgs();
         $div_arg->setDividend(7);
         $div_arg->setDivisor(4);
         $call = self::$client->Div($div_arg);
@@ -227,7 +230,7 @@
 
     public function testServerStreaming()
     {
-        $fib_arg = new math\FibArgs();
+        $fib_arg = new Math\FibArgs();
         $fib_arg->setLimit(7);
         $call = self::$client->Fib($fib_arg);
         $this->assertTrue(is_string($call->getPeer()));
@@ -246,7 +249,7 @@
         $call = self::$client->Sum();
         $this->assertTrue(is_string($call->getPeer()));
         for ($i = 0; $i < 7; ++$i) {
-            $num = new math\Num();
+            $num = new Math\Num();
             $num->setNum($i);
             $call->write($num);
         }
@@ -260,7 +263,7 @@
         $call = self::$client->DivMany();
         $this->assertTrue(is_string($call->getPeer()));
         for ($i = 0; $i < 7; ++$i) {
-            $div_arg = new math\DivArgs();
+            $div_arg = new Math\DivArgs();
             $div_arg->setDividend(2 * $i + 1);
             $div_arg->setDivisor(2);
             $call->write($div_arg);
@@ -276,7 +279,7 @@
 
 class DummyInvalidClient extends \Grpc\BaseStub
 {
-    public function InvalidUnaryCall(\math\DivArgs $argument,
+    public function InvalidUnaryCall(\Math\DivArgs $argument,
                                      $metadata = [],
                                      $options = [])
     {
diff --git a/src/php/tests/generated_code/GeneratedCodeTest.php b/src/php/tests/generated_code/GeneratedCodeTest.php
index 0cdce6c..12ba012 100755
--- a/src/php/tests/generated_code/GeneratedCodeTest.php
+++ b/src/php/tests/generated_code/GeneratedCodeTest.php
@@ -37,7 +37,7 @@
 {
     public function setUp()
     {
-        self::$client = new math\MathClient(
+        self::$client = new Math\MathClient(
             getenv('GRPC_TEST_HOST'), [
                 'credentials' => Grpc\ChannelCredentials::createInsecure(),
             ]);
diff --git a/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php b/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php
index 6b70b8a..e189948 100644
--- a/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php
+++ b/src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php
@@ -37,7 +37,7 @@
 {
     public function setUp()
     {
-        self::$client = new math\MathClient(
+        self::$client = new Math\MathClient(
         getenv('GRPC_TEST_HOST'),
         ['credentials' => Grpc\ChannelCredentials::createInsecure(),
          'update_metadata' => function ($a_hash,
diff --git a/src/php/tests/generated_code/math_client.php b/src/php/tests/generated_code/math_client.php
index 6ee92bc..9ddb1c8 100644
--- a/src/php/tests/generated_code/math_client.php
+++ b/src/php/tests/generated_code/math_client.php
@@ -32,9 +32,10 @@
  *
  */
 
-# Fix the following two lines to point to your installation
+# Fix the following line to point to your installation
+# This assumes that you are using protoc 3.2.0+ and the generated stubs
+# were being autoloaded via composer.
 include 'vendor/autoload.php';
-include 'tests/generated_code/math.php';
 
 function p($line)
 {
@@ -43,7 +44,7 @@
 
 $host = 'localhost:50051';
 p("Connecting to host: $host");
-$client = new math\MathClient($host, [
+$client = new Math\MathClient($host, [
     'credentials' => Grpc\ChannelCredentials::createInsecure(),
 ]);
 p('Client class: '.get_class($client));
@@ -52,7 +53,7 @@
 p('Running unary call test:');
 $dividend = 7;
 $divisor = 4;
-$div_arg = new math\DivArgs();
+$div_arg = new Math\DivArgs();
 $div_arg->setDividend($dividend);
 $div_arg->setDivisor($divisor);
 $call = $client->Div($div_arg);
@@ -65,7 +66,7 @@
 
 p('Running server streaming test:');
 $limit = 7;
-$fib_arg = new math\FibArgs();
+$fib_arg = new Math\FibArgs();
 $fib_arg->setLimit($limit);
 $call = $client->Fib($fib_arg);
 $result_array = iterator_to_array($call->responses());
@@ -79,7 +80,7 @@
 p('Running client streaming test:');
 $call = $client->Sum();
 for ($i = 0; $i <= $limit; ++$i) {
-    $num = new math\Num();
+    $num = new Math\Num();
     $num->setNum($i);
     $call->write($num);
 }
@@ -91,7 +92,7 @@
 p('Running bidi-streaming test:');
 $call = $client->DivMany();
 for ($i = 0; $i < 7; ++$i) {
-    $div_arg = new math\DivArgs();
+    $div_arg = new Math\DivArgs();
     $dividend = 2 * $i + 1;
     $divisor = 3;
     $div_arg->setDividend($dividend);
diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php
index 2acf561..cf93ac3 100755
--- a/src/php/tests/interop/interop_client.php
+++ b/src/php/tests/interop/interop_client.php
@@ -32,8 +32,12 @@
  *
  */
 require_once realpath(dirname(__FILE__).'/../../vendor/autoload.php');
-require 'src/proto/grpc/testing/test.pb.php';
-require 'src/proto/grpc/testing/test_grpc_pb.php';
+
+// The following includes are needed when using protobuf 3.1.0
+// and will suppress warnings when using protobuf 3.2.0+
+@include_once 'src/proto/grpc/testing/test.pb.php';
+@include_once 'src/proto/grpc/testing/test_grpc_pb.php';
+
 use Google\Auth\CredentialsLoader;
 use Google\Auth\ApplicationDefaultCredentials;
 use GuzzleHttp\ClientInterface;
@@ -70,7 +74,7 @@
 function emptyUnary($stub)
 {
     list($result, $status) =
-        $stub->EmptyCall(new grpc\testing\EmptyMessage())->wait();
+        $stub->EmptyCall(new Grpc\Testing\EmptyMessage())->wait();
     hardAssertIfStatusOk($status);
     hardAssert($result !== null, 'Call completed with a null response');
 }
@@ -98,11 +102,11 @@
     $request_len = 271828;
     $response_len = 314159;
 
-    $request = new grpc\testing\SimpleRequest();
-    $request->setResponseType(grpc\testing\PayloadType::COMPRESSABLE);
+    $request = new Grpc\Testing\SimpleRequest();
+    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
     $request->setResponseSize($response_len);
-    $payload = new grpc\testing\Payload();
-    $payload->setType(grpc\testing\PayloadType::COMPRESSABLE);
+    $payload = new Grpc\Testing\Payload();
+    $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE);
     $payload->setBody(str_repeat("\0", $request_len));
     $request->setPayload($payload);
     $request->setFillUsername($fillUsername);
@@ -117,7 +121,7 @@
     hardAssertIfStatusOk($status);
     hardAssert($result !== null, 'Call returned a null response');
     $payload = $result->getPayload();
-    hardAssert($payload->getType() === grpc\testing\PayloadType::COMPRESSABLE,
+    hardAssert($payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE,
                'Payload had the wrong type');
     hardAssert(strlen($payload->getBody()) === $response_len,
                'Payload had the wrong length');
@@ -249,8 +253,8 @@
 
     $requests = array_map(
         function ($length) {
-            $request = new grpc\testing\StreamingInputCallRequest();
-            $payload = new grpc\testing\Payload();
+            $request = new Grpc\Testing\StreamingInputCallRequest();
+            $payload = new Grpc\Testing\Payload();
             $payload->setBody(str_repeat("\0", $length));
             $request->setPayload($payload);
 
@@ -276,10 +280,10 @@
 {
     $sizes = [31415, 9, 2653, 58979];
 
-    $request = new grpc\testing\StreamingOutputCallRequest();
-    $request->setResponseType(grpc\testing\PayloadType::COMPRESSABLE);
+    $request = new Grpc\Testing\StreamingOutputCallRequest();
+    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
     foreach ($sizes as $size) {
-        $response_parameters = new grpc\testing\ResponseParameters();
+        $response_parameters = new Grpc\Testing\ResponseParameters();
         $response_parameters->setSize($size);
         $request->getResponseParameters()[] = $response_parameters;
     }
@@ -290,7 +294,7 @@
         hardAssert($i < 4, 'Too many responses');
         $payload = $value->getPayload();
         hardAssert(
-            $payload->getType() === grpc\testing\PayloadType::COMPRESSABLE,
+            $payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE,
             'Payload '.$i.' had the wrong type');
         hardAssert(strlen($payload->getBody()) === $sizes[$i],
                    'Response '.$i.' had the wrong length');
@@ -311,12 +315,12 @@
 
     $call = $stub->FullDuplexCall();
     for ($i = 0; $i < 4; ++$i) {
-        $request = new grpc\testing\StreamingOutputCallRequest();
-        $request->setResponseType(grpc\testing\PayloadType::COMPRESSABLE);
-        $response_parameters = new grpc\testing\ResponseParameters();
+        $request = new Grpc\Testing\StreamingOutputCallRequest();
+        $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
+        $response_parameters = new Grpc\Testing\ResponseParameters();
         $response_parameters->setSize($response_lengths[$i]);
         $request->getResponseParameters()[] = $response_parameters;
-        $payload = new grpc\testing\Payload();
+        $payload = new Grpc\Testing\Payload();
         $payload->setBody(str_repeat("\0", $request_lengths[$i]));
         $request->setPayload($payload);
 
@@ -326,7 +330,7 @@
         hardAssert($response !== null, 'Server returned too few responses');
         $payload = $response->getPayload();
         hardAssert(
-            $payload->getType() === grpc\testing\PayloadType::COMPRESSABLE,
+            $payload->getType() === Grpc\Testing\PayloadType::COMPRESSABLE,
             'Payload '.$i.' had the wrong type');
         hardAssert(strlen($payload->getBody()) === $response_lengths[$i],
                    'Payload '.$i.' had the wrong length');
@@ -371,12 +375,12 @@
 function cancelAfterFirstResponse($stub)
 {
     $call = $stub->FullDuplexCall();
-    $request = new grpc\testing\StreamingOutputCallRequest();
-    $request->setResponseType(grpc\testing\PayloadType::COMPRESSABLE);
-    $response_parameters = new grpc\testing\ResponseParameters();
+    $request = new Grpc\Testing\StreamingOutputCallRequest();
+    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
+    $response_parameters = new Grpc\Testing\ResponseParameters();
     $response_parameters->setSize(31415);
     $request->getResponseParameters()[] = $response_parameters;
-    $payload = new grpc\testing\Payload();
+    $payload = new Grpc\Testing\Payload();
     $payload->setBody(str_repeat("\0", 27182));
     $request->setPayload($payload);
 
@@ -391,12 +395,12 @@
 function timeoutOnSleepingServer($stub)
 {
     $call = $stub->FullDuplexCall([], ['timeout' => 1000]);
-    $request = new grpc\testing\StreamingOutputCallRequest();
-    $request->setResponseType(grpc\testing\PayloadType::COMPRESSABLE);
-    $response_parameters = new grpc\testing\ResponseParameters();
+    $request = new Grpc\Testing\StreamingOutputCallRequest();
+    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
+    $response_parameters = new Grpc\Testing\ResponseParameters();
     $response_parameters->setSize(8);
     $request->getResponseParameters()[] = $response_parameters;
-    $payload = new grpc\testing\Payload();
+    $payload = new Grpc\Testing\Payload();
     $payload->setBody(str_repeat("\0", 9));
     $request->setPayload($payload);
 
@@ -416,11 +420,11 @@
     $request_len = 271828;
     $response_len = 314159;
 
-    $request = new grpc\testing\SimpleRequest();
-    $request->setResponseType(grpc\testing\PayloadType::COMPRESSABLE);
+    $request = new Grpc\Testing\SimpleRequest();
+    $request->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
     $request->setResponseSize($response_len);
-    $payload = new grpc\testing\Payload();
-    $payload->setType(grpc\testing\PayloadType::COMPRESSABLE);
+    $payload = new Grpc\Testing\Payload();
+    $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE);
     $payload->setBody(str_repeat("\0", $request_len));
     $request->setPayload($payload);
 
@@ -449,9 +453,9 @@
 
     $streaming_call = $stub->FullDuplexCall($metadata);
 
-    $streaming_request = new grpc\testing\StreamingOutputCallRequest();
+    $streaming_request = new Grpc\Testing\StreamingOutputCallRequest();
     $streaming_request->setPayload($payload);
-    $response_parameters = new grpc\testing\ResponseParameters();
+    $response_parameters = new Grpc\Testing\ResponseParameters();
     $response_parameters->setSize($response_len);
     $streaming_request->getResponseParameters()[] = $response_parameters;
     $streaming_call->write($streaming_request);
@@ -477,11 +481,11 @@
 
 function statusCodeAndMessage($stub)
 {
-    $echo_status = new grpc\testing\EchoStatus();
+    $echo_status = new Grpc\Testing\EchoStatus();
     $echo_status->setCode(2);
     $echo_status->setMessage('test status message');
 
-    $request = new grpc\testing\SimpleRequest();
+    $request = new Grpc\Testing\SimpleRequest();
     $request->setResponseStatus($echo_status);
 
     $call = $stub->UnaryCall($request);
@@ -496,7 +500,7 @@
 
     $streaming_call = $stub->FullDuplexCall();
 
-    $streaming_request = new grpc\testing\StreamingOutputCallRequest();
+    $streaming_request = new Grpc\Testing\StreamingOutputCallRequest();
     $streaming_request->setResponseStatus($echo_status);
     $streaming_call->write($streaming_request);
     $streaming_call->writesDone();
@@ -514,7 +518,7 @@
 # NOTE: the stub input to this function is from UnimplementedService
 function unimplementedService($stub)
 {
-    $call = $stub->UnimplementedCall(new grpc\testing\EmptyMessage());
+    $call = $stub->UnimplementedCall(new Grpc\Testing\EmptyMessage());
     list($result, $status) = $call->wait();
     hardAssert($status->code === Grpc\STATUS_UNIMPLEMENTED,
                'Received unexpected status code');
@@ -523,7 +527,7 @@
 # NOTE: the stub input to this function is from TestService
 function unimplementedMethod($stub)
 {
-    $call = $stub->UnimplementedCall(new grpc\testing\EmptyMessage());
+    $call = $stub->UnimplementedCall(new Grpc\Testing\EmptyMessage());
     list($result, $status) = $call->wait();
     hardAssert($status->code === Grpc\STATUS_UNIMPLEMENTED,
                'Received unexpected status code');
@@ -614,10 +618,10 @@
     }
 
     if ($test_case === 'unimplemented_service') {
-        $stub = new grpc\testing\UnimplementedServiceClient($server_address,
+        $stub = new Grpc\Testing\UnimplementedServiceClient($server_address,
                                                             $opts);
     } else {
-        $stub = new grpc\testing\TestServiceClient($server_address, $opts);
+        $stub = new Grpc\Testing\TestServiceClient($server_address, $opts);
     }
 
     return $stub;
diff --git a/src/proto/census/trace_context.proto b/src/proto/census/trace_context.proto
index a5d5a95..fc0a54d 100644
--- a/src/proto/census/trace_context.proto
+++ b/src/proto/census/trace_context.proto
@@ -31,18 +31,14 @@
 
 package google.trace;
 
-// A TraceId uniquely represents a single Trace. It is a 128-bit nonce.
-message TraceId {
-  fixed64 hi = 1;
-  fixed64 lo = 2;
-}
-
 // Tracing information that is propagated with RPC's.
 message TraceContext {
-  // Trace identifer. Must be present.
-  TraceId trace_id = 1;
-  // ID of parent (client) span. Must be present.
-  fixed64 span_id = 2;
-  // true if this trace is sampled.
-  bool is_sampled = 3;
+  // A TraceId uniquely represents a single Trace. It is a 128-bit nonce.
+  // The 128-bit ID is split into 2 64-bit chunks. (REQUIRED)
+  fixed64 trace_id_hi = 1;
+  fixed64 trace_id_lo = 2;
+  // ID of parent (client) span. (REQUIRED)
+  fixed64 span_id = 3;
+  // Span option flags. First bit is true if this trace is sampled. (OPTIONAL)
+  fixed32 span_options = 4;
 }
diff --git a/src/proto/grpc/health/v1/health.options b/src/proto/grpc/health/v1/health.options
new file mode 100644
index 0000000..240b498
--- /dev/null
+++ b/src/proto/grpc/health/v1/health.options
@@ -0,0 +1 @@
+grpc.health.v1.HealthCheckRequest.service max_size:200
diff --git a/src/proto/grpc/reflection/v1alpha/BUILD b/src/proto/grpc/reflection/v1alpha/BUILD
new file mode 100644
index 0000000..92dd3d7
--- /dev/null
+++ b/src/proto/grpc/reflection/v1alpha/BUILD
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+package(default_visibility = ["//visibility:public"])
+
+load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
+
+grpc_proto_library(
+    name = "reflection_proto",
+    srcs = ["reflection.proto"],
+)
diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD
index 2837408..23a16a7 100644
--- a/src/proto/grpc/testing/BUILD
+++ b/src/proto/grpc/testing/BUILD
@@ -42,11 +42,13 @@
     name = "control_proto",
     srcs = ["control.proto"],
     deps = ["payloads_proto", "stats_proto"],
+    has_services = False,
 )
 
 grpc_proto_library(
     name = "echo_messages_proto",
     srcs = ["echo_messages.proto"],
+    has_services = False,
 )
 
 grpc_proto_library(
@@ -58,11 +60,13 @@
 grpc_proto_library(
     name = "empty_proto",
     srcs = ["empty.proto"],
+    has_services = False,
 )
 
 grpc_proto_library(
     name = "messages_proto",
     srcs = ["messages.proto"],
+    has_services = False,
 )
 
 grpc_proto_library(
@@ -73,6 +77,7 @@
 grpc_proto_library(
     name = "payloads_proto",
     srcs = ["payloads.proto"],
+    has_services = False,
 )
 
 grpc_proto_library(
@@ -84,6 +89,7 @@
 grpc_proto_library(
     name = "stats_proto",
     srcs = ["stats.proto"],
+    has_services = False,
 )
 
 grpc_proto_library(
diff --git a/src/proto/grpc/testing/control.proto b/src/proto/grpc/testing/control.proto
index 529313c..8f0d25c 100644
--- a/src/proto/grpc/testing/control.proto
+++ b/src/proto/grpc/testing/control.proto
@@ -139,7 +139,10 @@
   int32 async_server_threads = 7;
   // Specify the number of cores to limit server to, if desired
   int32 core_limit = 8;
-  // payload config, used in generic server
+  // payload config, used in generic server.
+  // Note this must NOT be used in proto (non-generic) servers. For proto servers,
+  // 'response sizes' must be configured from the 'response_size' field of the
+  // 'SimpleRequest' objects in RPC requests.
   PayloadConfig payload_config = 9;
 
   // Specify the cores we should run the server on, if desired
diff --git a/src/proto/grpc/testing/echo_messages.proto b/src/proto/grpc/testing/echo_messages.proto
index b405acf..efb6f4d 100644
--- a/src/proto/grpc/testing/echo_messages.proto
+++ b/src/proto/grpc/testing/echo_messages.proto
@@ -50,6 +50,7 @@
   bool skip_cancelled_check = 9;
   string expected_transport_security_type = 10;
   DebugInfo debug_info = 11;
+  bool server_die = 12; // Server should not see a request with this set.
 }
 
 message EchoRequest {
diff --git a/src/python/grpcio/grpc/_auth.py b/src/python/grpcio/grpc/_auth.py
index e8a90cf..21131f8 100644
--- a/src/python/grpcio/grpc/_auth.py
+++ b/src/python/grpcio/grpc/_auth.py
@@ -48,11 +48,8 @@
 
         # Hack to determine if these are JWT creds and we need to pass
         # additional_claims when getting a token
-        if 'additional_claims' in inspect.getargspec(
-                credentials.get_access_token).args:
-            self._is_jwt = True
-        else:
-            self._is_jwt = False
+        self._is_jwt = 'additional_claims' in inspect.getargspec(
+            credentials.get_access_token).args
 
     def __call__(self, context, callback):
         # MetadataPlugins cannot block (see grpc.beta.interfaces.py)
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index a1ac806..af86f5e 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -43,7 +43,6 @@
 
 _EMPTY_FLAGS = 0
 _INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
-_EMPTY_METADATA = cygrpc.Metadata(())
 
 _UNARY_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata,
                             cygrpc.OperationType.send_message,
@@ -138,8 +137,8 @@
         state.code = code
         state.details = details
         if state.initial_metadata is None:
-            state.initial_metadata = _EMPTY_METADATA
-        state.trailing_metadata = _EMPTY_METADATA
+            state.initial_metadata = _common.EMPTY_METADATA
+        state.trailing_metadata = _common.EMPTY_METADATA
 
 
 def _handle_event(event, state, response_deserializer):
@@ -435,7 +434,7 @@
     deadline, deadline_timespec = _deadline(timeout)
     serialized_request = _common.serialize(request, request_serializer)
     if serialized_request is None:
-        state = _RPCState((), _EMPTY_METADATA, _EMPTY_METADATA,
+        state = _RPCState((), _common.EMPTY_METADATA, _common.EMPTY_METADATA,
                           grpc.StatusCode.INTERNAL,
                           'Exception serializing request!')
         rendezvous = _Rendezvous(state, None, None, deadline)
@@ -444,10 +443,10 @@
         return deadline, deadline_timespec, serialized_request, None
 
 
-def _end_unary_response_blocking(state, with_call, deadline):
+def _end_unary_response_blocking(state, call, with_call, deadline):
     if state.code is grpc.StatusCode.OK:
         if with_call:
-            rendezvous = _Rendezvous(state, None, None, deadline)
+            rendezvous = _Rendezvous(state, call, None, deadline)
             return state.response, rendezvous
         else:
             return state.response
@@ -499,17 +498,17 @@
             _check_call_error(call_error, metadata)
             _handle_event(completion_queue.poll(), state,
                           self._response_deserializer)
-            return state, deadline
+            return state, call, deadline
 
     def __call__(self, request, timeout=None, metadata=None, credentials=None):
-        state, deadline, = self._blocking(request, timeout, metadata,
-                                          credentials)
-        return _end_unary_response_blocking(state, False, deadline)
+        state, call, deadline = self._blocking(request, timeout, metadata,
+                                               credentials)
+        return _end_unary_response_blocking(state, call, False, deadline)
 
     def with_call(self, request, timeout=None, metadata=None, credentials=None):
-        state, deadline, = self._blocking(request, timeout, metadata,
-                                          credentials)
-        return _end_unary_response_blocking(state, True, deadline)
+        state, call, deadline = self._blocking(request, timeout, metadata,
+                                               credentials)
+        return _end_unary_response_blocking(state, call, True, deadline)
 
     def future(self, request, timeout=None, metadata=None, credentials=None):
         state, operations, deadline, deadline_timespec, rendezvous = self._prepare(
@@ -619,25 +618,25 @@
                 state.condition.notify_all()
                 if not state.due:
                     break
-        return state, deadline
+        return state, call, deadline
 
     def __call__(self,
                  request_iterator,
                  timeout=None,
                  metadata=None,
                  credentials=None):
-        state, deadline, = self._blocking(request_iterator, timeout, metadata,
-                                          credentials)
-        return _end_unary_response_blocking(state, False, deadline)
+        state, call, deadline = self._blocking(request_iterator, timeout,
+                                               metadata, credentials)
+        return _end_unary_response_blocking(state, call, False, deadline)
 
     def with_call(self,
                   request_iterator,
                   timeout=None,
                   metadata=None,
                   credentials=None):
-        state, deadline, = self._blocking(request_iterator, timeout, metadata,
-                                          credentials)
-        return _end_unary_response_blocking(state, True, deadline)
+        state, call, deadline = self._blocking(request_iterator, timeout,
+                                               metadata, credentials)
+        return _end_unary_response_blocking(state, call, True, deadline)
 
     def future(self,
                request_iterator,
diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py
index a5f1f38..6879e17 100644
--- a/src/python/grpcio/grpc/_common.py
+++ b/src/python/grpcio/grpc/_common.py
@@ -37,7 +37,7 @@
 import grpc
 from grpc._cython import cygrpc
 
-_EMPTY_METADATA = cygrpc.Metadata(())
+EMPTY_METADATA = cygrpc.Metadata(())
 
 CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = {
     cygrpc.ConnectivityState.idle:
@@ -92,7 +92,7 @@
         try:
             return b.decode('utf8')
         except UnicodeDecodeError:
-            logging.exception('Invalid encoding on {}'.format(b))
+            logging.exception('Invalid encoding on %s', b)
             return b.decode('latin1')
 
 
@@ -107,7 +107,7 @@
 
 
 def cygrpc_metadata(application_metadata):
-    return _EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
+    return EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
         cygrpc.Metadatum(encode(key), encode(value))
         for key, value in application_metadata)
 
@@ -148,36 +148,23 @@
 class CleanupThread(threading.Thread):
     """A threading.Thread subclass supporting custom behavior on join().
 
-  On Python Interpreter exit, Python will attempt to join outstanding threads
-  prior to garbage collection.  We may need to do additional cleanup, and
-  we accomplish this by overriding the join() method.
-  """
+    On Python Interpreter exit, Python will attempt to join outstanding threads
+    prior to garbage collection.  We may need to do additional cleanup, and
+    we accomplish this by overriding the join() method.
+    """
 
-    def __init__(self,
-                 behavior,
-                 group=None,
-                 target=None,
-                 name=None,
-                 args=(),
-                 kwargs={}):
+    def __init__(self, behavior, *args, **kwargs):
         """Constructor.
 
-    Args:
-      behavior (function): Function called on join() with a single
-          argument, timeout, indicating the maximum duration of
-          `behavior`, or None indicating `behavior` has no deadline.
-          `behavior` must be idempotent.
-      group (None): should be None.  Reseved for future extensions
-          when ThreadGroup is implemented.
-      target (function): The function to invoke when this thread is
-          run.  Defaults to None.
-      name (str): The name of this thread.  Defaults to None.
-        args (tuple[object]): A tuple of arguments to pass to `target`.
-      kwargs (dict[str,object]): A dictionary of keyword arguments to
-           pass to `target`.
-    """
-        super(CleanupThread, self).__init__(
-            group=group, target=target, name=name, args=args, kwargs=kwargs)
+        Args:
+            behavior (function): Function called on join() with a single
+                argument, timeout, indicating the maximum duration of
+                `behavior`, or None indicating `behavior` has no deadline.
+                `behavior` must be idempotent.
+            args: Positional arguments passed to threading.Thread constructor.
+            kwargs: Keyword arguments passed to threading.Thread constructor.
+        """
+        super(CleanupThread, self).__init__(*args, **kwargs)
         self._behavior = behavior
 
     def join(self, timeout=None):
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index 73d1ff7..246e839 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -60,20 +60,25 @@
                   method, host, Timespec deadline not None):
     if queue.is_shutting_down:
       raise ValueError("queue must not be shutting down or shutdown")
-    cdef char *method_c_string = method
-    cdef char *host_c_string = NULL
+    cdef grpc_slice method_slice = _slice_from_bytes(method)
+    cdef grpc_slice host_slice
+    cdef grpc_slice *host_slice_ptr = NULL
     if host is not None:
-      host_c_string = host
+      host_slice = _slice_from_bytes(host)
+      host_slice_ptr = &host_slice
     cdef Call operation_call = Call()
-    operation_call.references = [self, method, host, queue]
+    operation_call.references = [self, queue]
     cdef grpc_call *parent_call = NULL
     if parent is not None:
       parent_call = parent.c_call
     with nogil:
       operation_call.c_call = grpc_channel_create_call(
           self.c_channel, parent_call, flags,
-          queue.c_completion_queue, method_c_string, host_c_string,
+          queue.c_completion_queue, method_slice, host_slice_ptr,
           deadline.c_time, NULL)
+      grpc_slice_unref(method_slice)
+      if host_slice_ptr:
+        grpc_slice_unref(host_slice)
     return operation_call
 
   def check_connectivity_state(self, bint try_to_connect):
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index a258ba4..d8df6c2 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -51,6 +51,7 @@
     cdef CallDetails request_call_details = None
     cdef Metadata request_metadata = None
     cdef Operations batch_operations = None
+    cdef Operation batch_operation = None
     if event.type == GRPC_QUEUE_TIMEOUT:
       return Event(
           event.type, False, None, None, None, None, False, None)
@@ -69,8 +70,15 @@
         user_tag = tag.user_tag
         operation_call = tag.operation_call
         request_call_details = tag.request_call_details
-        request_metadata = tag.request_metadata
+        if tag.request_metadata is not None:
+          request_metadata = tag.request_metadata
+          request_metadata._claim_slice_ownership()
         batch_operations = tag.batch_operations
+        if tag.batch_operations is not None:
+          for op in batch_operations.operations:
+            batch_operation = <Operation>op
+            if batch_operation._received_metadata is not None:
+              batch_operation._received_metadata._claim_slice_ownership()
         if tag.is_new_request:
           # Stuff in the tag not explicitly handled by us needs to live through
           # the life of the call
@@ -91,7 +99,7 @@
       c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
       if deadline is not None:
         c_deadline = deadline.c_time
-      
+
       while True:
         c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment)
         if gpr_time_cmp(c_timeout, c_deadline) > 0:
@@ -100,7 +108,7 @@
           self.c_completion_queue, c_timeout, NULL)
         if event.type != GRPC_QUEUE_TIMEOUT or gpr_time_cmp(c_timeout, c_deadline) == 0:
           break;
-        
+
         # Handle any signals
         with gil:
           cpython.PyErr_CheckSignals()
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index 348d42c..bbd7242 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -51,6 +51,13 @@
     pass
 
 
+cdef extern from "grpc/impl/codegen/exec_ctx_fwd.h":
+
+  struct grpc_exec_ctx:
+    # We don't care about the internals
+    pass
+
+
 cdef extern from "grpc/grpc.h":
 
   ctypedef struct grpc_slice:
@@ -60,6 +67,7 @@
 
   grpc_slice grpc_slice_ref(grpc_slice s) nogil
   void grpc_slice_unref(grpc_slice s) nogil
+  grpc_slice grpc_empty_slice() nogil
   grpc_slice grpc_slice_new(void *p, size_t len, void (*destroy)(void *)) nogil
   grpc_slice grpc_slice_new_with_len(
       void *p, size_t len, void (*destroy)(void *, size_t)) nogil
@@ -175,7 +183,7 @@
 
   ctypedef struct grpc_arg_pointer_vtable:
     void *(*copy)(void *)
-    void (*destroy)(void *)
+    void (*destroy)(grpc_exec_ctx *, void *)
     int (*cmp)(void *, void *)
 
   ctypedef struct grpc_arg_value_pointer:
@@ -217,9 +225,8 @@
     GRPC_CHANNEL_SHUTDOWN
 
   ctypedef struct grpc_metadata:
-    const char *key
-    const char *value
-    size_t value_length
+    grpc_slice key
+    grpc_slice value
     # ignore the 'internal_data.obfuscated' fields.
 
   ctypedef enum grpc_completion_type:
@@ -241,10 +248,8 @@
   void grpc_metadata_array_destroy(grpc_metadata_array *array) nogil
 
   ctypedef struct grpc_call_details:
-    char *method
-    size_t method_capacity
-    char *host
-    size_t host_capacity
+    grpc_slice method
+    grpc_slice host
     gpr_timespec deadline
 
   void grpc_call_details_init(grpc_call_details *details) nogil
@@ -268,13 +273,12 @@
     size_t trailing_metadata_count
     grpc_metadata *trailing_metadata
     grpc_status_code status
-    const char *status_details
+    grpc_slice *status_details
 
   ctypedef struct grpc_op_data_recv_status_on_client:
     grpc_metadata_array *trailing_metadata
     grpc_status_code *status
-    char **status_details
-    size_t *status_details_capacity
+    grpc_slice *status_details
 
   ctypedef struct grpc_op_data_recv_close_on_server:
     int *cancelled
@@ -330,9 +334,9 @@
                                              const grpc_channel_args *args,
                                              void *reserved) nogil
   grpc_call *grpc_channel_create_call(
-      grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
-      grpc_completion_queue *completion_queue, const char *method,
-      const char *host, gpr_timespec deadline, void *reserved) nogil
+    grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
+    grpc_completion_queue *completion_queue, grpc_slice method,
+    const grpc_slice *host, gpr_timespec deadline, void *reserved) nogil
   grpc_connectivity_state grpc_channel_check_connectivity_state(
       grpc_channel *channel, int try_to_connect) nogil
   void grpc_channel_watch_connectivity_state(
@@ -482,8 +486,7 @@
     grpc_compression_algorithm default_compression_algorithm
 
   int grpc_compression_algorithm_parse(
-      const char *name, size_t name_length,
-      grpc_compression_algorithm *algorithm) nogil
+      grpc_slice value, grpc_compression_algorithm *algorithm) nogil
   int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
                                       char **name) nogil
   grpc_compression_algorithm grpc_compression_algorithm_for_level(
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
index 00ec91b..c4a1711 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
@@ -28,6 +28,11 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
+cdef bytes _slice_bytes(grpc_slice slice)
+cdef grpc_slice _copy_slice(grpc_slice slice) nogil
+cdef grpc_slice _slice_from_bytes(bytes value) nogil
+
+
 cdef class Timespec:
 
   cdef gpr_timespec c_time
@@ -97,13 +102,13 @@
 cdef class Metadatum:
 
   cdef grpc_metadata c_metadata
-  cdef object _key, _value
+  cdef void _copy_metadatum(self, grpc_metadata *destination) nogil
 
 
 cdef class Metadata:
 
   cdef grpc_metadata_array c_metadata_array
-  cdef object metadata
+  cdef void _claim_slice_ownership(self)
 
 
 cdef class Operation:
@@ -112,8 +117,7 @@
   cdef ByteBuffer _received_message
   cdef Metadata _received_metadata
   cdef grpc_status_code _received_status_code
-  cdef char *_received_status_details
-  cdef size_t _received_status_details_capacity
+  cdef grpc_slice _status_details
   cdef int _received_cancelled
   cdef readonly bint is_valid
   cdef object references
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
index 0738512..c3d158d 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
@@ -29,6 +29,26 @@
 
 from libc.stdint cimport intptr_t
 
+
+cdef bytes _slice_bytes(grpc_slice slice):
+  cdef void *start = grpc_slice_start_ptr(slice)
+  cdef size_t length = grpc_slice_length(slice)
+  return (<const char *>start)[:length]
+
+cdef grpc_slice _copy_slice(grpc_slice slice) nogil:
+  cdef void *start = grpc_slice_start_ptr(slice)
+  cdef size_t length = grpc_slice_length(slice)
+  return grpc_slice_from_copied_buffer(<const char *>start, length)
+
+cdef grpc_slice _slice_from_bytes(bytes value) nogil:
+  cdef const char *value_ptr
+  cdef size_t length
+  with gil:
+    value_ptr = <const char *>value
+    length = len(value)
+  return grpc_slice_from_copied_buffer(value_ptr, length)
+
+
 class ConnectivityState:
   idle = GRPC_CHANNEL_IDLE
   connecting = GRPC_CHANNEL_CONNECTING
@@ -208,17 +228,11 @@
 
   @property
   def method(self):
-    if self.c_details.method != NULL:
-      return <bytes>self.c_details.method
-    else:
-      return None
+    return _slice_bytes(self.c_details.method)
 
   @property
   def host(self):
-    if self.c_details.host != NULL:
-      return <bytes>self.c_details.host
-    else:
-      return None
+    return _slice_bytes(self.c_details.host)
 
   @property
   def deadline(self):
@@ -329,7 +343,7 @@
   return ptr
 
 
-cdef void destroy_ptr(void* ptr):
+cdef void destroy_ptr(grpc_exec_ctx* ctx, void* ptr):
   pass
 
 
@@ -402,19 +416,20 @@
 cdef class Metadatum:
 
   def __cinit__(self, bytes key, bytes value):
-    self._key = key
-    self._value = value
-    self.c_metadata.key = self._key
-    self.c_metadata.value = self._value
-    self.c_metadata.value_length = len(self._value)
+    self.c_metadata.key = _slice_from_bytes(key)
+    self.c_metadata.value = _slice_from_bytes(value)
+
+  cdef void _copy_metadatum(self, grpc_metadata *destination) nogil:
+    destination[0].key = _copy_slice(self.c_metadata.key)
+    destination[0].value = _copy_slice(self.c_metadata.value)
 
   @property
   def key(self):
-    return <bytes>self.c_metadata.key
+    return _slice_bytes(self.c_metadata.key)
 
   @property
   def value(self):
-    return <bytes>self.c_metadata.value[:self.c_metadata.value_length]
+    return _slice_bytes(self.c_metadata.value)
 
   def __len__(self):
     return 2
@@ -430,6 +445,9 @@
   def __iter__(self):
     return iter((self.key, self.value))
 
+  def __dealloc__(self):
+    grpc_slice_unref(self.c_metadata.key)
+    grpc_slice_unref(self.c_metadata.value)
 
 cdef class _MetadataIterator:
 
@@ -454,51 +472,65 @@
 
 cdef class Metadata:
 
-  def __cinit__(self, metadata):
-    grpc_init()
-    self.metadata = list(metadata)
+  def __cinit__(self, metadata_iterable):
+    with nogil:
+      grpc_init()
+      grpc_metadata_array_init(&self.c_metadata_array)
+    metadata = list(metadata_iterable)
     for metadatum in metadata:
       if not isinstance(metadatum, Metadatum):
         raise TypeError("expected list of Metadatum")
-    with nogil:
-      grpc_metadata_array_init(&self.c_metadata_array)
-    self.c_metadata_array.count = len(self.metadata)
-    self.c_metadata_array.capacity = len(self.metadata)
+    self.c_metadata_array.count = len(metadata)
+    self.c_metadata_array.capacity = len(metadata)
     with nogil:
       self.c_metadata_array.metadata = <grpc_metadata *>gpr_malloc(
           self.c_metadata_array.count*sizeof(grpc_metadata)
       )
     for i in range(self.c_metadata_array.count):
-      self.c_metadata_array.metadata[i] = (
-          (<Metadatum>self.metadata[i]).c_metadata)
+      (<Metadatum>metadata[i])._copy_metadatum(&self.c_metadata_array.metadata[i])
 
   def __dealloc__(self):
-    # this frees the allocated memory for the grpc_metadata_array (although
-    # it'd be nice if that were documented somewhere...)
-    # TODO(atash): document this in the C core
-    grpc_metadata_array_destroy(&self.c_metadata_array)
-    grpc_shutdown()
+    with nogil:
+      # this frees the allocated memory for the grpc_metadata_array (although
+      # it'd be nice if that were documented somewhere...)
+      # TODO(atash): document this in the C core
+      grpc_metadata_array_destroy(&self.c_metadata_array)
+      grpc_shutdown()
 
   def __len__(self):
     return self.c_metadata_array.count
 
   def __getitem__(self, size_t i):
-    return Metadatum(
-        key=<bytes>self.c_metadata_array.metadata[i].key,
-        value=<bytes>self.c_metadata_array.metadata[i].value[
-            :self.c_metadata_array.metadata[i].value_length])
+    if i >= self.c_metadata_array.count:
+      raise IndexError
+    key = _slice_bytes(self.c_metadata_array.metadata[i].key)
+    value = _slice_bytes(self.c_metadata_array.metadata[i].value)
+    return Metadatum(key=key, value=value)
 
   def __iter__(self):
     return _MetadataIterator(self)
 
+  cdef void _claim_slice_ownership(self):
+    cdef grpc_metadata_array new_c_metadata_array
+    grpc_metadata_array_init(&new_c_metadata_array)
+    new_c_metadata_array.metadata = <grpc_metadata *>gpr_malloc(
+        self.c_metadata_array.count*sizeof(grpc_metadata))
+    new_c_metadata_array.count = self.c_metadata_array.count
+    for i in range(self.c_metadata_array.count):
+      new_c_metadata_array.metadata[i].key = _copy_slice(
+          self.c_metadata_array.metadata[i].key)
+      new_c_metadata_array.metadata[i].value = _copy_slice(
+          self.c_metadata_array.metadata[i].value)
+    grpc_metadata_array_destroy(&self.c_metadata_array)
+    self.c_metadata_array = new_c_metadata_array
+
 
 cdef class Operation:
 
   def __cinit__(self):
     grpc_init()
     self.references = []
-    self._received_status_details = NULL
-    self._received_status_details_capacity = 0
+    self._status_details = grpc_empty_slice()
     self.is_valid = False
 
   @property
@@ -555,19 +587,13 @@
   def received_status_details(self):
     if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT:
       raise TypeError("self must be an operation receiving status details")
-    if self._received_status_details:
-      return self._received_status_details
-    else:
-      return None
+    return _slice_bytes(self._status_details)
 
   @property
   def received_status_details_or_none(self):
     if self.c_op.type != GRPC_OP_RECV_STATUS_ON_CLIENT:
       return None
-    if self._received_status_details:
-      return self._received_status_details
-    else:
-      return None
+    return _slice_bytes(self._status_details)
 
   @property
   def received_cancelled(self):
@@ -583,11 +609,7 @@
     return False if self._received_cancelled == 0 else True
 
   def __dealloc__(self):
-    # We *almost* don't need to do anything; most of the objects are handled by
-    # Python. The remaining one(s) are primitive fields filled in by GRPC core.
-    # This means that we need to clean up after receive_status_on_client.
-    if self.c_op.type == GRPC_OP_RECV_STATUS_ON_CLIENT:
-      gpr_free(self._received_status_details)
+    grpc_slice_unref(self._status_details)
     grpc_shutdown()
 
 def operation_send_initial_metadata(Metadata metadata, int flags):
@@ -628,9 +650,10 @@
   op.c_op.data.send_status_from_server.trailing_metadata = (
       metadata.c_metadata_array.metadata)
   op.c_op.data.send_status_from_server.status = code
-  op.c_op.data.send_status_from_server.status_details = details
+  grpc_slice_unref(op._status_details)
+  op._status_details = _slice_from_bytes(details)
+  op.c_op.data.send_status_from_server.status_details = &op._status_details
   op.references.append(metadata)
-  op.references.append(details)
   op.is_valid = True
   return op
 
@@ -667,9 +690,7 @@
   op.c_op.data.receive_status_on_client.status = (
       &op._received_status_code)
   op.c_op.data.receive_status_on_client.status_details = (
-      &op._received_status_details)
-  op.c_op.data.receive_status_on_client.status_details_capacity = (
-      &op._received_status_details_capacity)
+      &op._status_details)
   op.is_valid = True
   return op
 
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index 549c6cc..b8e7ea1 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -57,7 +57,6 @@
 _CANCELLED = 'cancelled'
 
 _EMPTY_FLAGS = 0
-_EMPTY_METADATA = cygrpc.Metadata(())
 
 _UNEXPECTED_EXIT_SERVER_GRACE = 1.0
 
@@ -143,7 +142,7 @@
         effective_details = details if state.details is None else state.details
         if state.initial_metadata_allowed:
             operations = (cygrpc.operation_send_initial_metadata(
-                _EMPTY_METADATA, _EMPTY_FLAGS),
+                _common.EMPTY_METADATA, _EMPTY_FLAGS),
                           cygrpc.operation_send_status_from_server(
                               _common.cygrpc_metadata(state.trailing_metadata),
                               effective_code, effective_details, _EMPTY_FLAGS),)
@@ -416,7 +415,7 @@
         else:
             if state.initial_metadata_allowed:
                 operations = (cygrpc.operation_send_initial_metadata(
-                    _EMPTY_METADATA, _EMPTY_FLAGS),
+                    _common.EMPTY_METADATA, _EMPTY_FLAGS),
                               cygrpc.operation_send_message(serialized_response,
                                                             _EMPTY_FLAGS),)
                 state.initial_metadata_allowed = False
@@ -446,8 +445,8 @@
             ]
             if state.initial_metadata_allowed:
                 operations.append(
-                    cygrpc.operation_send_initial_metadata(_EMPTY_METADATA,
-                                                           _EMPTY_FLAGS))
+                    cygrpc.operation_send_initial_metadata(
+                        _common.EMPTY_METADATA, _EMPTY_FLAGS))
             if serialized_response is not None:
                 operations.append(
                     cygrpc.operation_send_message(serialized_response,
@@ -549,12 +548,12 @@
 
 
 def _handle_unrecognized_method(rpc_event):
-    operations = (
-        cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS),
-        cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
-        cygrpc.operation_send_status_from_server(
-            _EMPTY_METADATA, cygrpc.StatusCode.unimplemented,
-            b'Method not found!', _EMPTY_FLAGS),)
+    operations = (cygrpc.operation_send_initial_metadata(_common.EMPTY_METADATA,
+                                                         _EMPTY_FLAGS),
+                  cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
+                  cygrpc.operation_send_status_from_server(
+                      _common.EMPTY_METADATA, cygrpc.StatusCode.unimplemented,
+                      b'Method not found!', _EMPTY_FLAGS),)
     rpc_state = _RPCState()
     rpc_event.operation_call.start_server_batch(
         operations, lambda ignored_event: (rpc_state, (),))
@@ -587,6 +586,8 @@
 
 
 def _handle_call(rpc_event, generic_handlers, thread_pool):
+    if not rpc_event.success:
+        return None
     if rpc_event.request_call_details.method is not None:
         method_handler = _find_method_handler(rpc_event, generic_handlers)
         if method_handler is None:
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index ba64174..a9f20e6 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -159,6 +159,8 @@
   'src/core/lib/slice/percent_encoding.c',
   'src/core/lib/slice/slice.c',
   'src/core/lib/slice/slice_buffer.c',
+  'src/core/lib/slice/slice_hash_table.c',
+  'src/core/lib/slice/slice_intern.c',
   'src/core/lib/slice/slice_string_helpers.c',
   'src/core/lib/surface/alarm.c',
   'src/core/lib/surface/api_trace.c',
@@ -178,14 +180,16 @@
   'src/core/lib/surface/server.c',
   'src/core/lib/surface/validate_metadata.c',
   'src/core/lib/surface/version.c',
+  'src/core/lib/transport/bdp_estimator.c',
   'src/core/lib/transport/byte_stream.c',
   'src/core/lib/transport/connectivity_state.c',
-  'src/core/lib/transport/mdstr_hash_table.c',
+  'src/core/lib/transport/error_utils.c',
   'src/core/lib/transport/metadata.c',
   'src/core/lib/transport/metadata_batch.c',
   'src/core/lib/transport/pid_controller.c',
   'src/core/lib/transport/service_config.c',
   'src/core/lib/transport/static_metadata.c',
+  'src/core/lib/transport/status_conversion.c',
   'src/core/lib/transport/timeout_encoding.c',
   'src/core/lib/transport/transport.c',
   'src/core/lib/transport/transport_op_string.c',
@@ -206,7 +210,6 @@
   'src/core/ext/transport/chttp2/transport/huffsyms.c',
   'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
   'src/core/ext/transport/chttp2/transport/parsing.c',
-  'src/core/ext/transport/chttp2/transport/status_conversion.c',
   'src/core/ext/transport/chttp2/transport/stream_lists.c',
   'src/core/ext/transport/chttp2/transport/stream_map.c',
   'src/core/ext/transport/chttp2/transport/varint.c',
@@ -228,6 +231,7 @@
   'src/core/lib/security/credentials/plugin/plugin_credentials.c',
   'src/core/lib/security/credentials/ssl/ssl_credentials.c',
   'src/core/lib/security/transport/client_auth_filter.c',
+  'src/core/lib/security/transport/lb_targets_info.c',
   'src/core/lib/security/transport/secure_endpoint.c',
   'src/core/lib/security/transport/security_connector.c',
   'src/core/lib/security/transport/security_handshaker.c',
@@ -248,11 +252,14 @@
   'src/core/ext/client_channel/connector.c',
   'src/core/ext/client_channel/default_initial_connect_string.c',
   'src/core/ext/client_channel/http_connect_handshaker.c',
+  'src/core/ext/client_channel/http_proxy.c',
   'src/core/ext/client_channel/initial_connect_string.c',
   'src/core/ext/client_channel/lb_policy.c',
   'src/core/ext/client_channel/lb_policy_factory.c',
   'src/core/ext/client_channel/lb_policy_registry.c',
   'src/core/ext/client_channel/parse_address.c',
+  'src/core/ext/client_channel/proxy_mapper.c',
+  'src/core/ext/client_channel/proxy_mapper_registry.c',
   'src/core/ext/client_channel/resolver.c',
   'src/core/ext/client_channel/resolver_factory.c',
   'src/core/ext/client_channel/resolver_registry.c',
@@ -265,6 +272,7 @@
   'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
   'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
   'src/core/ext/lb_policy/grpclb/grpclb.c',
+  'src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c',
   'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
   'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
   'third_party/nanopb/pb_common.c',
diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py
index 7e57e07..c197e92 100644
--- a/src/python/grpcio/grpc_version.py
+++ b/src/python/grpcio/grpc_version.py
@@ -29,4 +29,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
 
-VERSION='1.1.2'
+VERSION='1.2.0.dev0'
diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py
index 5d63397..c1807e9 100644
--- a/src/python/grpcio_health_checking/grpc_version.py
+++ b/src/python/grpcio_health_checking/grpc_version.py
@@ -29,4 +29,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
 
-VERSION='1.1.2'
+VERSION='1.2.0.dev0'
diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py
index 495f354..3778dcd 100644
--- a/src/python/grpcio_reflection/grpc_version.py
+++ b/src/python/grpcio_reflection/grpc_version.py
@@ -29,4 +29,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
 
-VERSION='1.1.2'
+VERSION='1.2.0.dev0'
diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py
index af0ffe3..40f9b83 100644
--- a/src/python/grpcio_tests/commands.py
+++ b/src/python/grpcio_tests/commands.py
@@ -28,7 +28,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 """Provides distutils command classes for the gRPC Python setup process."""
 
-import distutils
+from distutils import errors as _errors
 import glob
 import os
 import os.path
@@ -186,7 +186,7 @@
 
     def finalize_options(self):
         if self.client and self.server:
-            raise DistutilsOptionError(
+            raise _errors.DistutilsOptionError(
                 'you may only specify one of client or server')
 
     def run(self):
diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py
index b441b10..33824b6 100644
--- a/src/python/grpcio_tests/grpc_version.py
+++ b/src/python/grpcio_tests/grpc_version.py
@@ -29,4 +29,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
 
-VERSION='1.1.2'
+VERSION='1.2.0.dev0'
diff --git a/src/python/grpcio_tests/tests/interop/client.py b/src/python/grpcio_tests/tests/interop/client.py
index 833818e..97f6843 100644
--- a/src/python/grpcio_tests/tests/interop/client.py
+++ b/src/python/grpcio_tests/tests/interop/client.py
@@ -45,7 +45,7 @@
         '--server_host',
         help='the host to which to connect',
         type=str,
-        default="127.0.0.1")
+        default="localhost")
     parser.add_argument(
         '--server_port', help='the port to which to connect', type=int)
     parser.add_argument(
diff --git a/src/ruby/ext/grpc/rb_byte_buffer.c b/src/ruby/ext/grpc/rb_byte_buffer.c
index 47fd6d9..65fa2f2 100644
--- a/src/ruby/ext/grpc/rb_byte_buffer.c
+++ b/src/ruby/ext/grpc/rb_byte_buffer.c
@@ -68,3 +68,10 @@
   grpc_byte_buffer_reader_destroy(&reader);
   return rb_string;
 }
+
+VALUE grpc_rb_slice_to_ruby_string(grpc_slice slice) {
+  if (GRPC_SLICE_START_PTR(slice) == NULL) {
+    rb_raise(rb_eRuntimeError, "attempt to convert uninitialized grpc_slice to ruby string");
+  }
+  return rb_str_new((char*)GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice));
+}
diff --git a/src/ruby/ext/grpc/rb_byte_buffer.h b/src/ruby/ext/grpc/rb_byte_buffer.h
index c7ddd76..fac68fe 100644
--- a/src/ruby/ext/grpc/rb_byte_buffer.h
+++ b/src/ruby/ext/grpc/rb_byte_buffer.h
@@ -44,4 +44,7 @@
 /* Converts a grpc_byte_buffer to a ruby string */
 VALUE grpc_rb_byte_buffer_to_s(grpc_byte_buffer *buffer);
 
+/* Converts a grpc_slice to a ruby string */
+VALUE grpc_rb_slice_to_ruby_string(grpc_slice slice);
+
 #endif /* GRPC_RB_BYTE_BUFFER_H_ */
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index fbc68c4..82d340b 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -121,8 +121,8 @@
   size_t i, datasize = sizeof(grpc_metadata_array);
   for (i = 0; i < ary->count; ++i) {
     const grpc_metadata *const md = &ary->metadata[i];
-    datasize += strlen(md->key);
-    datasize += md->value_length;
+    datasize += GRPC_SLICE_LENGTH(md->key);
+    datasize += GRPC_SLICE_LENGTH(md->value);
   }
   datasize += ary->capacity * sizeof(grpc_metadata);
   return datasize;
@@ -386,23 +386,23 @@
   grpc_metadata_array *md_ary = NULL;
   long array_length;
   long i;
-  char *key_str;
-  size_t key_len;
-  char *value_str;
-  size_t value_len;
+  grpc_slice key_slice;
+  grpc_slice value_slice;
+  char* tmp_str;
 
   if (TYPE(key) == T_SYMBOL) {
-    key_str = (char *)rb_id2name(SYM2ID(key));
-    key_len = strlen(key_str);
-  } else { /* StringValueCStr does all other type exclusions for us */
-    key_str = StringValueCStr(key);
-    key_len = RSTRING_LEN(key);
+    key_slice = grpc_slice_from_static_string(rb_id2name(SYM2ID(key)));
+  } else if (TYPE(key) == T_STRING) {
+    key_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(key), RSTRING_LEN(key));
+  } else {
+    rb_raise(rb_eTypeError, "grpc_rb_md_ary_fill_hash_cb: bad type for key parameter");
   }
 
-  if (!grpc_header_key_is_legal(key_str, key_len)) {
+  if (!grpc_header_key_is_legal(key_slice)) {
+    tmp_str = grpc_slice_to_c_string(key_slice);
     rb_raise(rb_eArgError,
              "'%s' is an invalid header key, must match [a-z0-9-_.]+",
-             key_str);
+             tmp_str);
     return ST_STOP;
   }
 
@@ -414,33 +414,31 @@
     array_length = RARRAY_LEN(val);
     /* If the value is an array, add capacity for each value in the array */
     for (i = 0; i < array_length; i++) {
-      value_str = RSTRING_PTR(rb_ary_entry(val, i));
-      value_len = RSTRING_LEN(rb_ary_entry(val, i));
-      if (!grpc_is_binary_header(key_str, key_len) &&
-          !grpc_header_nonbin_value_is_legal(value_str, value_len)) {
+      value_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(rb_ary_entry(val, i)), RSTRING_LEN(rb_ary_entry(val, i)));
+      if (!grpc_is_binary_header(key_slice) &&
+          !grpc_header_nonbin_value_is_legal(value_slice)) {
         // The value has invalid characters
+        tmp_str = grpc_slice_to_c_string(value_slice);
         rb_raise(rb_eArgError,
-                 "Header value '%s' has invalid characters", value_str);
+                 "Header value '%s' has invalid characters", tmp_str);
         return ST_STOP;
       }
-      md_ary->metadata[md_ary->count].key = key_str;
-      md_ary->metadata[md_ary->count].value = value_str;
-      md_ary->metadata[md_ary->count].value_length = value_len;
+      md_ary->metadata[md_ary->count].key = key_slice;
+      md_ary->metadata[md_ary->count].value = value_slice;
       md_ary->count += 1;
     }
   } else if (TYPE(val) == T_STRING) {
-    value_str = RSTRING_PTR(val);
-    value_len = RSTRING_LEN(val);
-    if (!grpc_is_binary_header(key_str, key_len) &&
-        !grpc_header_nonbin_value_is_legal(value_str, value_len)) {
+    value_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(val), RSTRING_LEN(val));
+    if (!grpc_is_binary_header(key_slice) &&
+        !grpc_header_nonbin_value_is_legal(value_slice)) {
       // The value has invalid characters
+      tmp_str = grpc_slice_to_c_string(value_slice);
       rb_raise(rb_eArgError,
-               "Header value '%s' has invalid characters", value_str);
+               "Header value '%s' has invalid characters", tmp_str);
       return ST_STOP;
     }
-    md_ary->metadata[md_ary->count].key = key_str;
-    md_ary->metadata[md_ary->count].value = value_str;
-    md_ary->metadata[md_ary->count].value_length = value_len;
+    md_ary->metadata[md_ary->count].key = key_slice;
+    md_ary->metadata[md_ary->count].value = value_slice;
     md_ary->count += 1;
   } else {
     rb_raise(rb_eArgError,
@@ -506,22 +504,19 @@
   size_t i;
 
   for (i = 0; i < md_ary->count; i++) {
-    key = rb_str_new2(md_ary->metadata[i].key);
+    key = grpc_rb_slice_to_ruby_string(md_ary->metadata[i].key);
     value = rb_hash_aref(result, key);
     if (value == Qnil) {
-      value = rb_str_new(md_ary->metadata[i].value,
-                         md_ary->metadata[i].value_length);
+      value = grpc_rb_slice_to_ruby_string(md_ary->metadata[i].value);
       rb_hash_aset(result, key, value);
     } else if (TYPE(value) == T_ARRAY) {
       /* Add the string to the returned array */
-      rb_ary_push(value, rb_str_new(md_ary->metadata[i].value,
-                                    md_ary->metadata[i].value_length));
+      rb_ary_push(value, grpc_rb_slice_to_ruby_string(md_ary->metadata[i].value));
     } else {
       /* Add the current value with this key and the new one to an array */
       new_ary = rb_ary_new();
       rb_ary_push(new_ary, value);
-      rb_ary_push(new_ary, rb_str_new(md_ary->metadata[i].value,
-                                      md_ary->metadata[i].value_length));
+      rb_ary_push(new_ary, grpc_rb_slice_to_ruby_string(md_ary->metadata[i].value));
       rb_hash_aset(result, key, new_ary);
     }
   }
@@ -563,6 +558,7 @@
 */
 static void grpc_rb_op_update_status_from_server(grpc_op *op,
                                                  grpc_metadata_array *md_ary,
+                                                 grpc_slice *send_status_details,
                                                  VALUE status) {
   VALUE code = rb_struct_aref(status, sym_code);
   VALUE details = rb_struct_aref(status, sym_details);
@@ -579,8 +575,11 @@
              rb_obj_classname(code));
     return;
   }
+
+  *send_status_details = grpc_slice_from_copied_buffer(RSTRING_PTR(details), RSTRING_LEN(details));
+
   op->data.send_status_from_server.status = NUM2INT(code);
-  op->data.send_status_from_server.status_details = StringValueCStr(details);
+  op->data.send_status_from_server.status_details = send_status_details;
   grpc_rb_md_ary_convert(metadata_hash, md_ary);
   op->data.send_status_from_server.trailing_metadata_count = md_ary->count;
   op->data.send_status_from_server.trailing_metadata = md_ary->metadata;
@@ -603,9 +602,9 @@
   grpc_metadata_array recv_trailing_metadata;
   int recv_cancelled;
   grpc_status_code recv_status;
-  char *recv_status_details;
-  size_t recv_status_details_capacity;
+  grpc_slice recv_status_details;
   unsigned write_flag;
+  grpc_slice send_status_details;
 } run_batch_stack;
 
 /* grpc_run_batch_stack_init ensures the run_batch_stack is properly
@@ -631,8 +630,12 @@
   grpc_metadata_array_destroy(&st->recv_metadata);
   grpc_metadata_array_destroy(&st->recv_trailing_metadata);
 
-  if (st->recv_status_details != NULL) {
-    gpr_free(st->recv_status_details);
+  if (GRPC_SLICE_START_PTR(st->send_status_details) != NULL) {
+    grpc_slice_unref(st->send_status_details);
+  }
+
+  if (GRPC_SLICE_START_PTR(st->recv_status_details) != NULL) {
+    grpc_slice_unref(st->recv_status_details);
   }
 
   if (st->recv_message != NULL) {
@@ -684,7 +687,7 @@
         /* N.B. later there is no need to explicitly delete the metadata keys
          * and values, they are references to data in ruby objects. */
         grpc_rb_op_update_status_from_server(
-            &st->ops[st->op_num], &st->send_trailing_metadata, this_value);
+            &st->ops[st->op_num], &st->send_trailing_metadata, &st->send_status_details, this_value);
         break;
       case GRPC_OP_RECV_INITIAL_METADATA:
         st->ops[st->op_num].data.recv_initial_metadata.recv_initial_metadata =
@@ -700,8 +703,6 @@
             &st->recv_status;
         st->ops[st->op_num].data.recv_status_on_client.status_details =
             &st->recv_status_details;
-        st->ops[st->op_num].data.recv_status_on_client.status_details_capacity =
-            &st->recv_status_details_capacity;
         break;
       case GRPC_OP_RECV_CLOSE_ON_SERVER:
         st->ops[st->op_num].data.recv_close_on_server.cancelled =
@@ -749,9 +750,9 @@
         rb_struct_aset(
             result, sym_status,
             rb_struct_new(grpc_rb_sStatus, UINT2NUM(st->recv_status),
-                          (st->recv_status_details == NULL
+                          (GRPC_SLICE_START_PTR(st->recv_status_details) == NULL
                                ? Qnil
-                               : rb_str_new2(st->recv_status_details)),
+                               : grpc_rb_slice_to_ruby_string(st->recv_status_details)),
                           grpc_rb_md_ary_to_h(&st->recv_trailing_metadata),
                           NULL));
         break;
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 3b2b88e..84e43d3 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -35,6 +35,7 @@
 
 #include "rb_grpc_imports.generated.h"
 #include "rb_channel.h"
+#include "rb_byte_buffer.h"
 
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
@@ -252,10 +253,14 @@
   grpc_channel *ch = NULL;
   grpc_completion_queue *cq = NULL;
   int flags = GRPC_PROPAGATE_DEFAULTS;
-  char *method_chars = StringValueCStr(method);
-  char *host_chars = NULL;
+  grpc_slice method_slice;
+  grpc_slice host_slice;
+  grpc_slice *host_slice_ptr = NULL;
+  char* tmp_str = NULL;
+
   if (host != Qnil) {
-    host_chars = StringValueCStr(host);
+    host_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(host), RSTRING_LEN(host));
+    host_slice_ptr = &host_slice;
   }
   if (mask != Qnil) {
     flags = NUM2UINT(mask);
@@ -272,15 +277,25 @@
     return Qnil;
   }
 
-  call = grpc_channel_create_call(ch, parent_call, flags, cq, method_chars,
-                                  host_chars, grpc_rb_time_timeval(
+  method_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(method), RSTRING_LEN(method));
+
+  call = grpc_channel_create_call(ch, parent_call, flags, cq, method_slice,
+                                  host_slice_ptr, grpc_rb_time_timeval(
                                       deadline,
                                       /* absolute time */ 0), NULL);
+
   if (call == NULL) {
+    tmp_str = grpc_slice_to_c_string(method_slice);
     rb_raise(rb_eRuntimeError, "cannot create call with method %s",
-             method_chars);
+             tmp_str);
     return Qnil;
   }
+
+  grpc_slice_unref(method_slice);
+  if (host_slice_ptr != NULL) {
+    grpc_slice_unref(host_slice);
+  }
+
   res = grpc_rb_wrap_call(call, cq);
 
   /* Make this channel an instance attribute of the call so that it is not GCed
diff --git a/src/ruby/ext/grpc/rb_compression_options.c b/src/ruby/ext/grpc/rb_compression_options.c
index 6200dba..6b2467e 100644
--- a/src/ruby/ext/grpc/rb_compression_options.c
+++ b/src/ruby/ext/grpc/rb_compression_options.c
@@ -34,6 +34,7 @@
 #include <ruby/ruby.h>
 
 #include "rb_compression_options.h"
+#include "rb_byte_buffer.h"
 #include "rb_grpc_imports.generated.h"
 
 #include <grpc/compression.h>
@@ -168,9 +169,9 @@
  * Raises an error if the name of the algorithm passed in is invalid. */
 void grpc_rb_compression_options_algorithm_name_to_value_internal(
     grpc_compression_algorithm *algorithm_value, VALUE algorithm_name) {
-  char *name_str = NULL;
-  long name_len = 0;
+  grpc_slice name_slice;
   VALUE algorithm_name_as_string = Qnil;
+  char *tmp_str = NULL;
 
   Check_Type(algorithm_name, T_SYMBOL);
 
@@ -178,16 +179,18 @@
    * correct C string out of it. */
   algorithm_name_as_string = rb_funcall(algorithm_name, rb_intern("to_s"), 0);
 
-  name_str = RSTRING_PTR(algorithm_name_as_string);
-  name_len = RSTRING_LEN(algorithm_name_as_string);
+  name_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(algorithm_name_as_string), RSTRING_LEN(algorithm_name_as_string));
 
   /* Raise an error if the name isn't recognized as a compression algorithm by
    * the algorithm parse function
    * in GRPC core. */
-  if (!grpc_compression_algorithm_parse(name_str, name_len, algorithm_value)) {
+  if(!grpc_compression_algorithm_parse(name_slice, algorithm_value)) {
+    tmp_str = grpc_slice_to_c_string(name_slice);
     rb_raise(rb_eNameError, "Invalid compression algorithm name: %s",
-             StringValueCStr(algorithm_name_as_string));
+             tmp_str);
   }
+
+  grpc_slice_unref(name_slice);
 }
 
 /* Indicates whether a given algorithm is enabled on this instance, given the
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 6c36df9..52465a4 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -107,6 +107,7 @@
 grpc_channel_create_registered_call_type grpc_channel_create_registered_call_import;
 grpc_call_start_batch_type grpc_call_start_batch_import;
 grpc_call_get_peer_type grpc_call_get_peer_import;
+grpc_call_set_load_reporting_cost_context_type grpc_call_set_load_reporting_cost_context_import;
 grpc_census_call_set_context_type grpc_census_call_set_context_import;
 grpc_census_call_get_context_type grpc_census_call_get_context_import;
 grpc_channel_get_target_type grpc_channel_get_target_import;
@@ -179,17 +180,30 @@
 grpc_slice_new_with_user_data_type grpc_slice_new_with_user_data_import;
 grpc_slice_new_with_len_type grpc_slice_new_with_len_import;
 grpc_slice_malloc_type grpc_slice_malloc_import;
+grpc_slice_intern_type grpc_slice_intern_import;
 grpc_slice_from_copied_string_type grpc_slice_from_copied_string_import;
 grpc_slice_from_copied_buffer_type grpc_slice_from_copied_buffer_import;
 grpc_slice_from_static_string_type grpc_slice_from_static_string_import;
+grpc_slice_from_static_buffer_type grpc_slice_from_static_buffer_import;
 grpc_slice_sub_type grpc_slice_sub_import;
 grpc_slice_sub_no_ref_type grpc_slice_sub_no_ref_import;
 grpc_slice_split_tail_type grpc_slice_split_tail_import;
 grpc_slice_split_head_type grpc_slice_split_head_import;
-gpr_empty_slice_type gpr_empty_slice_import;
+grpc_empty_slice_type grpc_empty_slice_import;
+grpc_slice_default_hash_impl_type grpc_slice_default_hash_impl_import;
+grpc_slice_default_eq_impl_type grpc_slice_default_eq_impl_import;
+grpc_slice_eq_type grpc_slice_eq_import;
 grpc_slice_cmp_type grpc_slice_cmp_import;
 grpc_slice_str_cmp_type grpc_slice_str_cmp_import;
+grpc_slice_buf_cmp_type grpc_slice_buf_cmp_import;
+grpc_slice_buf_start_eq_type grpc_slice_buf_start_eq_import;
+grpc_slice_rchr_type grpc_slice_rchr_import;
+grpc_slice_chr_type grpc_slice_chr_import;
+grpc_slice_slice_type grpc_slice_slice_import;
+grpc_slice_hash_type grpc_slice_hash_import;
 grpc_slice_is_equivalent_type grpc_slice_is_equivalent_import;
+grpc_slice_dup_type grpc_slice_dup_import;
+grpc_slice_to_c_string_type grpc_slice_to_c_string_import;
 grpc_slice_buffer_init_type grpc_slice_buffer_init_import;
 grpc_slice_buffer_destroy_type grpc_slice_buffer_destroy_import;
 grpc_slice_buffer_add_type grpc_slice_buffer_add_import;
@@ -202,8 +216,11 @@
 grpc_slice_buffer_move_into_type grpc_slice_buffer_move_into_import;
 grpc_slice_buffer_trim_end_type grpc_slice_buffer_trim_end_import;
 grpc_slice_buffer_move_first_type grpc_slice_buffer_move_first_import;
+grpc_slice_buffer_move_first_into_buffer_type grpc_slice_buffer_move_first_into_buffer_import;
 grpc_slice_buffer_take_first_type grpc_slice_buffer_take_first_import;
+grpc_slice_buffer_undo_take_first_type grpc_slice_buffer_undo_take_first_import;
 gpr_malloc_type gpr_malloc_import;
+gpr_zalloc_type gpr_zalloc_import;
 gpr_free_type gpr_free_import;
 gpr_realloc_type gpr_realloc_import;
 gpr_malloc_aligned_type gpr_malloc_aligned_import;
@@ -383,6 +400,7 @@
   grpc_channel_create_registered_call_import = (grpc_channel_create_registered_call_type) GetProcAddress(library, "grpc_channel_create_registered_call");
   grpc_call_start_batch_import = (grpc_call_start_batch_type) GetProcAddress(library, "grpc_call_start_batch");
   grpc_call_get_peer_import = (grpc_call_get_peer_type) GetProcAddress(library, "grpc_call_get_peer");
+  grpc_call_set_load_reporting_cost_context_import = (grpc_call_set_load_reporting_cost_context_type) GetProcAddress(library, "grpc_call_set_load_reporting_cost_context");
   grpc_census_call_set_context_import = (grpc_census_call_set_context_type) GetProcAddress(library, "grpc_census_call_set_context");
   grpc_census_call_get_context_import = (grpc_census_call_get_context_type) GetProcAddress(library, "grpc_census_call_get_context");
   grpc_channel_get_target_import = (grpc_channel_get_target_type) GetProcAddress(library, "grpc_channel_get_target");
@@ -455,17 +473,30 @@
   grpc_slice_new_with_user_data_import = (grpc_slice_new_with_user_data_type) GetProcAddress(library, "grpc_slice_new_with_user_data");
   grpc_slice_new_with_len_import = (grpc_slice_new_with_len_type) GetProcAddress(library, "grpc_slice_new_with_len");
   grpc_slice_malloc_import = (grpc_slice_malloc_type) GetProcAddress(library, "grpc_slice_malloc");
+  grpc_slice_intern_import = (grpc_slice_intern_type) GetProcAddress(library, "grpc_slice_intern");
   grpc_slice_from_copied_string_import = (grpc_slice_from_copied_string_type) GetProcAddress(library, "grpc_slice_from_copied_string");
   grpc_slice_from_copied_buffer_import = (grpc_slice_from_copied_buffer_type) GetProcAddress(library, "grpc_slice_from_copied_buffer");
   grpc_slice_from_static_string_import = (grpc_slice_from_static_string_type) GetProcAddress(library, "grpc_slice_from_static_string");
+  grpc_slice_from_static_buffer_import = (grpc_slice_from_static_buffer_type) GetProcAddress(library, "grpc_slice_from_static_buffer");
   grpc_slice_sub_import = (grpc_slice_sub_type) GetProcAddress(library, "grpc_slice_sub");
   grpc_slice_sub_no_ref_import = (grpc_slice_sub_no_ref_type) GetProcAddress(library, "grpc_slice_sub_no_ref");
   grpc_slice_split_tail_import = (grpc_slice_split_tail_type) GetProcAddress(library, "grpc_slice_split_tail");
   grpc_slice_split_head_import = (grpc_slice_split_head_type) GetProcAddress(library, "grpc_slice_split_head");
-  gpr_empty_slice_import = (gpr_empty_slice_type) GetProcAddress(library, "gpr_empty_slice");
+  grpc_empty_slice_import = (grpc_empty_slice_type) GetProcAddress(library, "grpc_empty_slice");
+  grpc_slice_default_hash_impl_import = (grpc_slice_default_hash_impl_type) GetProcAddress(library, "grpc_slice_default_hash_impl");
+  grpc_slice_default_eq_impl_import = (grpc_slice_default_eq_impl_type) GetProcAddress(library, "grpc_slice_default_eq_impl");
+  grpc_slice_eq_import = (grpc_slice_eq_type) GetProcAddress(library, "grpc_slice_eq");
   grpc_slice_cmp_import = (grpc_slice_cmp_type) GetProcAddress(library, "grpc_slice_cmp");
   grpc_slice_str_cmp_import = (grpc_slice_str_cmp_type) GetProcAddress(library, "grpc_slice_str_cmp");
+  grpc_slice_buf_cmp_import = (grpc_slice_buf_cmp_type) GetProcAddress(library, "grpc_slice_buf_cmp");
+  grpc_slice_buf_start_eq_import = (grpc_slice_buf_start_eq_type) GetProcAddress(library, "grpc_slice_buf_start_eq");
+  grpc_slice_rchr_import = (grpc_slice_rchr_type) GetProcAddress(library, "grpc_slice_rchr");
+  grpc_slice_chr_import = (grpc_slice_chr_type) GetProcAddress(library, "grpc_slice_chr");
+  grpc_slice_slice_import = (grpc_slice_slice_type) GetProcAddress(library, "grpc_slice_slice");
+  grpc_slice_hash_import = (grpc_slice_hash_type) GetProcAddress(library, "grpc_slice_hash");
   grpc_slice_is_equivalent_import = (grpc_slice_is_equivalent_type) GetProcAddress(library, "grpc_slice_is_equivalent");
+  grpc_slice_dup_import = (grpc_slice_dup_type) GetProcAddress(library, "grpc_slice_dup");
+  grpc_slice_to_c_string_import = (grpc_slice_to_c_string_type) GetProcAddress(library, "grpc_slice_to_c_string");
   grpc_slice_buffer_init_import = (grpc_slice_buffer_init_type) GetProcAddress(library, "grpc_slice_buffer_init");
   grpc_slice_buffer_destroy_import = (grpc_slice_buffer_destroy_type) GetProcAddress(library, "grpc_slice_buffer_destroy");
   grpc_slice_buffer_add_import = (grpc_slice_buffer_add_type) GetProcAddress(library, "grpc_slice_buffer_add");
@@ -478,8 +509,11 @@
   grpc_slice_buffer_move_into_import = (grpc_slice_buffer_move_into_type) GetProcAddress(library, "grpc_slice_buffer_move_into");
   grpc_slice_buffer_trim_end_import = (grpc_slice_buffer_trim_end_type) GetProcAddress(library, "grpc_slice_buffer_trim_end");
   grpc_slice_buffer_move_first_import = (grpc_slice_buffer_move_first_type) GetProcAddress(library, "grpc_slice_buffer_move_first");
+  grpc_slice_buffer_move_first_into_buffer_import = (grpc_slice_buffer_move_first_into_buffer_type) GetProcAddress(library, "grpc_slice_buffer_move_first_into_buffer");
   grpc_slice_buffer_take_first_import = (grpc_slice_buffer_take_first_type) GetProcAddress(library, "grpc_slice_buffer_take_first");
+  grpc_slice_buffer_undo_take_first_import = (grpc_slice_buffer_undo_take_first_type) GetProcAddress(library, "grpc_slice_buffer_undo_take_first");
   gpr_malloc_import = (gpr_malloc_type) GetProcAddress(library, "gpr_malloc");
+  gpr_zalloc_import = (gpr_zalloc_type) GetProcAddress(library, "gpr_zalloc");
   gpr_free_import = (gpr_free_type) GetProcAddress(library, "gpr_free");
   gpr_realloc_import = (gpr_realloc_type) GetProcAddress(library, "gpr_realloc");
   gpr_malloc_aligned_import = (gpr_malloc_aligned_type) GetProcAddress(library, "gpr_malloc_aligned");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 5745686..b16e673 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -176,7 +176,7 @@
 typedef void(*census_record_values_type)(census_context *context, census_value *values, size_t nvalues);
 extern census_record_values_type census_record_values_import;
 #define census_record_values census_record_values_import
-typedef int(*grpc_compression_algorithm_parse_type)(const char *name, size_t name_length, grpc_compression_algorithm *algorithm);
+typedef int(*grpc_compression_algorithm_parse_type)(grpc_slice value, grpc_compression_algorithm *algorithm);
 extern grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import;
 #define grpc_compression_algorithm_parse grpc_compression_algorithm_parse_import
 typedef int(*grpc_compression_algorithm_name_type)(grpc_compression_algorithm algorithm, char **name);
@@ -254,7 +254,7 @@
 typedef void(*grpc_channel_watch_connectivity_state_type)(grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag);
 extern grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import;
 #define grpc_channel_watch_connectivity_state grpc_channel_watch_connectivity_state_import
-typedef grpc_call *(*grpc_channel_create_call_type)(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, const char *method, const char *host, gpr_timespec deadline, void *reserved);
+typedef grpc_call *(*grpc_channel_create_call_type)(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *completion_queue, grpc_slice method, const grpc_slice *host, gpr_timespec deadline, void *reserved);
 extern grpc_channel_create_call_type grpc_channel_create_call_import;
 #define grpc_channel_create_call grpc_channel_create_call_import
 typedef void(*grpc_channel_ping_type)(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved);
@@ -272,6 +272,9 @@
 typedef char *(*grpc_call_get_peer_type)(grpc_call *call);
 extern grpc_call_get_peer_type grpc_call_get_peer_import;
 #define grpc_call_get_peer grpc_call_get_peer_import
+typedef void(*grpc_call_set_load_reporting_cost_context_type)(grpc_call *call, struct grpc_load_reporting_cost_context *context);
+extern grpc_call_set_load_reporting_cost_context_type grpc_call_set_load_reporting_cost_context_import;
+#define grpc_call_set_load_reporting_cost_context grpc_call_set_load_reporting_cost_context_import
 typedef void(*grpc_census_call_set_context_type)(grpc_call *call, struct census_context *context);
 extern grpc_census_call_set_context_type grpc_census_call_set_context_import;
 #define grpc_census_call_set_context grpc_census_call_set_context_import
@@ -338,13 +341,13 @@
 typedef int(*grpc_tracer_set_enabled_type)(const char *name, int enabled);
 extern grpc_tracer_set_enabled_type grpc_tracer_set_enabled_import;
 #define grpc_tracer_set_enabled grpc_tracer_set_enabled_import
-typedef int(*grpc_header_key_is_legal_type)(const char *key, size_t length);
+typedef int(*grpc_header_key_is_legal_type)(grpc_slice slice);
 extern grpc_header_key_is_legal_type grpc_header_key_is_legal_import;
 #define grpc_header_key_is_legal grpc_header_key_is_legal_import
-typedef int(*grpc_header_nonbin_value_is_legal_type)(const char *value, size_t length);
+typedef int(*grpc_header_nonbin_value_is_legal_type)(grpc_slice slice);
 extern grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import;
 #define grpc_header_nonbin_value_is_legal grpc_header_nonbin_value_is_legal_import
-typedef int(*grpc_is_binary_header_type)(const char *key, size_t length);
+typedef int(*grpc_is_binary_header_type)(grpc_slice slice);
 extern grpc_is_binary_header_type grpc_is_binary_header_import;
 #define grpc_is_binary_header grpc_is_binary_header_import
 typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error);
@@ -488,6 +491,9 @@
 typedef grpc_slice(*grpc_slice_malloc_type)(size_t length);
 extern grpc_slice_malloc_type grpc_slice_malloc_import;
 #define grpc_slice_malloc grpc_slice_malloc_import
+typedef grpc_slice(*grpc_slice_intern_type)(grpc_slice slice);
+extern grpc_slice_intern_type grpc_slice_intern_import;
+#define grpc_slice_intern grpc_slice_intern_import
 typedef grpc_slice(*grpc_slice_from_copied_string_type)(const char *source);
 extern grpc_slice_from_copied_string_type grpc_slice_from_copied_string_import;
 #define grpc_slice_from_copied_string grpc_slice_from_copied_string_import
@@ -497,6 +503,9 @@
 typedef grpc_slice(*grpc_slice_from_static_string_type)(const char *source);
 extern grpc_slice_from_static_string_type grpc_slice_from_static_string_import;
 #define grpc_slice_from_static_string grpc_slice_from_static_string_import
+typedef grpc_slice(*grpc_slice_from_static_buffer_type)(const void *source, size_t len);
+extern grpc_slice_from_static_buffer_type grpc_slice_from_static_buffer_import;
+#define grpc_slice_from_static_buffer grpc_slice_from_static_buffer_import
 typedef grpc_slice(*grpc_slice_sub_type)(grpc_slice s, size_t begin, size_t end);
 extern grpc_slice_sub_type grpc_slice_sub_import;
 #define grpc_slice_sub grpc_slice_sub_import
@@ -509,18 +518,51 @@
 typedef grpc_slice(*grpc_slice_split_head_type)(grpc_slice *s, size_t split);
 extern grpc_slice_split_head_type grpc_slice_split_head_import;
 #define grpc_slice_split_head grpc_slice_split_head_import
-typedef grpc_slice(*gpr_empty_slice_type)(void);
-extern gpr_empty_slice_type gpr_empty_slice_import;
-#define gpr_empty_slice gpr_empty_slice_import
+typedef grpc_slice(*grpc_empty_slice_type)(void);
+extern grpc_empty_slice_type grpc_empty_slice_import;
+#define grpc_empty_slice grpc_empty_slice_import
+typedef uint32_t(*grpc_slice_default_hash_impl_type)(grpc_slice s);
+extern grpc_slice_default_hash_impl_type grpc_slice_default_hash_impl_import;
+#define grpc_slice_default_hash_impl grpc_slice_default_hash_impl_import
+typedef int(*grpc_slice_default_eq_impl_type)(grpc_slice a, grpc_slice b);
+extern grpc_slice_default_eq_impl_type grpc_slice_default_eq_impl_import;
+#define grpc_slice_default_eq_impl grpc_slice_default_eq_impl_import
+typedef int(*grpc_slice_eq_type)(grpc_slice a, grpc_slice b);
+extern grpc_slice_eq_type grpc_slice_eq_import;
+#define grpc_slice_eq grpc_slice_eq_import
 typedef int(*grpc_slice_cmp_type)(grpc_slice a, grpc_slice b);
 extern grpc_slice_cmp_type grpc_slice_cmp_import;
 #define grpc_slice_cmp grpc_slice_cmp_import
 typedef int(*grpc_slice_str_cmp_type)(grpc_slice a, const char *b);
 extern grpc_slice_str_cmp_type grpc_slice_str_cmp_import;
 #define grpc_slice_str_cmp grpc_slice_str_cmp_import
+typedef int(*grpc_slice_buf_cmp_type)(grpc_slice a, const void *b, size_t blen);
+extern grpc_slice_buf_cmp_type grpc_slice_buf_cmp_import;
+#define grpc_slice_buf_cmp grpc_slice_buf_cmp_import
+typedef int(*grpc_slice_buf_start_eq_type)(grpc_slice a, const void *b, size_t blen);
+extern grpc_slice_buf_start_eq_type grpc_slice_buf_start_eq_import;
+#define grpc_slice_buf_start_eq grpc_slice_buf_start_eq_import
+typedef int(*grpc_slice_rchr_type)(grpc_slice s, char c);
+extern grpc_slice_rchr_type grpc_slice_rchr_import;
+#define grpc_slice_rchr grpc_slice_rchr_import
+typedef int(*grpc_slice_chr_type)(grpc_slice s, char c);
+extern grpc_slice_chr_type grpc_slice_chr_import;
+#define grpc_slice_chr grpc_slice_chr_import
+typedef int(*grpc_slice_slice_type)(grpc_slice haystack, grpc_slice needle);
+extern grpc_slice_slice_type grpc_slice_slice_import;
+#define grpc_slice_slice grpc_slice_slice_import
+typedef uint32_t(*grpc_slice_hash_type)(grpc_slice s);
+extern grpc_slice_hash_type grpc_slice_hash_import;
+#define grpc_slice_hash grpc_slice_hash_import
 typedef int(*grpc_slice_is_equivalent_type)(grpc_slice a, grpc_slice b);
 extern grpc_slice_is_equivalent_type grpc_slice_is_equivalent_import;
 #define grpc_slice_is_equivalent grpc_slice_is_equivalent_import
+typedef grpc_slice(*grpc_slice_dup_type)(grpc_slice a);
+extern grpc_slice_dup_type grpc_slice_dup_import;
+#define grpc_slice_dup grpc_slice_dup_import
+typedef char *(*grpc_slice_to_c_string_type)(grpc_slice s);
+extern grpc_slice_to_c_string_type grpc_slice_to_c_string_import;
+#define grpc_slice_to_c_string grpc_slice_to_c_string_import
 typedef void(*grpc_slice_buffer_init_type)(grpc_slice_buffer *sb);
 extern grpc_slice_buffer_init_type grpc_slice_buffer_init_import;
 #define grpc_slice_buffer_init grpc_slice_buffer_init_import
@@ -557,12 +599,21 @@
 typedef void(*grpc_slice_buffer_move_first_type)(grpc_slice_buffer *src, size_t n, grpc_slice_buffer *dst);
 extern grpc_slice_buffer_move_first_type grpc_slice_buffer_move_first_import;
 #define grpc_slice_buffer_move_first grpc_slice_buffer_move_first_import
+typedef void(*grpc_slice_buffer_move_first_into_buffer_type)(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *src, size_t n, void *dst);
+extern grpc_slice_buffer_move_first_into_buffer_type grpc_slice_buffer_move_first_into_buffer_import;
+#define grpc_slice_buffer_move_first_into_buffer grpc_slice_buffer_move_first_into_buffer_import
 typedef grpc_slice(*grpc_slice_buffer_take_first_type)(grpc_slice_buffer *src);
 extern grpc_slice_buffer_take_first_type grpc_slice_buffer_take_first_import;
 #define grpc_slice_buffer_take_first grpc_slice_buffer_take_first_import
+typedef void(*grpc_slice_buffer_undo_take_first_type)(grpc_slice_buffer *src, grpc_slice slice);
+extern grpc_slice_buffer_undo_take_first_type grpc_slice_buffer_undo_take_first_import;
+#define grpc_slice_buffer_undo_take_first grpc_slice_buffer_undo_take_first_import
 typedef void *(*gpr_malloc_type)(size_t size);
 extern gpr_malloc_type gpr_malloc_import;
 #define gpr_malloc gpr_malloc_import
+typedef void *(*gpr_zalloc_type)(size_t size);
+extern gpr_zalloc_type gpr_zalloc_import;
+#define gpr_zalloc gpr_zalloc_import
 typedef void(*gpr_free_type)(void *ptr);
 extern gpr_free_type gpr_free_import;
 #define gpr_free gpr_free_import
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index c7b112c..7b2f5774 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -44,6 +44,7 @@
 #include "rb_channel_args.h"
 #include "rb_completion_queue.h"
 #include "rb_server_credentials.h"
+#include "rb_byte_buffer.h"
 #include "rb_grpc.h"
 
 /* grpc_rb_cServer is the ruby class that proxies grpc_server. */
@@ -166,8 +167,6 @@
   MEMZERO(st, request_call_stack, 1);
   grpc_metadata_array_init(&st->md_ary);
   grpc_call_details_init(&st->details);
-  st->details.method = NULL;
-  st->details.host = NULL;
 }
 
 /* grpc_request_call_stack_cleanup ensures the request_call_stack is properly
@@ -191,6 +190,7 @@
   void *tag = (void*)&st;
   grpc_completion_queue *call_queue = grpc_completion_queue_create(NULL);
   gpr_timespec deadline;
+
   TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
   if (s->wrapped == NULL) {
     rb_raise(rb_eRuntimeError, "destroyed!");
@@ -218,11 +218,13 @@
     return Qnil;
   }
 
+
+
   /* build the NewServerRpc struct result */
   deadline = gpr_convert_clock_type(st.details.deadline, GPR_CLOCK_REALTIME);
   result = rb_struct_new(
-      grpc_rb_sNewServerRpc, rb_str_new2(st.details.method),
-      rb_str_new2(st.details.host),
+      grpc_rb_sNewServerRpc, grpc_rb_slice_to_ruby_string(st.details.method),
+      grpc_rb_slice_to_ruby_string(st.details.host),
       rb_funcall(rb_cTime, id_at, 2, INT2NUM(deadline.tv_sec),
                  INT2NUM(deadline.tv_nsec / 1000)),
       grpc_rb_md_ary_to_h(&st.md_ary), grpc_rb_wrap_call(call, call_queue),
diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb
index 6934257..d8de0be 100644
--- a/src/ruby/lib/grpc/generic/client_stub.rb
+++ b/src/ruby/lib/grpc/generic/client_stub.rb
@@ -84,7 +84,7 @@
     # channel:
     #
     # - :channel_override
-    # when present, this must be a pre-created GRPC::Channel.  If it's
+    # when present, this must be a pre-created GRPC::Core::Channel.  If it's
     # present the host and arbitrary keyword arg areignored, and the RPC
     # connection uses this channel.
     #
diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb
index 79c4a96..ce0892d 100644
--- a/src/ruby/lib/grpc/version.rb
+++ b/src/ruby/lib/grpc/version.rb
@@ -29,5 +29,5 @@
 
 # GRPC contains the General RPC module.
 module GRPC
-  VERSION = '1.1.2'
+  VERSION = '1.2.0.dev'
 end
diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb
index 85ae9fd..8f3d2ba 100644
--- a/src/ruby/tools/version.rb
+++ b/src/ruby/tools/version.rb
@@ -29,6 +29,6 @@
 
 module GRPC
   module Tools
-    VERSION = '1.1.2'
+    VERSION = '1.2.0.dev'
   end
 end
diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template
index a326f36..1c2ef0a 100644
--- a/templates/CMakeLists.txt.template
+++ b/templates/CMakeLists.txt.template
@@ -59,15 +59,27 @@
       deps.append("${_gRPC_PROTOBUF_PROTOC_LIBRARIES}")
     if target_dict.get('secure', False):
       deps.append("${_gRPC_SSL_LIBRARIES}")
-    if target_dict['name'] in ['grpc++', 'grpc++_unsecure', 'grpc++_codegen_lib']:
+    if target_dict.language == 'c++':
       deps.append("${_gRPC_PROTOBUF_LIBRARIES}")
-    elif target_dict['name'] in ['grpc']:
+    if target_dict['name'] in ['grpc']:
       deps.append("${_gRPC_ZLIB_LIBRARIES}")
+    deps.append("${_gRPC_ALLTARGETS_LIBRARIES}")
     for d in target_dict.get('deps', []):
       deps.append(d)
     if target_dict.build == 'test' and target_dict.language == 'c++':
       deps.append("${_gRPC_GFLAGS_LIBRARIES}")
     return deps
+  
+  def get_platforms_condition_begin(platforms):
+    if all(platform in platforms for platform in ['linux', 'mac', 'posix', 'windows']):
+      return ''
+    cond = ' OR '.join(['_gRPC_PLATFORM_%s' % platform.upper() for platform in platforms])
+    return 'if(%s)\n' % cond
+  
+  def get_platforms_condition_end(platforms):
+    if not get_platforms_condition_begin(platforms):
+      return ''
+    return 'endif()\n'
   %>
 
   cmake_minimum_required(VERSION 2.8)
@@ -100,12 +112,30 @@
   set(gRPC_GFLAGS_PROVIDER "module" CACHE STRING "Provider of gflags library")
   set_property(CACHE gRPC_GFLAGS_PROVIDER PROPERTY STRINGS "module" "package")
   
+  set(gRPC_BENCHMARK_PROVIDER "module" CACHE STRING "Provider of benchmark library")
+  set_property(CACHE gRPC_BENCHMARK_PROVIDER PROPERTY STRINGS "module" "package")
+  
   set(gRPC_USE_PROTO_LITE OFF CACHE BOOL "Use the protobuf-lite library")
 
+  if(UNIX)
+    if(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "Linux")
+      set(_gRPC_PLATFORM_LINUX ON)
+    elseif(<%text>${CMAKE_SYSTEM_NAME}</%text> MATCHES "Darwin")
+      set(_gRPC_PLATFORM_MAC ON)
+    else()
+      set(_gRPC_PLATFORM_POSIX ON)
+    endif()
+  endif()
+  if(WIN32)
+    set(_gRPC_PLATFORM_WINDOWS ON)
+  endif()
+  
+  ## Some libraries are shared even with BUILD_SHARED_LIBRARIES=OFF
+  set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+
   if (MSVC)
+    include(cmake/msvc_static_runtime.cmake)
     add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS)
-    # needed to compile boringssl
-    add_definitions(/wd4464 /wd4623 /wd4668 /wd4701 /wd4702 /wd4777 /wd5027)
     # needed to compile protobuf
     add_definitions(/wd4065 /wd4506)
     # TODO(jtattermusch): revisit C4267 occurrences throughout the code
@@ -189,6 +219,7 @@
       set(BORINGSSL_ROOT_DIR <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/third_party/boringssl)
     endif()
     if(EXISTS "<%text>${BORINGSSL_ROOT_DIR}</%text>/CMakeLists.txt")
+      set(OPENSSL_NO_ASM ON)  # make boringssl buildable with Visual Studio
       add_subdirectory(<%text>${BORINGSSL_ROOT_DIR}</%text> third_party/boringssl)
       if(TARGET ssl)
         set(_gRPC_SSL_LIBRARIES ssl)
@@ -223,12 +254,36 @@
     endif()
     set(_gRPC_FIND_GFLAGS "if(NOT gflags_FOUND)\n  find_package(gflags)\nendif()")
   endif()
+  
+  if("<%text>${gRPC_BENCHMARK_PROVIDER}</%text>" STREQUAL "module")
+    if(NOT BENCHMARK_ROOT_DIR)
+      set(BENCHMARK_ROOT_DIR <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/third_party/benchmark)
+    endif()
+    if(EXISTS "<%text>${BENCHMARK_ROOT_DIR}</%text>/CMakeLists.txt")
+        add_subdirectory(<%text>${BENCHMARK_ROOT_DIR}</%text> third_party/benchmark)
+        if(TARGET benchmark)
+            set(_gRPC_BENCHMARK_LIBRARIES benchmark)
+        endif()
+    else()
+        message(WARNING "gRPC_BENCHMARK_PROVIDER is \"module\" but BENCHMARK_ROOT_DIR is wrong")
+    endif()
+  elseif("<%text>${gRPC_BENCHMARK_PROVIDER}</%text>" STREQUAL "package")
+    find_package(benchmark)
+    if(TARGET benchmark::benchmark)
+      set(_gRPC_BENCHMARK_LIBRARIES benchmark::benchmark)
+    endif()
+    set(_gRPC_FIND_BENCHMARK "if(NOT benchmark_FOUND)\n  find_package(benchmark)\nendif()")
+  endif()
 
   if(NOT MSVC)
-    set(CMAKE_C_FLAGS   "<%text>${CMAKE_C_FLAGS}</%text>   -std=c11")
+    set(CMAKE_C_FLAGS   "<%text>${CMAKE_C_FLAGS}</%text> -std=c99")
     set(CMAKE_CXX_FLAGS "<%text>${CMAKE_CXX_FLAGS}</%text> -std=c++11")
   endif()
 
+  if(UNIX)
+    set(_gRPC_ALLTARGETS_LIBRARIES dl rt m pthread)
+  endif()
+
   if(WIN32 AND MSVC)
     set(_gRPC_BASELIB_LIBRARIES wsock32 ws2_32)
   endif()
@@ -287,9 +342,63 @@
     endforeach()
   endfunction()
   
+  add_custom_target(plugins
+    DEPENDS
+  % for tgt in targets:
+  % if tgt.build == 'protoc':
+    ${tgt.name}
+  % endif
+  % endfor
+  )
+  
+  add_custom_target(tools_c
+    DEPENDS
+  % for tgt in targets:
+  % if tgt.build == 'tool' and not tgt.language == 'c++':
+    ${tgt.name}
+  % endif
+  % endfor
+  )
+  
+  add_custom_target(tools_cxx
+    DEPENDS
+  % for tgt in targets:
+  % if tgt.build == 'tool' and tgt.language == 'c++':
+    ${tgt.name}
+  % endif
+  % endfor
+  )
+  
+  add_custom_target(tools
+    DEPENDS tools_c tools_cxx)
+  
+  if (gRPC_BUILD_TESTS)
+  add_custom_target(buildtests_c)
+  % for tgt in targets:
+  % if tgt.build == 'test' and not tgt.language == 'c++' and not tgt.get('external_deps', None) and not tgt.boringssl:
+  ${get_platforms_condition_begin(tgt.platforms)}\
+  add_dependencies(buildtests_c ${tgt.name})
+  ${get_platforms_condition_end(tgt.platforms)}\
+  % endif
+  % endfor
+  
+  add_custom_target(buildtests_cxx)
+  % for tgt in targets:
+  % if tgt.build == 'test' and tgt.language == 'c++' and not tgt.get('external_deps', None) and not tgt.boringssl:
+  ${get_platforms_condition_begin(tgt.platforms)}\
+  add_dependencies(buildtests_cxx ${tgt.name})
+  ${get_platforms_condition_end(tgt.platforms)}\
+  % endif
+  % endfor
+  
+  add_custom_target(buildtests
+    DEPENDS buildtests_c buildtests_cxx)
+  endif (gRPC_BUILD_TESTS)
+  
   % for lib in libs:
-  % if lib.build in ["all", "protoc", "tool", "test", "private"] and lib.language in ['c', 'c++']:
+  % if lib.build in ["all", "protoc", "tool", "test", "private"] and not lib.boringssl:
   % if not lib.get('build_system', []) or 'cmake' in lib.get('build_system', []):
+  % if not lib.name in ['benchmark', 'z']:  # we build these using CMake instead
   % if lib.build in ["test", "private"]:
   if (gRPC_BUILD_TESTS)
   ${cc_library(lib)}
@@ -300,23 +409,28 @@
   % endif
   % endif
   % endif
+  % endif
   % endfor
 
   % for tgt in targets:
-  % if tgt.build in ["all", "protoc", "tool", "test", "private"] and tgt.language in ['c', 'c++']:
+  % if tgt.build in ["all", "protoc", "tool", "test", "private"] and not tgt.boringssl:
   % if tgt.build in ["test", "private"]:
   if (gRPC_BUILD_TESTS)
+  ${get_platforms_condition_begin(tgt.platforms)}\
   ${cc_binary(tgt)}
+  ${get_platforms_condition_end(tgt.platforms)}\
   endif (gRPC_BUILD_TESTS)
   % else:
+  ${get_platforms_condition_begin(tgt.platforms)}\
   ${cc_binary(tgt)}
   ${cc_install(tgt)}
+  ${get_platforms_condition_end(tgt.platforms)}\
   % endif
   % endif
   % endfor
 
   <%def name="cc_library(lib)">
-  add_library(${lib.name}
+  add_library(${lib.name}${' SHARED' if lib.get('dll', None) == 'only' else ''}
   % for src in lib.src:
   % if not proto_re.match(src):
     ${src}
@@ -328,7 +442,18 @@
   % endif
   % endfor
   )
-  
+
+  if(WIN32 AND MSVC)
+    set_target_properties(${lib.name} PROPERTIES COMPILE_PDB_NAME "${lib.name}"
+      COMPILE_PDB_OUTPUT_DIRECTORY <%text>"${CMAKE_BINARY_DIR}</%text>"
+    )
+    if (gRPC_INSTALL)
+      install(FILES <%text>${CMAKE_CURRENT_BINARY_DIR}/</%text>${lib.name}.pdb
+        DESTINATION <%text>${CMAKE_INSTALL_LIBDIR}</%text> OPTIONAL
+      )
+    endif()
+  endif()
+
   % for src in lib.src:
   % if proto_re.match(src):
   protobuf_generate_grpc_cpp(
@@ -343,13 +468,14 @@
     PRIVATE <%text>${BORINGSSL_ROOT_DIR}</%text>/include
     PRIVATE <%text>${PROTOBUF_ROOT_DIR}</%text>/src
     PRIVATE <%text>${ZLIB_INCLUDE_DIR}</%text>
+    PRIVATE <%text>${BENCHMARK}</%text>/include
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/zlib
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/gflags/include
   % if lib.build in ['test', 'private'] and lib.language == 'c++':
     PRIVATE third_party/googletest/include
     PRIVATE third_party/googletest
   % endif
-  % if any(proto_re.match(src) for src in lib.src):
+  % if lib.language == 'c++':
     PRIVATE <%text>${_gRPC_PROTO_GENS_DIR}</%text>
   % endif
   )
@@ -380,18 +506,34 @@
   <%def name="cc_binary(tgt)">
   add_executable(${tgt.name}
   % for src in tgt.src:
+  % if not proto_re.match(src):
     ${src}
+  % else:
+    ${proto_replace_ext(src, '.pb.cc')}
+    ${proto_replace_ext(src, '.grpc.pb.cc')}
+    ${proto_replace_ext(src, '.pb.h')}
+    ${proto_replace_ext(src, '.grpc.pb.h')}
+  % endif
   % endfor
   % if tgt.build == 'test' and tgt.language == 'c++':
     third_party/googletest/src/gtest-all.cc
   % endif
   )
+  
+  % for src in tgt.src:
+  % if proto_re.match(src):
+  protobuf_generate_grpc_cpp(
+    ${src}
+  )
+  % endif
+  % endfor
 
   target_include_directories(${tgt.name}
     PRIVATE <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>
     PRIVATE <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/include
     PRIVATE <%text>${BORINGSSL_ROOT_DIR}</%text>/include
     PRIVATE <%text>${PROTOBUF_ROOT_DIR}</%text>/src
+    PRIVATE <%text>${BENCHMARK_ROOT_DIR}</%text>/include
     PRIVATE <%text>${ZLIB_ROOT_DIR}</%text>
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/zlib
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/gflags/include
@@ -399,6 +541,9 @@
     PRIVATE third_party/googletest/include
     PRIVATE third_party/googletest
   % endif
+  % if tgt.language == 'c++':
+    PRIVATE <%text>${_gRPC_PROTO_GENS_DIR}</%text>
+  % endif
   )
 
   % if len(get_deps(tgt)) > 0:
@@ -420,13 +565,6 @@
   endif()
   </%def>
 
-  if (gRPC_INSTALL)
-    install(EXPORT gRPCTargets
-      DESTINATION <%text>${CMAKE_INSTALL_CMAKEDIR}</%text>
-      NAMESPACE gRPC::
-    )
-  endif()
-
   foreach(_config gRPCConfig gRPCConfigVersion)
     configure_file(tools/cmake/<%text>${_config}</%text>.cmake.in
       <%text>${_config}</%text>.cmake @ONLY)
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 3bab79b..f81d643 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -135,9 +135,6 @@
   ${arg}_${name} = ${args.get(arg)}
   %   endif
   %  endfor
-  %  if args.get('timeout_multiplier', 1) != 1:
-  DEFINES_${name} += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=${args.timeout_multiplier}
-  %  endif
 
   % endfor
 
diff --git a/templates/composer.json.template b/templates/composer.json.template
index 3b4d62f..f56ecb6 100644
--- a/templates/composer.json.template
+++ b/templates/composer.json.template
@@ -9,8 +9,7 @@
     "license": "BSD-3-Clause",
     "require": {
       "php": ">=5.5.0",
-      "ext-grpc": "*",
-      "google/protobuf": "v3.1.0-alpha-1"
+      "google/protobuf": "v3.1.0"
     },
     "require-dev": {
       "google/auth": "v0.9"
diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template
index 66b3659..f05ee4c 100644
--- a/templates/gRPC-Core.podspec.template
+++ b/templates/gRPC-Core.podspec.template
@@ -161,7 +161,8 @@
 
     s.subspec 'Cronet-Interface' do |ss|
       ss.header_mappings_dir = 'include/grpc'
-      ss.source_files = 'include/grpc/grpc_cronet.h'
+      ss.source_files = 'include/grpc/grpc_cronet.h',
+                        'src/core/ext/transport/cronet/transport/cronet_transport.h'
     end
 
     s.subspec 'Cronet-Implementation' do |ss|
@@ -173,7 +174,7 @@
 
       ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c',
                         'src/core/ext/transport/cronet/transport/cronet_transport.c',
-                        'third_party/Cronet/bidirectional_stream_c.h'
+                        'third_party/objective_c/Cronet/bidirectional_stream_c.h'
     end
 
     s.subspec 'Tests' do |ss|
@@ -187,6 +188,7 @@
                         'test/core/end2end/end2end_test_utils.c',
                         'test/core/end2end/tests/*.{c,h}',
                         'test/core/end2end/data/*.{c,h}',
+                        'test/core/util/debugger_macros.c',
                         'test/core/util/test_config.{c,h}',
                         'test/core/util/port.h',
                         'test/core/util/port_posix.c',
diff --git a/templates/src/csharp/Grpc.Core.Testing/project.json.template b/templates/src/csharp/Grpc.Core.Testing/project.json.template
new file mode 100644
index 0000000..7aff991
--- /dev/null
+++ b/templates/src/csharp/Grpc.Core.Testing/project.json.template
@@ -0,0 +1,41 @@
+%YAML 1.2
+--- |
+  {
+    "version": "${settings.csharp_version}",
+    "title": "gRPC C# Core Testing",
+    "authors": [ "Google Inc." ],
+    "copyright": "Copyright 2017, Google Inc.",
+    "packOptions": {
+      "summary": "Testing support for gRPC C#",
+      "description": "Useful when testing code that uses gRPC.",
+      "owners": [ "grpc-packages" ],
+      "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
+      "projectUrl": "https://github.com/grpc/grpc",
+      "requireLicenseAcceptance": false,
+      "tags": [ "gRPC test testing" ]
+    },
+    "buildOptions": {
+      "define": [ "SIGNED" ],
+      "keyFile": "../keys/Grpc.snk",
+      "xmlDoc": true,
+      "compile": {
+        "includeFiles": [ "../Grpc.Core/Version.cs" ]
+      }
+    },
+    "dependencies": {
+      "Grpc.Core": "${settings.csharp_version}"
+    },
+    "frameworks": {
+      "net45": {
+        "frameworkAssemblies": {
+          "System.Runtime": "",
+          "System.IO": ""
+        }
+      },
+      "netstandard1.5": {
+        "dependencies": {
+          "NETStandard.Library": "1.6.0"
+        }
+      }
+    }
+  }
diff --git a/templates/src/csharp/build_options.include b/templates/src/csharp/build_options.include
index 9a32b7c..db4cc19 100644
--- a/templates/src/csharp/build_options.include
+++ b/templates/src/csharp/build_options.include
@@ -21,8 +21,8 @@
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
             % endif
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
           }
@@ -44,8 +44,8 @@
             "data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
             "data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
             % endif
-            "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
-            "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+            "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
             "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
             "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
           }
diff --git a/templates/src/csharp/build_packages_dotnetcli.bat.template b/templates/src/csharp/build_packages_dotnetcli.bat.template
index 562b770..2f91d48 100755
--- a/templates/src/csharp/build_packages_dotnetcli.bat.template
+++ b/templates/src/csharp/build_packages_dotnetcli.bat.template
@@ -61,6 +61,7 @@
   %%DOTNET% restore . || goto :error
   
   %%DOTNET% pack --configuration Release Grpc.Core\project.json --output ..\..\artifacts || goto :error
+  %%DOTNET% pack --configuration Release Grpc.Core.Testing\project.json --output ..\..\artifacts || goto :error
   %%DOTNET% pack --configuration Release Grpc.Auth\project.json --output ..\..\artifacts || goto :error
   %%DOTNET% pack --configuration Release Grpc.HealthCheck\project.json --output ..\..\artifacts || goto :error
   %%DOTNET% pack --configuration Release Grpc.Reflection\project.json --output ..\..\artifacts || goto :error
diff --git a/templates/src/csharp/build_packages_dotnetcli.sh.template b/templates/src/csharp/build_packages_dotnetcli.sh.template
index 91c6fb6..c536437 100755
--- a/templates/src/csharp/build_packages_dotnetcli.sh.template
+++ b/templates/src/csharp/build_packages_dotnetcli.sh.template
@@ -63,6 +63,7 @@
   dotnet restore .
   
   dotnet pack --configuration Release Grpc.Core/project.json --output ../../artifacts
+  dotnet pack --configuration Release Grpc.Core.Testing/project.json --output ../../artifacts
   dotnet pack --configuration Release Grpc.Auth/project.json --output ../../artifacts
   dotnet pack --configuration Release Grpc.HealthCheck/project.json --output ../../artifacts
   dotnet pack --configuration Release Grpc.Reflection/project.json --output ../../artifacts
diff --git a/templates/src/php/composer.json.template b/templates/src/php/composer.json.template
index 12a4ce8..ecc516d 100644
--- a/templates/src/php/composer.json.template
+++ b/templates/src/php/composer.json.template
@@ -1,24 +1,22 @@
 %YAML 1.2
 --- |
   {
-    "name": "grpc/grpc",
-    "type": "library",
-    "description": "gRPC library for PHP",
-    "keywords": ["rpc"],
-    "homepage": "http://grpc.io",
+    "name": "grpc/grpc-dev",
+    "description": "gRPC library for PHP - for Developement use only",
     "license": "BSD-3-Clause",
     "version": "${settings.php_version.php_composer()}",
     "require": {
       "php": ">=5.5.0",
-      "ext-grpc": "*",
-      "google/protobuf": "v3.1.0-alpha-1"
+      "google/protobuf": "v3.1.0"
     },
     "require-dev": {
       "google/auth": "v0.9"
     },
     "autoload": {
       "psr-4": {
-        "Grpc\\": "lib/Grpc/"
+        "Grpc\\": "lib/Grpc/",
+        "": ["tests/interop/",
+             "tests/generated_code/"]
       }
     }
   }
diff --git a/templates/test/core/end2end/end2end_defs.include b/templates/test/core/end2end/end2end_defs.include
index b828f84..68b9e69 100644
--- a/templates/test/core/end2end/end2end_defs.include
+++ b/templates/test/core/end2end/end2end_defs.include
@@ -42,6 +42,8 @@
 
 #include <grpc/support/log.h>
 
+#include "test/core/util/debugger_macros.h"
+
 static bool g_pre_init_called = false;
 
 % for test in tests:
@@ -52,6 +54,7 @@
 void grpc_end2end_tests_pre_init(void) {
   GPR_ASSERT(!g_pre_init_called);
   g_pre_init_called = true;
+  grpc_summon_debugger_macros();
 % for test in tests:
   ${test}_pre_init();
 % endfor
diff --git a/templates/tools/run_tests/generated/tests.json.template b/templates/tools/run_tests/generated/tests.json.template
index 1e21465..10ab2e4 100644
--- a/templates/tools/run_tests/generated/tests.json.template
+++ b/templates/tools/run_tests/generated/tests.json.template
@@ -2,18 +2,28 @@
 --- |
   <%!
   import json
+
+  def gen_one_target(tgt):
+    out = {"name": tgt.name,
+           "language": tgt.language,
+           "platforms": tgt.platforms,
+           "ci_platforms": tgt.ci_platforms,
+           "gtest": tgt.gtest,
+           "exclude_configs": tgt.get("exclude_configs", []),
+           "exclude_iomgrs": tgt.get("exclude_iomgrs", []),
+           "args": tgt.get("args", []),
+           "flaky": tgt.flaky,
+           "cpu_cost": tgt.get("cpu_cost", 1.0)}
+    timeout_seconds = tgt.get("timeout_seconds", None)
+    if timeout_seconds:
+      out['timeout_seconds'] = timeout_seconds
+    excluded_poll_engines = tgt.get("excluded_poll_engines", None)
+    if excluded_poll_engines:
+      out['excluded_poll_engines'] = excluded_poll_engines
+    return out
   %>
 
-  ${json.dumps([{"name": tgt.name,
-                 "language": tgt.language,
-                 "platforms": tgt.platforms,
-                 "ci_platforms": tgt.ci_platforms,
-                 "gtest": tgt.gtest,
-                 "exclude_configs": tgt.get("exclude_configs", []),
-                 "exclude_iomgrs": tgt.get("exclude_iomgrs", []),
-                 "args": [],
-                 "flaky": tgt.flaky,
-                 "cpu_cost": tgt.get("cpu_cost", 1.0)}
+  ${json.dumps([gen_one_target(tgt)
                 for tgt in targets
                 if tgt.get('run', True) and tgt.build == 'test'] +
                 tests,
diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c
index a840868..fdedfe2 100644
--- a/test/core/bad_client/bad_client.c
+++ b/test/core/bad_client/bad_client.c
@@ -160,16 +160,17 @@
 
   /* Await completion */
   GPR_ASSERT(
-      gpr_event_wait(&a.done_write, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5)));
+      gpr_event_wait(&a.done_write, grpc_timeout_seconds_to_deadline(5)));
 
   if (flags & GRPC_BAD_CLIENT_DISCONNECT) {
-    grpc_endpoint_shutdown(&exec_ctx, sfd.client);
+    grpc_endpoint_shutdown(&exec_ctx, sfd.client,
+                           GRPC_ERROR_CREATE("Forced Disconnect"));
     grpc_endpoint_destroy(&exec_ctx, sfd.client);
     grpc_exec_ctx_finish(&exec_ctx);
     sfd.client = NULL;
   }
 
-  GPR_ASSERT(gpr_event_wait(&a.done_thd, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5)));
+  GPR_ASSERT(gpr_event_wait(&a.done_thd, grpc_timeout_seconds_to_deadline(5)));
 
   if (sfd.client != NULL) {
     // Validate client stream, if requested.
@@ -185,17 +186,18 @@
                          &read_done_closure);
       grpc_exec_ctx_finish(&exec_ctx);
       GPR_ASSERT(
-          gpr_event_wait(&args.read_done, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5)));
+          gpr_event_wait(&args.read_done, grpc_timeout_seconds_to_deadline(5)));
       grpc_slice_buffer_destroy_internal(&exec_ctx, &args.incoming);
     }
     // Shutdown.
-    grpc_endpoint_shutdown(&exec_ctx, sfd.client);
+    grpc_endpoint_shutdown(&exec_ctx, sfd.client,
+                           GRPC_ERROR_CREATE("Test Shutdown"));
     grpc_endpoint_destroy(&exec_ctx, sfd.client);
     grpc_exec_ctx_finish(&exec_ctx);
   }
   grpc_server_shutdown_and_notify(a.server, a.cq, NULL);
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 a.cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)
+                 a.cq, NULL, grpc_timeout_seconds_to_deadline(1), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(a.server);
   grpc_completion_queue_destroy(a.cq);
diff --git a/test/core/bad_client/tests/badreq.c b/test/core/bad_client/tests/badreq.c
index 5d9ffef..7b22f88 100644
--- a/test/core/bad_client/tests/badreq.c
+++ b/test/core/bad_client/tests/badreq.c
@@ -46,7 +46,7 @@
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
     GPR_ASSERT(grpc_completion_queue_next(
-                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   cq, grpc_timeout_milliseconds_to_deadline(20), NULL)
                    .type == GRPC_QUEUE_TIMEOUT);
   }
 }
diff --git a/test/core/bad_client/tests/connection_prefix.c b/test/core/bad_client/tests/connection_prefix.c
index bc5ed2e..42787ab9 100644
--- a/test/core/bad_client/tests/connection_prefix.c
+++ b/test/core/bad_client/tests/connection_prefix.c
@@ -38,7 +38,7 @@
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
     GPR_ASSERT(grpc_completion_queue_next(
-                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   cq, grpc_timeout_milliseconds_to_deadline(20), NULL)
                    .type == GRPC_QUEUE_TIMEOUT);
   }
 }
diff --git a/test/core/bad_client/tests/headers.c b/test/core/bad_client/tests/headers.c
index f872e50..ab47821 100644
--- a/test/core/bad_client/tests/headers.c
+++ b/test/core/bad_client/tests/headers.c
@@ -42,7 +42,7 @@
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
     GPR_ASSERT(grpc_completion_queue_next(
-                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   cq, grpc_timeout_milliseconds_to_deadline(20), NULL)
                    .type == GRPC_QUEUE_TIMEOUT);
   }
 }
diff --git a/test/core/bad_client/tests/initial_settings_frame.c b/test/core/bad_client/tests/initial_settings_frame.c
index b84b67a..890efd8 100644
--- a/test/core/bad_client/tests/initial_settings_frame.c
+++ b/test/core/bad_client/tests/initial_settings_frame.c
@@ -41,7 +41,7 @@
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
     GPR_ASSERT(grpc_completion_queue_next(
-                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   cq, grpc_timeout_milliseconds_to_deadline(20), NULL)
                    .type == GRPC_QUEUE_TIMEOUT);
   }
 }
diff --git a/test/core/bad_client/tests/large_metadata.c b/test/core/bad_client/tests/large_metadata.c
index 9c804e7..f672776 100644
--- a/test/core/bad_client/tests/large_metadata.c
+++ b/test/core/bad_client/tests/large_metadata.c
@@ -126,8 +126,8 @@
   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.host, "localhost"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));
 
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
@@ -153,16 +153,14 @@
   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.host, "localhost"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));
 
   const size_t metadata_value_size = 16 * 1024;
   grpc_metadata meta;
-  meta.key = "key";
-  meta.value = gpr_malloc(metadata_value_size + 1);
-  memset((char *)meta.value, 'a', metadata_value_size);
-  ((char *)meta.value)[metadata_value_size] = 0;
-  meta.value_length = metadata_value_size;
+  meta.key = grpc_slice_from_static_string("key");
+  meta.value = grpc_slice_malloc(metadata_value_size);
+  memset(GRPC_SLICE_START_PTR(meta.value), 'a', metadata_value_size);
 
   grpc_op op;
   memset(&op, 0, sizeof(op));
@@ -176,7 +174,7 @@
   CQ_EXPECT_COMPLETION(cqv, tag(102), 0);  // Operation fails.
   cq_verify(cqv);
 
-  gpr_free((char *)meta.value);
+  grpc_slice_unref(meta.value);
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
   grpc_call_destroy(s);
@@ -190,29 +188,26 @@
   grpc_slice_buffer_trim_end(incoming, 13, &last_frame_buffer);
   GPR_ASSERT(last_frame_buffer.count == 1);
   grpc_slice last_frame = last_frame_buffer.slices[0];
-  // Construct expected frame.
-  grpc_slice expected = grpc_slice_malloc(13);
-  uint8_t *p = GRPC_SLICE_START_PTR(expected);
-  // Length.
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 4;
-  // Frame type (RST_STREAM).
-  *p++ = 3;
-  // Flags.
-  *p++ = 0;
+  const uint8_t *p = GRPC_SLICE_START_PTR(last_frame);
+  // Length = 4
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 4);
+  // Frame type (RST_STREAM)
+  GPR_ASSERT(*p++ == 3);
+  // Flags
+  GPR_ASSERT(*p++ == 0);
   // Stream ID.
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 1;
-  // Payload (error code).
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 11;
-  // Compare actual and expected.
-  GPR_ASSERT(grpc_slice_cmp(last_frame, expected) == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 1);
+  // Payload (error code)
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p == 0 || *p == 11);
+
   grpc_slice_buffer_destroy(&last_frame_buffer);
 }
 
diff --git a/test/core/bad_client/tests/simple_request.c b/test/core/bad_client/tests/simple_request.c
index c08aa40..608b849 100644
--- a/test/core/bad_client/tests/simple_request.c
+++ b/test/core/bad_client/tests/simple_request.c
@@ -117,8 +117,8 @@
   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.host, "localhost"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));
 
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
@@ -130,7 +130,7 @@
                              void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
     GPR_ASSERT(grpc_completion_queue_next(
-                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   cq, grpc_timeout_milliseconds_to_deadline(20), NULL)
                    .type == GRPC_QUEUE_TIMEOUT);
   }
 }
diff --git a/test/core/bad_client/tests/unknown_frame.c b/test/core/bad_client/tests/unknown_frame.c
index 4f483d2..1d04699 100644
--- a/test/core/bad_client/tests/unknown_frame.c
+++ b/test/core/bad_client/tests/unknown_frame.c
@@ -42,7 +42,7 @@
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
     GPR_ASSERT(grpc_completion_queue_next(
-                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   cq, grpc_timeout_milliseconds_to_deadline(20), NULL)
                    .type == GRPC_QUEUE_TIMEOUT);
   }
 }
diff --git a/test/core/bad_client/tests/window_overflow.c b/test/core/bad_client/tests/window_overflow.c
index 0d17dbe..7db8590 100644
--- a/test/core/bad_client/tests/window_overflow.c
+++ b/test/core/bad_client/tests/window_overflow.c
@@ -61,7 +61,7 @@
                      void *registered_method) {
   while (grpc_server_has_open_connections(server)) {
     GPR_ASSERT(grpc_completion_queue_next(
-                   cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(20), NULL)
+                   cq, grpc_timeout_milliseconds_to_deadline(20), NULL)
                    .type == GRPC_QUEUE_TIMEOUT);
   }
 }
diff --git a/test/core/bad_ssl/bad_ssl_test.c b/test/core/bad_ssl/bad_ssl_test.c
index 41b514b..bd85585 100644
--- a/test/core/bad_ssl/bad_ssl_test.c
+++ b/test/core/bad_ssl/bad_ssl_test.c
@@ -57,11 +57,10 @@
 
   grpc_metadata_array initial_metadata_recv;
   grpc_metadata_array trailing_metadata_recv;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_status_code status;
   grpc_call_error error;
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
   grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
   cq_verifier *cqv = cq_verifier_create(cq);
 
@@ -80,9 +79,10 @@
   grpc_metadata_array_init(&trailing_metadata_recv);
 
   channel = grpc_secure_channel_create(ssl_creds, target, &args, NULL);
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr:1234");
   c = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                               "/foo", "foo.test.google.fr:1234", deadline,
-                               NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
 
   memset(ops, 0, sizeof(ops));
   op = ops;
@@ -95,7 +95,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -117,7 +116,7 @@
   GPR_ASSERT(status != GRPC_STATUS_OK);
 
   grpc_call_destroy(c);
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
diff --git a/test/core/bad_ssl/server_common.c b/test/core/bad_ssl/server_common.c
index 14b1892..6a4313e 100644
--- a/test/core/bad_ssl/server_common.c
+++ b/test/core/bad_ssl/server_common.c
@@ -84,7 +84,7 @@
       gpr_log(GPR_INFO, "Shutting down due to SIGINT");
       grpc_server_shutdown_and_notify(server, cq, NULL);
       GPR_ASSERT(grpc_completion_queue_pluck(
-                     cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                     cq, NULL, grpc_timeout_seconds_to_deadline(5), NULL)
                      .type == GRPC_OP_COMPLETE);
       grpc_completion_queue_shutdown(cq);
       shutdown_started = 1;
diff --git a/test/core/census/BUILD b/test/core/census/BUILD
new file mode 100644
index 0000000..9ec48bd
--- /dev/null
+++ b/test/core/census/BUILD
@@ -0,0 +1,91 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+cc_test(
+    name = "context_test",
+    srcs = ["context_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "mlog_test",
+    srcs = ["mlog_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "resource_test",
+    srcs = ["resource_test.c"],
+    copts = ["-std=c99"],
+    data = [
+        ":data/resource_empty_name.pb",
+        ":data/resource_full.pb",
+        ":data/resource_minimal_good.pb",
+        ":data/resource_no_name.pb",
+        ":data/resource_no_numerator.pb",
+        ":data/resource_no_unit.pb",
+    ],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "trace_context_test",
+    srcs = ["trace_context_test.c"],
+    copts = ["-std=c99"],
+    data = [
+        ":data/context_empty.pb",
+        ":data/context_full.pb",
+        ":data/context_no_span_options.pb",
+        ":data/context_span_only.pb",
+        ":data/context_trace_only.pb",
+    ],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/census/data/context_full.pb b/test/core/census/data/context_full.pb
index 80ebcf2..7b5895c 100644
--- a/test/core/census/data/context_full.pb
+++ b/test/core/census/data/context_full.pb
Binary files differ
diff --git a/test/core/census/data/context_full.txt b/test/core/census/data/context_full.txt
index 7901a10..7d8df37 100644
--- a/test/core/census/data/context_full.txt
+++ b/test/core/census/data/context_full.txt
@@ -1,3 +1,4 @@
-trace_id { hi : 5; lo : 1 }
+trace_id_hi : 5
+trace_id_lo : 1
 span_id : 7
-is_sampled : true
+span_options : 1
diff --git a/test/core/census/data/context_no_sample.pb b/test/core/census/data/context_no_sample.pb
deleted file mode 100644
index ab7ad7d..0000000
--- a/test/core/census/data/context_no_sample.pb
+++ /dev/null
Binary files differ
diff --git a/test/core/census/data/context_no_sample.txt b/test/core/census/data/context_no_sample.txt
deleted file mode 100644
index 1502980..0000000
--- a/test/core/census/data/context_no_sample.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-trace_id { hi : 5; lo : 1 }
-span_id : 7
diff --git a/test/core/census/data/context_no_span_options.pb b/test/core/census/data/context_no_span_options.pb
new file mode 100644
index 0000000..4b3425a
--- /dev/null
+++ b/test/core/census/data/context_no_span_options.pb
Binary files differ
diff --git a/test/core/census/data/context_no_span_options.txt b/test/core/census/data/context_no_span_options.txt
new file mode 100644
index 0000000..4c8398f
--- /dev/null
+++ b/test/core/census/data/context_no_span_options.txt
@@ -0,0 +1,3 @@
+trace_id_hi : 5
+trace_id_lo : 1
+span_id : 7
diff --git a/test/core/census/data/context_span_only.pb b/test/core/census/data/context_span_only.pb
index 2a9527a..a9315be 100644
--- a/test/core/census/data/context_span_only.pb
+++ b/test/core/census/data/context_span_only.pb
Binary files differ
diff --git a/test/core/census/data/context_span_only.txt b/test/core/census/data/context_span_only.txt
index d90de2e..4e473fc 100644
--- a/test/core/census/data/context_span_only.txt
+++ b/test/core/census/data/context_span_only.txt
@@ -1,2 +1,2 @@
 span_id : 7
-is_sampled : true
+span_options : 1
diff --git a/test/core/census/data/context_trace_only.pb b/test/core/census/data/context_trace_only.pb
index 7fdf6f6..aabb325 100644
--- a/test/core/census/data/context_trace_only.pb
+++ b/test/core/census/data/context_trace_only.pb
Binary files differ
diff --git a/test/core/census/data/context_trace_only.txt b/test/core/census/data/context_trace_only.txt
index 9b68a6a..e48a6d7 100644
--- a/test/core/census/data/context_trace_only.txt
+++ b/test/core/census/data/context_trace_only.txt
@@ -1,2 +1,3 @@
-trace_id { hi : 5; lo : 1 }
-is_sampled : true
+trace_id_hi : 5
+trace_id_lo : 1
+span_options : 1
diff --git a/test/core/census/mlog_test.c b/test/core/census/mlog_test.c
index 36e8a49..e2605d1 100644
--- a/test/core/census/mlog_test.c
+++ b/test/core/census/mlog_test.c
@@ -185,7 +185,7 @@
             "written\n",
             args->index, records_written, args->num_records);
       }
-      gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10));
+      gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10));
     }
   }
   // Done. Decrement count and signal.
diff --git a/test/core/census/trace_context_test.c b/test/core/census/trace_context_test.c
index ee409e8..5963b1a 100644
--- a/test/core/census/trace_context_test.c
+++ b/test/core/census/trace_context_test.c
@@ -59,7 +59,6 @@
                                     uint8_t *buffer, size_t buf_size) {
   google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero;
   size_t msg_length;
-  GPR_ASSERT(ctxt1->has_trace_id && ctxt1->has_span_id);
 
   msg_length = encode_trace_context(ctxt1, buffer, buf_size);
   if (msg_length == 0) {
@@ -70,16 +69,17 @@
     return false;
   }
 
-  if (!ctxt2.has_trace_id || !ctxt2.has_span_id) {
+  if (!ctxt2.has_trace_id_hi || !ctxt2.has_trace_id_lo || !ctxt2.has_span_id) {
     return false;
   }
 
-  GPR_ASSERT(
-      ctxt1->trace_id.hi == ctxt2.trace_id.hi &&
-      ctxt1->trace_id.lo == ctxt2.trace_id.lo &&
-      ctxt1->span_id == ctxt2.span_id &&
-      ctxt1->has_is_sampled == ctxt2.has_is_sampled &&
-      (ctxt1->has_is_sampled ? ctxt1->is_sampled == ctxt2.is_sampled : true));
+  GPR_ASSERT(ctxt1->trace_id_hi == ctxt2.trace_id_hi &&
+             ctxt1->trace_id_lo == ctxt2.trace_id_lo &&
+             ctxt1->span_id == ctxt2.span_id &&
+             ctxt1->has_span_options == ctxt2.has_span_options &&
+             (ctxt1->has_span_options
+                  ? ctxt1->span_options == ctxt2.span_options
+                  : true));
 
   return true;
 }
@@ -94,7 +94,7 @@
     return false;
   }
 
-  if (!ctxt->has_trace_id || !ctxt->has_span_id) {
+  if (!ctxt->has_trace_id_hi || !ctxt->has_trace_id_lo || !ctxt->has_span_id) {
     return false;
   }
 
@@ -144,49 +144,48 @@
       &ctxt, "test/core/census/data/context_span_only.pb", false);
 }
 
-// Test proto-buffer without is_sampled value.
-static void test_no_sample() {
+// Test proto-buffer without span_options value.
+static void test_no_span_options() {
   google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
   read_and_validate_context_from_file(
-      &ctxt, "test/core/census/data/context_no_sample.pb", true);
-  GPR_ASSERT(ctxt.has_is_sampled == false && ctxt.is_sampled == false);
+      &ctxt, "test/core/census/data/context_no_span_options.pb", true);
+  GPR_ASSERT(ctxt.has_span_options == false && ctxt.span_options == 0);
 }
 
 static void test_encode_decode() {
   uint8_t buffer[BUF_SIZE] = {0};
 
   google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
-  ctxt1.has_trace_id = true;
-  ctxt1.trace_id.has_hi = true;
-  ctxt1.trace_id.has_lo = true;
-  ctxt1.trace_id.lo = 1;
-  ctxt1.trace_id.hi = 2;
+  ctxt1.has_trace_id_hi = true;
+  ctxt1.has_trace_id_lo = true;
+  ctxt1.trace_id_lo = 1;
+  ctxt1.trace_id_hi = 2;
   ctxt1.has_span_id = true;
   ctxt1.span_id = 3;
   validate_encode_decode_context(&ctxt1, buffer, sizeof(buffer));
 
+  // Missing trace_id. This should fail.
   google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero;
-  ctxt2.has_trace_id = true;
-  ctxt2.trace_id.has_hi = false;
-  ctxt2.trace_id.has_lo = false;
+  ctxt2.has_trace_id_hi = false;
+  ctxt2.has_trace_id_lo = false;
   ctxt2.has_span_id = true;
   validate_encode_decode_context(&ctxt2, buffer, sizeof(buffer));
 }
 
-// Test a corrupted proto-buffer.
+// Test a corrupted proto-buffer. This should fail.
 static void test_corrupt() {
   uint8_t buffer[BUF_SIZE] = {0};
   google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
   size_t msg_length;
 
-  ctxt1.has_trace_id = true;
-  ctxt1.trace_id.has_hi = true;
-  ctxt1.trace_id.has_lo = true;
-  ctxt1.trace_id.lo = 1;
-  ctxt1.trace_id.hi = 2;
+  ctxt1.has_trace_id_hi = true;
+  ctxt1.has_trace_id_lo = true;
+  ctxt1.trace_id_lo = 1;
+  ctxt1.trace_id_hi = 2;
   ctxt1.has_span_id = true;
   ctxt1.span_id = 3;
-  ctxt1.is_sampled = true;
+  ctxt1.has_span_options = true;
+  ctxt1.span_options = SPAN_OPTIONS_IS_SAMPLED;
   msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer));
 
   /* Corrupt some bytes.  255 (0xFF) should be illegal for the first byte of the
@@ -198,19 +197,19 @@
 }
 
 static void test_buffer_size() {
-  // This buffer is too small, so the encode should fail.
+  // This buffer is too small. This should fail.
   uint8_t buffer[16] = {0};
   google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
   size_t msg_length;
 
-  ctxt1.has_trace_id = true;
-  ctxt1.trace_id.has_hi = true;
-  ctxt1.trace_id.has_lo = true;
-  ctxt1.trace_id.lo = 1;
-  ctxt1.trace_id.hi = 2;
+  ctxt1.has_trace_id_hi = true;
+  ctxt1.has_trace_id_lo = true;
+  ctxt1.trace_id_lo = 1;
+  ctxt1.trace_id_hi = 2;
   ctxt1.has_span_id = true;
   ctxt1.span_id = 3;
-  ctxt1.is_sampled = true;
+  ctxt1.has_span_options = true;
+  ctxt1.span_options = SPAN_OPTIONS_IS_SAMPLED;
   msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer));
 
   GPR_ASSERT(msg_length == 0);
@@ -224,7 +223,7 @@
   test_span_only();
   test_encode_decode();
   test_corrupt();
-  test_no_sample();
+  test_no_span_options();
   test_buffer_size();
 
   return 0;
diff --git a/test/core/channel/BUILD b/test/core/channel/BUILD
new file mode 100644
index 0000000..42cb468
--- /dev/null
+++ b/test/core/channel/BUILD
@@ -0,0 +1,52 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+cc_test(
+    name = "channel_args_test",
+    srcs = ["channel_args_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "channel_stack_test",
+    srcs = ["channel_stack_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c
index 080c56f..76bb573 100644
--- a/test/core/channel/channel_stack_test.c
+++ b/test/core/channel/channel_stack_test.c
@@ -39,6 +39,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/slice/slice_internal.h"
 #include "test/core/util/test_config.h"
 
 static grpc_error *channel_init_func(grpc_exec_ctx *exec_ctx,
@@ -56,7 +57,7 @@
 
 static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   ++*(int *)(elem->channel_data);
   *(int *)(elem->call_data) = 0;
   return GRPC_ERROR_NONE;
@@ -120,7 +121,7 @@
   int *channel_data;
   int *call_data;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_mdstr *path = grpc_mdstr_from_string("/service/method");
+  grpc_slice path = grpc_slice_from_static_string("/service/method");
 
   arg.type = GRPC_ARG_INTEGER;
   arg.key = "test_key";
@@ -157,7 +158,7 @@
 
   GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done");
 
-  GRPC_MDSTR_UNREF(&exec_ctx, path);
+  grpc_slice_unref_internal(&exec_ctx, path);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD
new file mode 100644
index 0000000..a29e9ac
--- /dev/null
+++ b/test/core/client_channel/BUILD
@@ -0,0 +1,54 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
+
+grpc_fuzzer(
+  name = "uri_fuzzer_test",
+  srcs = ["uri_fuzzer_test.c"],
+  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
+  corpus = "uri_corpus",
+  copts = ["-std=c99"],
+)
+
+cc_test(
+    name = "lb_policies_test",
+    srcs = ["lb_policies_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:cq_verifier"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "set_initial_connect_string_test",
+    srcs = ["set_initial_connect_string_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/client_channel/lb_policies_test.c b/test/core/client_channel/lb_policies_test.c
index a34741e..057b90e 100644
--- a/test/core/client_channel/lb_policies_test.c
+++ b/test/core/client_channel/lb_policies_test.c
@@ -157,8 +157,7 @@
 typedef struct request_data {
   grpc_metadata_array initial_metadata_recv;
   grpc_metadata_array trailing_metadata_recv;
-  char *details;
-  size_t details_capacity;
+  grpc_slice details;
   grpc_status_code status;
   grpc_call_details *call_details;
 } request_data;
@@ -272,8 +271,6 @@
 
   for (iter_num = 0; iter_num < spec->num_iters; iter_num++) {
     cq_verifier *cqv = cq_verifier_create(f->cq);
-    rdata->details = NULL;
-    rdata->details_capacity = 0;
     was_cancelled = 2;
 
     for (i = 0; i < f->num_servers; i++) {
@@ -294,8 +291,9 @@
     }
     memset(s_valid, 0, f->num_servers * sizeof(int));
 
+    grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
     c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
-                                 "/foo", "foo.test.google.fr",
+                                 grpc_slice_from_static_string("/foo"), &host,
                                  gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
     GPR_ASSERT(c);
     completed_client = 0;
@@ -322,8 +320,6 @@
         &rdata->trailing_metadata_recv;
     op->data.recv_status_on_client.status = &rdata->status;
     op->data.recv_status_on_client.status_details = &rdata->details;
-    op->data.recv_status_on_client.status_details_capacity =
-        &rdata->details_capacity;
     op->flags = 0;
     op->reserved = NULL;
     op++;
@@ -331,9 +327,10 @@
                grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL));
 
     s_idx = -1;
-    while ((ev = grpc_completion_queue_next(
-                f->cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(RETRY_TIMEOUT), NULL))
-               .type != GRPC_QUEUE_TIMEOUT) {
+    while (
+        (ev = grpc_completion_queue_next(
+             f->cq, grpc_timeout_milliseconds_to_deadline(RETRY_TIMEOUT), NULL))
+            .type != GRPC_QUEUE_TIMEOUT) {
       GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
       read_tag = ((int)(intptr_t)ev.tag);
       const grpc_connectivity_state conn_state =
@@ -366,7 +363,8 @@
       op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
       op->data.send_status_from_server.trailing_metadata_count = 0;
       op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-      op->data.send_status_from_server.status_details = "xyz";
+      grpc_slice status_details = grpc_slice_from_static_string("xyz");
+      op->data.send_status_from_server.status_details = &status_details;
       op->flags = 0;
       op->reserved = NULL;
       op++;
@@ -385,12 +383,12 @@
       }
       cq_verify(cqv);
 
-      gpr_log(GPR_DEBUG, "status=%d; %s", rdata->status, rdata->details);
       GPR_ASSERT(rdata->status == GRPC_STATUS_UNIMPLEMENTED);
-      GPR_ASSERT(0 == strcmp(rdata->details, "xyz"));
-      GPR_ASSERT(0 == strcmp(rdata->call_details[s_idx].method, "/foo"));
+      GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->details, "xyz"));
       GPR_ASSERT(0 ==
-                 strcmp(rdata->call_details[s_idx].host, "foo.test.google.fr"));
+                 grpc_slice_str_cmp(rdata->call_details[s_idx].method, "/foo"));
+      GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->call_details[s_idx].host,
+                                         "foo.test.google.fr"));
       GPR_ASSERT(was_cancelled == 1);
 
       grpc_call_destroy(f->server_calls[s_idx]);
@@ -409,9 +407,10 @@
       }
     }
 
-    GPR_ASSERT(grpc_completion_queue_next(
-                   f->cq, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(RETRY_TIMEOUT), NULL)
-                   .type == GRPC_QUEUE_TIMEOUT);
+    GPR_ASSERT(
+        grpc_completion_queue_next(
+            f->cq, grpc_timeout_milliseconds_to_deadline(RETRY_TIMEOUT), NULL)
+            .type == GRPC_QUEUE_TIMEOUT);
 
     grpc_metadata_array_destroy(&rdata->initial_metadata_recv);
     grpc_metadata_array_destroy(&rdata->trailing_metadata_recv);
@@ -423,7 +422,7 @@
     for (i = 0; i < f->num_servers; i++) {
       grpc_call_details_destroy(&rdata->call_details[i]);
     }
-    gpr_free(rdata->details);
+    grpc_slice_unref(rdata->details);
   }
 
   gpr_free(s_valid);
@@ -455,10 +454,12 @@
   op->flags = 0;
   op->reserved = NULL;
 
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
   for (i = 0; i < concurrent_calls; i++) {
-    calls[i] = grpc_channel_create_call(
-        client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo",
-        "foo.test.google.fr", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+    calls[i] =
+        grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
+                                 grpc_slice_from_static_string("/foo"), &host,
+                                 gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
     GPR_ASSERT(calls[i]);
     GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[i], ops,
                                                      (size_t)(op - ops), tag(1),
@@ -516,7 +517,7 @@
   grpc_channel *client;
   char *client_hostport;
   char *servers_hostports_str;
-  grpc_arg arg_array[2];
+  grpc_arg arg_array[3];
   grpc_channel_args args;
 
   servers_hostports_str = gpr_strjoin_sep((const char **)f->servers_hostports,
@@ -529,7 +530,10 @@
   arg_array[1].type = GRPC_ARG_STRING;
   arg_array[1].key = GRPC_ARG_LB_POLICY_NAME;
   arg_array[1].value.string = "ROUND_ROBIN";
-  args.num_args = 2;
+  arg_array[2].type = GRPC_ARG_INTEGER;
+  arg_array[2].key = GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS;
+  arg_array[2].value.integer = 0;
+  args.num_args = GPR_ARRAY_SIZE(arg_array);
   args.args = arg_array;
 
   client = grpc_insecure_channel_create(client_hostport, &args, NULL);
@@ -564,7 +568,7 @@
      READY is reached */
   while (state != GRPC_CHANNEL_READY) {
     grpc_channel_watch_connectivity_state(
-        client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f->cq, tag(99));
+        client, state, grpc_timeout_seconds_to_deadline(3), f->cq, tag(99));
     CQ_EXPECT_COMPLETION(cqv, tag(99), 1);
     cq_verify(cqv);
     state = grpc_channel_check_connectivity_state(client, 0);
diff --git a/test/core/client_channel/resolvers/BUILD b/test/core/client_channel/resolvers/BUILD
new file mode 100644
index 0000000..af37072
--- /dev/null
+++ b/test/core/client_channel/resolvers/BUILD
@@ -0,0 +1,51 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+cc_test(
+    name = "dns_resolver_connectivity_test",
+    srcs = ["dns_resolver_connectivity_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "dns_resolver_test",
+    srcs = ["dns_resolver_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "sockaddr_resolver_test",
+    srcs = ["sockaddr_resolver_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
index f0c6843..3e34011 100644
--- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
+++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
@@ -36,14 +36,17 @@
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 
+#include "src/core/ext/client_channel/resolver.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "test/core/util/test_config.h"
 
 static gpr_mu g_mu;
 static bool g_fail_resolution = true;
+static grpc_combiner *g_combiner;
 
 static grpc_error *my_resolve_address(const char *name, const char *addr,
                                       grpc_resolved_addresses **addrs) {
@@ -71,6 +74,7 @@
   grpc_resolver_args args;
   memset(&args, 0, sizeof(args));
   args.uri = uri;
+  args.combiner = g_combiner;
   grpc_resolver *resolver =
       grpc_resolver_factory_create_resolver(exec_ctx, factory, &args);
   grpc_resolver_factory_unref(factory);
@@ -86,7 +90,7 @@
 static bool wait_loop(int deadline_seconds, gpr_event *ev) {
   while (deadline_seconds) {
     gpr_log(GPR_DEBUG, "Test: waiting for %d more seconds", deadline_seconds);
-    if (gpr_event_wait(ev, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1))) return true;
+    if (gpr_event_wait(ev, grpc_timeout_seconds_to_deadline(1))) return true;
     deadline_seconds--;
 
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -96,11 +100,41 @@
   return false;
 }
 
+typedef struct next_args {
+  grpc_resolver *resolver;
+  grpc_channel_args **result;
+  grpc_closure *on_complete;
+} next_args;
+
+static void call_resolver_next_now_lock_taken(grpc_exec_ctx *exec_ctx,
+                                              void *arg,
+                                              grpc_error *error_unused) {
+  next_args *a = arg;
+  grpc_resolver_next_locked(exec_ctx, a->resolver, a->result, a->on_complete);
+  gpr_free(a);
+}
+
+static void call_resolver_next_after_locking(grpc_exec_ctx *exec_ctx,
+                                             grpc_resolver *resolver,
+                                             grpc_channel_args **result,
+                                             grpc_closure *on_complete) {
+  next_args *a = gpr_malloc(sizeof(*a));
+  a->resolver = resolver;
+  a->result = result;
+  a->on_complete = on_complete;
+  grpc_closure_sched(
+      exec_ctx,
+      grpc_closure_create(call_resolver_next_now_lock_taken, a,
+                          grpc_combiner_scheduler(resolver->combiner, false)),
+      GRPC_ERROR_NONE);
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
 
   grpc_init();
   gpr_mu_init(&g_mu);
+  g_combiner = grpc_combiner_create(NULL);
   grpc_blocking_resolve_address = my_resolve_address;
   grpc_channel_args *result = (grpc_channel_args *)1;
 
@@ -108,7 +142,7 @@
   grpc_resolver *resolver = create_resolver(&exec_ctx, "dns:test");
   gpr_event ev1;
   gpr_event_init(&ev1);
-  grpc_resolver_next(
+  call_resolver_next_after_locking(
       &exec_ctx, resolver, &result,
       grpc_closure_create(on_done, &ev1, grpc_schedule_on_exec_ctx));
   grpc_exec_ctx_flush(&exec_ctx);
@@ -117,7 +151,7 @@
 
   gpr_event ev2;
   gpr_event_init(&ev2);
-  grpc_resolver_next(
+  call_resolver_next_after_locking(
       &exec_ctx, resolver, &result,
       grpc_closure_create(on_done, &ev2, grpc_schedule_on_exec_ctx));
   grpc_exec_ctx_flush(&exec_ctx);
@@ -126,6 +160,7 @@
 
   grpc_channel_args_destroy(&exec_ctx, result);
   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test");
+  GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
   grpc_exec_ctx_finish(&exec_ctx);
 
   grpc_shutdown();
diff --git a/test/core/client_channel/resolvers/dns_resolver_test.c b/test/core/client_channel/resolvers/dns_resolver_test.c
index 5603a57..9dd5aed 100644
--- a/test/core/client_channel/resolvers/dns_resolver_test.c
+++ b/test/core/client_channel/resolvers/dns_resolver_test.c
@@ -36,8 +36,11 @@
 #include <grpc/support/log.h>
 
 #include "src/core/ext/client_channel/resolver_registry.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "test/core/util/test_config.h"
 
+static grpc_combiner *g_combiner;
+
 static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_uri *uri = grpc_uri_parse(string, 0);
@@ -48,6 +51,7 @@
   GPR_ASSERT(uri);
   memset(&args, 0, sizeof(args));
   args.uri = uri;
+  args.combiner = g_combiner;
   resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
   GPR_ASSERT(resolver != NULL);
   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
@@ -65,6 +69,7 @@
   GPR_ASSERT(uri);
   memset(&args, 0, sizeof(args));
   args.uri = uri;
+  args.combiner = g_combiner;
   resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
   GPR_ASSERT(resolver == NULL);
   grpc_uri_destroy(uri);
@@ -76,6 +81,8 @@
   grpc_test_init(argc, argv);
   grpc_init();
 
+  g_combiner = grpc_combiner_create(NULL);
+
   dns = grpc_resolver_factory_lookup("dns");
 
   test_succeeds(dns, "dns:10.2.1.1");
@@ -84,6 +91,11 @@
   test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
 
   grpc_resolver_factory_unref(dns);
+  {
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
+    grpc_exec_ctx_finish(&exec_ctx);
+  }
   grpc_shutdown();
 
   return 0;
diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.c b/test/core/client_channel/resolvers/sockaddr_resolver_test.c
index 10df785..68831ab 100644
--- a/test/core/client_channel/resolvers/sockaddr_resolver_test.c
+++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.c
@@ -39,9 +39,12 @@
 
 #include "src/core/ext/client_channel/resolver_registry.h"
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
 
 #include "test/core/util/test_config.h"
 
+static grpc_combiner *g_combiner;
+
 typedef struct on_resolution_arg {
   char *expected_server_name;
   grpc_channel_args *resolver_result;
@@ -62,6 +65,7 @@
   GPR_ASSERT(uri);
   memset(&args, 0, sizeof(args));
   args.uri = uri;
+  args.combiner = g_combiner;
   resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
   GPR_ASSERT(resolver != NULL);
 
@@ -71,8 +75,8 @@
   grpc_closure *on_resolution = grpc_closure_create(
       on_resolution_cb, &on_res_arg, grpc_schedule_on_exec_ctx);
 
-  grpc_resolver_next(&exec_ctx, resolver, &on_res_arg.resolver_result,
-                     on_resolution);
+  grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result,
+                            on_resolution);
   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_uri_destroy(uri);
@@ -88,6 +92,7 @@
   GPR_ASSERT(uri);
   memset(&args, 0, sizeof(args));
   args.uri = uri;
+  args.combiner = g_combiner;
   resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
   GPR_ASSERT(resolver == NULL);
   grpc_uri_destroy(uri);
@@ -99,6 +104,8 @@
   grpc_test_init(argc, argv);
   grpc_init();
 
+  g_combiner = grpc_combiner_create(NULL);
+
   ipv4 = grpc_resolver_factory_lookup("ipv4");
   ipv6 = grpc_resolver_factory_lookup("ipv6");
 
@@ -118,6 +125,12 @@
 
   grpc_resolver_factory_unref(ipv4);
   grpc_resolver_factory_unref(ipv6);
+
+  {
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
+    grpc_exec_ctx_finish(&exec_ctx);
+  }
   grpc_shutdown();
 
   return 0;
diff --git a/test/core/client_channel/set_initial_connect_string_test.c b/test/core/client_channel/set_initial_connect_string_test.c
index b78ba98..a0a3366 100644
--- a/test/core/client_channel/set_initial_connect_string_test.c
+++ b/test/core/client_channel/set_initial_connect_string_test.c
@@ -81,7 +81,9 @@
           state.incoming_buffer.length, strlen(magic_connect_string));
   if (state.incoming_buffer.length > strlen(magic_connect_string)) {
     gpr_atm_rel_store(&state.done_atm, 1);
-    grpc_endpoint_shutdown(exec_ctx, state.tcp);
+    grpc_endpoint_shutdown(
+        exec_ctx, state.tcp,
+        GRPC_ERROR_CREATE("Incoming buffer longer than magic_connect_string"));
     grpc_endpoint_destroy(exec_ctx, state.tcp);
   } else {
     grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer,
@@ -141,9 +143,11 @@
   } else {
     state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
   }
+  grpc_slice host = grpc_slice_from_static_string("localhost");
   state.call = grpc_channel_create_call(
-      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, "/Service/Method",
-      "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq,
+      grpc_slice_from_static_string("/Service/Method"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   memset(&state.op, 0, sizeof(state.op));
   state.op.op = GRPC_OP_SEND_INITIAL_METADATA;
   state.op.data.send_initial_metadata.count = 0;
@@ -207,8 +211,7 @@
   size_t magic_length = strlen(magic_connect_string);
   GPR_ASSERT(buffer->length >= magic_length);
   for (i = 0, j = 0; i < state.incoming_buffer.count && j < magic_length; i++) {
-    char *dump =
-        grpc_dump_slice(state.incoming_buffer.slices[i], GPR_DUMP_ASCII);
+    char *dump = grpc_slice_to_c_string(state.incoming_buffer.slices[i]);
     cmp_length = GPR_MIN(strlen(dump), magic_length - j);
     GPR_ASSERT(strncmp(dump, magic_connect_string + j, cmp_length) == 0);
     j += cmp_length;
diff --git a/test/core/compression/BUILD b/test/core/compression/BUILD
new file mode 100644
index 0000000..a243a72
--- /dev/null
+++ b/test/core/compression/BUILD
@@ -0,0 +1,64 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+cc_test(
+    name = "algorithm_test",
+    srcs = ["algorithm_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "compression_test",
+    srcs = ["compression_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "message_compress_test",
+    srcs = ["message_compress_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/compression/algorithm_test.c b/test/core/compression/algorithm_test.c
index ff17667..37397ce 100644
--- a/test/core/compression/algorithm_test.c
+++ b/test/core/compression/algorithm_test.c
@@ -40,6 +40,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "test/core/util/test_config.h"
 
@@ -51,32 +52,33 @@
   for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) {
     char *name;
     grpc_compression_algorithm parsed;
-    grpc_mdstr *mdstr;
-    grpc_mdelem *mdelem;
+    grpc_slice mdstr;
+    grpc_mdelem mdelem;
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     GPR_ASSERT(
         grpc_compression_algorithm_name((grpc_compression_algorithm)i, &name));
-    GPR_ASSERT(grpc_compression_algorithm_parse(name, strlen(name), &parsed));
+    GPR_ASSERT(grpc_compression_algorithm_parse(
+        grpc_slice_from_static_string(name), &parsed));
     GPR_ASSERT((int)parsed == i);
-    mdstr = grpc_mdstr_from_string(name);
-    GPR_ASSERT(mdstr == grpc_compression_algorithm_mdstr(parsed));
-    GPR_ASSERT(parsed == grpc_compression_algorithm_from_mdstr(mdstr));
+    mdstr = grpc_slice_from_copied_string(name);
+    GPR_ASSERT(grpc_slice_eq(mdstr, grpc_compression_algorithm_slice(parsed)));
+    GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr));
     mdelem = grpc_compression_encoding_mdelem(parsed);
-    GPR_ASSERT(mdelem->value == mdstr);
-    GPR_ASSERT(mdelem->key == GRPC_MDSTR_GRPC_ENCODING);
-    GRPC_MDSTR_UNREF(&exec_ctx, mdstr);
+    GPR_ASSERT(grpc_slice_eq(GRPC_MDVALUE(mdelem), mdstr));
+    GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_GRPC_ENCODING));
+    grpc_slice_unref_internal(&exec_ctx, mdstr);
     GRPC_MDELEM_UNREF(&exec_ctx, mdelem);
     grpc_exec_ctx_finish(&exec_ctx);
   }
 
   /* test failure */
-  GPR_ASSERT(NULL ==
-             grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT));
+  GPR_ASSERT(GRPC_MDISNULL(
+      grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT)));
 }
 
 static void test_algorithm_failure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_mdstr *mdstr;
+  grpc_slice mdstr;
 
   gpr_log(GPR_DEBUG, "test_algorithm_failure");
 
@@ -84,14 +86,16 @@
                                              NULL) == 0);
   GPR_ASSERT(grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT + 1,
                                              NULL) == 0);
-  mdstr = grpc_mdstr_from_string("this-is-an-invalid-algorithm");
-  GPR_ASSERT(grpc_compression_algorithm_from_mdstr(mdstr) ==
+  mdstr = grpc_slice_from_static_string("this-is-an-invalid-algorithm");
+  GPR_ASSERT(grpc_compression_algorithm_from_slice(mdstr) ==
              GRPC_COMPRESS_ALGORITHMS_COUNT);
-  GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT) ==
-             NULL);
-  GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT +
-                                              1) == NULL);
-  GRPC_MDSTR_UNREF(&exec_ctx, mdstr);
+  GPR_ASSERT(grpc_slice_eq(
+      grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT),
+      grpc_empty_slice()));
+  GPR_ASSERT(grpc_slice_eq(
+      grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT + 1),
+      grpc_empty_slice()));
+  grpc_slice_unref_internal(&exec_ctx, mdstr);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
diff --git a/test/core/compression/compression_test.c b/test/core/compression/compression_test.c
index 4c43746..7b2e56d 100644
--- a/test/core/compression/compression_test.c
+++ b/test/core/compression/compression_test.c
@@ -54,7 +54,7 @@
     const char *valid_name = valid_names[i];
     grpc_compression_algorithm algorithm;
     const int success = grpc_compression_algorithm_parse(
-        valid_name, strlen(valid_name), &algorithm);
+        grpc_slice_from_static_string(valid_name), &algorithm);
     GPR_ASSERT(success != 0);
     GPR_ASSERT(algorithm == valid_algorithms[i]);
   }
@@ -64,7 +64,7 @@
     grpc_compression_algorithm algorithm;
     int success;
     success = grpc_compression_algorithm_parse(
-        invalid_name, strlen(invalid_name), &algorithm);
+        grpc_slice_from_static_string(invalid_name), &algorithm);
     GPR_ASSERT(success == 0);
     /* the value of "algorithm" is undefined upon failure */
   }
diff --git a/test/core/compression/message_compress_test.c b/test/core/compression/message_compress_test.c
index 2432ca7..246a2b3 100644
--- a/test/core/compression/message_compress_test.c
+++ b/test/core/compression/message_compress_test.c
@@ -114,7 +114,7 @@
   }
 
   final = grpc_slice_merge(output.slices, output.count);
-  GPR_ASSERT(0 == grpc_slice_cmp(value, final));
+  GPR_ASSERT(grpc_slice_eq(value, final));
 
   grpc_slice_buffer_destroy(&input);
   grpc_slice_buffer_destroy(&compressed);
diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c
index d3a47ab..39a98e8 100644
--- a/test/core/end2end/bad_server_response_test.c
+++ b/test/core/end2end/bad_server_response_test.c
@@ -82,7 +82,9 @@
 #define HTTP1_DETAIL_MSG "Trying to connect an http1.x server"
 
 /* TODO(zyc) Check the content of incomming data instead of using this length */
-#define EXPECTED_INCOMING_DATA_LENGTH (size_t)310
+/* The 'bad' server will start sending responses after reading this amount of
+ * data from the client. */
+#define SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD (size_t)200
 
 struct rpc_state {
   char *target;
@@ -134,8 +136,10 @@
   }
 
   gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, expected %" PRIuPTR " bytes",
-          state.incoming_data_length, EXPECTED_INCOMING_DATA_LENGTH);
-  if (state.incoming_data_length > EXPECTED_INCOMING_DATA_LENGTH) {
+          state.incoming_data_length,
+          SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD);
+  if (state.incoming_data_length >=
+      SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD) {
     handle_write(exec_ctx);
   } else {
     grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer,
@@ -172,16 +176,17 @@
   grpc_status_code status;
   grpc_call_error error;
   cq_verifier *cqv;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   state.cq = grpc_completion_queue_create(NULL);
   cqv = cq_verifier_create(state.cq);
   gpr_join_host_port(&state.target, "127.0.0.1", target_port);
   state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
+  grpc_slice host = grpc_slice_from_static_string("localhost");
   state.call = grpc_channel_create_call(
-      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, "/Service/Method",
-      "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq,
+      grpc_slice_from_static_string("/Service/Method"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 
   grpc_metadata_array_init(&initial_metadata_recv);
   grpc_metadata_array_init(&trailing_metadata_recv);
@@ -206,7 +211,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -218,13 +222,13 @@
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  gpr_log(GPR_DEBUG, "Rpc status: %d, details: %s", status, details);
   GPR_ASSERT(status == expected_status);
-  GPR_ASSERT(NULL != strstr(details, expected_detail));
+  GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string(
+                                                 expected_detail)));
 
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
   cq_verifier_destroy(cqv);
 }
 
@@ -298,7 +302,8 @@
   gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
 
   /* clean up */
-  grpc_endpoint_shutdown(&exec_ctx, state.tcp);
+  grpc_endpoint_shutdown(&exec_ctx, state.tcp,
+                         GRPC_ERROR_CREATE("Test Shutdown"));
   grpc_endpoint_destroy(&exec_ctx, state.tcp);
   cleanup_rpc(&exec_ctx);
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/end2end/connection_refused_test.c b/test/core/end2end/connection_refused_test.c
index 4430804..16a3005 100644
--- a/test/core/end2end/connection_refused_test.c
+++ b/test/core/end2end/connection_refused_test.c
@@ -40,6 +40,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/service_config.h"
 
@@ -52,15 +53,14 @@
 static void run_test(bool wait_for_ready, bool use_service_config) {
   grpc_channel *chan;
   grpc_call *call;
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2);
   grpc_completion_queue *cq;
   cq_verifier *cqv;
   grpc_op ops[6];
   grpc_op *op;
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   gpr_log(GPR_INFO, "TEST: wait_for_ready=%d use_service_config=%d",
           wait_for_ready, use_service_config);
@@ -97,9 +97,10 @@
   gpr_join_host_port(&addr, "127.0.0.1", port);
   gpr_log(GPR_INFO, "server: %s", addr);
   chan = grpc_insecure_channel_create(addr, args, NULL);
-  call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/service/method", "nonexistant", deadline,
-                                  NULL);
+  grpc_slice host = grpc_slice_from_static_string("nonexistant");
+  call = grpc_channel_create_call(
+      chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/service/method"), &host, deadline, NULL);
 
   gpr_free(addr);
 
@@ -116,7 +117,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -142,7 +142,7 @@
   grpc_channel_destroy(chan);
   cq_verifier_destroy(cqv);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
   {
diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c
index 5737397..9b0106e 100644
--- a/test/core/end2end/cq_verifier.c
+++ b/test/core/end2end/cq_verifier.c
@@ -92,8 +92,8 @@
                         const char *value) {
   size_t i;
   for (i = 0; i < count; i++) {
-    if (0 == strcmp(key, md[i].key) && strlen(value) == md[i].value_length &&
-        0 == memcmp(md[i].value, value, md[i].value_length)) {
+    if (0 == grpc_slice_str_cmp(md[i].key, key) &&
+        0 == grpc_slice_str_cmp(md[i].value, value)) {
       return 1;
     }
   }
@@ -105,6 +105,22 @@
   return has_metadata(array->metadata, array->count, key, value);
 }
 
+static int has_metadata_slices(const grpc_metadata *md, size_t count,
+                               grpc_slice key, grpc_slice value) {
+  size_t i;
+  for (i = 0; i < count; i++) {
+    if (grpc_slice_eq(md[i].key, key) && grpc_slice_eq(md[i].value, value)) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int contains_metadata_slices(grpc_metadata_array *array, grpc_slice key,
+                             grpc_slice value) {
+  return has_metadata_slices(array->metadata, array->count, key, value);
+}
+
 static grpc_slice merge_slices(grpc_slice *slices, size_t nslices) {
   size_t i;
   size_t len = 0;
@@ -233,7 +249,7 @@
 }
 
 void cq_verify(cq_verifier *v) {
-  const gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
+  const gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10);
   while (v->first_expectation != NULL) {
     grpc_event ev = grpc_completion_queue_next(v->cq, deadline, NULL);
     if (ev.type == GRPC_QUEUE_TIMEOUT) {
diff --git a/test/core/end2end/cq_verifier.h b/test/core/end2end/cq_verifier.h
index b754de9..035aa27 100644
--- a/test/core/end2end/cq_verifier.h
+++ b/test/core/end2end/cq_verifier.h
@@ -71,5 +71,7 @@
 int byte_buffer_eq_string(grpc_byte_buffer *byte_buffer, const char *string);
 int contains_metadata(grpc_metadata_array *array, const char *key,
                       const char *value);
+int contains_metadata_slices(grpc_metadata_array *array, grpc_slice key,
+                             grpc_slice value);
 
 #endif /* GRPC_TEST_CORE_END2END_CQ_VERIFIER_H */
diff --git a/test/core/end2end/cq_verifier_native.c b/test/core/end2end/cq_verifier_native.c
index b1fcb4b..e0f1d79 100644
--- a/test/core/end2end/cq_verifier_native.c
+++ b/test/core/end2end/cq_verifier_native.c
@@ -67,7 +67,7 @@
 
 grpc_event cq_verifier_next_event(cq_verifier *v, int timeout_seconds) {
   const gpr_timespec deadline =
-      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(timeout_seconds);
+      grpc_timeout_seconds_to_deadline(timeout_seconds);
   return grpc_completion_queue_next(v->cq, deadline, NULL);
 }
 
diff --git a/test/core/end2end/data/ssl_test_data.h b/test/core/end2end/data/ssl_test_data.h
index 4a64af1..0b274e0 100644
--- a/test/core/end2end/data/ssl_test_data.h
+++ b/test/core/end2end/data/ssl_test_data.h
@@ -34,6 +34,10 @@
 #ifndef GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H
 #define GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern const char test_root_cert[];
 extern const char test_server1_cert[];
 extern const char test_server1_key[];
@@ -42,4 +46,8 @@
 extern const char test_signed_client_cert[];
 extern const char test_signed_client_key[];
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* GRPC_TEST_CORE_END2END_DATA_SSL_TEST_DATA_H */
diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c
index 59079f5..3623bd7 100644
--- a/test/core/end2end/dualstack_socket_test.c
+++ b/test/core/end2end/dualstack_socket_test.c
@@ -57,7 +57,7 @@
 static void *tag(intptr_t i) { return (void *)i; }
 
 static gpr_timespec ms_from_now(int ms) {
-  return GRPC_TIMEOUT_MILLIS_TO_DEADLINE(ms);
+  return grpc_timeout_milliseconds_to_deadline(ms);
 }
 
 static void drain_cq(grpc_completion_queue *cq) {
@@ -88,8 +88,7 @@
   grpc_metadata_array request_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   grpc_call_details call_details;
   char *peer;
@@ -135,7 +134,7 @@
     grpc_slice_split(uri_slice, ",", &uri_parts);
     hosts_with_port = gpr_malloc(sizeof(char *) * uri_parts.count);
     for (i = 0; i < uri_parts.count; i++) {
-      char *uri_part_str = grpc_dump_slice(uri_parts.slices[i], GPR_DUMP_ASCII);
+      char *uri_part_str = grpc_slice_to_c_string(uri_parts.slices[i]);
       gpr_asprintf(&hosts_with_port[i], "%s:%d", uri_part_str, port);
       gpr_free(uri_part_str);
     }
@@ -168,8 +167,10 @@
   }
 
   /* Send a trivial request. */
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
   c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                               "/foo", "foo.test.google.fr", deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   memset(ops, 0, sizeof(ops));
@@ -192,7 +193,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -216,7 +216,8 @@
     op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
     op->data.send_status_from_server.trailing_metadata_count = 0;
     op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-    op->data.send_status_from_server.status_details = "xyz";
+    grpc_slice status_details = grpc_slice_from_static_string("xyz");
+    op->data.send_status_from_server.status_details = &status_details;
     op->flags = 0;
     op++;
     op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
@@ -235,9 +236,10 @@
     gpr_free(peer);
 
     GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-    GPR_ASSERT(0 == strcmp(details, "xyz"));
-    GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
-    GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
+    GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+    GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+    GPR_ASSERT(0 ==
+               grpc_slice_str_cmp(call_details.host, "foo.test.google.fr"));
     GPR_ASSERT(was_cancelled == 1);
 
     grpc_call_destroy(s);
@@ -259,7 +261,7 @@
   /* Destroy server. */
   grpc_server_shutdown_and_notify(server, cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(server);
   grpc_completion_queue_shutdown(cq);
@@ -271,7 +273,7 @@
   grpc_metadata_array_destroy(&request_metadata_recv);
 
   grpc_call_details_destroy(&call_details);
-  gpr_free(details);
+  grpc_slice_unref(details);
   if (picked_port) {
     grpc_recycle_unused_port(port);
   }
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c
index b162bf2..b351bde 100644
--- a/test/core/end2end/end2end_nosec_tests.c
+++ b/test/core/end2end/end2end_nosec_tests.c
@@ -41,6 +41,8 @@
 
 #include <grpc/support/log.h>
 
+#include "test/core/util/debugger_macros.h"
+
 static bool g_pre_init_called = false;
 
 extern void authority_not_supported(grpc_end2end_test_config config);
@@ -87,6 +89,8 @@
 extern void idempotent_request_pre_init(void);
 extern void invoke_large_request(grpc_end2end_test_config config);
 extern void invoke_large_request_pre_init(void);
+extern void keepalive_timeout(grpc_end2end_test_config config);
+extern void keepalive_timeout_pre_init(void);
 extern void large_metadata(grpc_end2end_test_config config);
 extern void large_metadata_pre_init(void);
 extern void load_reporting_hook(grpc_end2end_test_config config);
@@ -143,6 +147,7 @@
 void grpc_end2end_tests_pre_init(void) {
   GPR_ASSERT(!g_pre_init_called);
   g_pre_init_called = true;
+  grpc_summon_debugger_macros();
   authority_not_supported_pre_init();
   bad_hostname_pre_init();
   binary_metadata_pre_init();
@@ -165,6 +170,7 @@
   hpack_size_pre_init();
   idempotent_request_pre_init();
   invoke_large_request_pre_init();
+  keepalive_timeout_pre_init();
   large_metadata_pre_init();
   load_reporting_hook_pre_init();
   max_concurrent_streams_pre_init();
@@ -222,6 +228,7 @@
     hpack_size(config);
     idempotent_request(config);
     invoke_large_request(config);
+    keepalive_timeout(config);
     large_metadata(config);
     load_reporting_hook(config);
     max_concurrent_streams(config);
@@ -340,6 +347,10 @@
       invoke_large_request(config);
       continue;
     }
+    if (0 == strcmp("keepalive_timeout", argv[i])) {
+      keepalive_timeout(config);
+      continue;
+    }
     if (0 == strcmp("large_metadata", argv[i])) {
       large_metadata(config);
       continue;
diff --git a/test/core/end2end/end2end_test_utils.c b/test/core/end2end/end2end_test_utils.c
index 46fb4ec..8783d84 100644
--- a/test/core/end2end/end2end_test_utils.c
+++ b/test/core/end2end/end2end_test_utils.c
@@ -39,13 +39,27 @@
 
 const char *get_host_override_string(const char *str,
                                      grpc_end2end_test_config config) {
-  return (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER ? str
-                                                                       : NULL);
+  if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) {
+    return str;
+  } else {
+    return NULL;
+  }
 }
 
-void validate_host_override_string(const char *pattern, const char *str,
+const grpc_slice *get_host_override_slice(const char *str,
+                                          grpc_end2end_test_config config) {
+  const char *r = get_host_override_string(str, config);
+  if (r != NULL) {
+    static grpc_slice ret;
+    ret = grpc_slice_from_static_string(r);
+    return &ret;
+  }
+  return NULL;
+}
+
+void validate_host_override_string(const char *pattern, grpc_slice str,
                                    grpc_end2end_test_config config) {
   if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) {
-    GPR_ASSERT(0 == strcmp(str, pattern));
+    GPR_ASSERT(0 == grpc_slice_str_cmp(str, pattern));
   }
 }
diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c
index 9bca0c8..199c09e 100644
--- a/test/core/end2end/end2end_tests.c
+++ b/test/core/end2end/end2end_tests.c
@@ -41,6 +41,8 @@
 
 #include <grpc/support/log.h>
 
+#include "test/core/util/debugger_macros.h"
+
 static bool g_pre_init_called = false;
 
 extern void authority_not_supported(grpc_end2end_test_config config);
@@ -89,6 +91,8 @@
 extern void idempotent_request_pre_init(void);
 extern void invoke_large_request(grpc_end2end_test_config config);
 extern void invoke_large_request_pre_init(void);
+extern void keepalive_timeout(grpc_end2end_test_config config);
+extern void keepalive_timeout_pre_init(void);
 extern void large_metadata(grpc_end2end_test_config config);
 extern void large_metadata_pre_init(void);
 extern void load_reporting_hook(grpc_end2end_test_config config);
@@ -145,6 +149,7 @@
 void grpc_end2end_tests_pre_init(void) {
   GPR_ASSERT(!g_pre_init_called);
   g_pre_init_called = true;
+  grpc_summon_debugger_macros();
   authority_not_supported_pre_init();
   bad_hostname_pre_init();
   binary_metadata_pre_init();
@@ -168,6 +173,7 @@
   hpack_size_pre_init();
   idempotent_request_pre_init();
   invoke_large_request_pre_init();
+  keepalive_timeout_pre_init();
   large_metadata_pre_init();
   load_reporting_hook_pre_init();
   max_concurrent_streams_pre_init();
@@ -226,6 +232,7 @@
     hpack_size(config);
     idempotent_request(config);
     invoke_large_request(config);
+    keepalive_timeout(config);
     large_metadata(config);
     load_reporting_hook(config);
     max_concurrent_streams(config);
@@ -348,6 +355,10 @@
       invoke_large_request(config);
       continue;
     }
+    if (0 == strcmp("keepalive_timeout", argv[i])) {
+      keepalive_timeout(config);
+      continue;
+    }
     if (0 == strcmp("large_metadata", argv[i])) {
       large_metadata(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h
index f25e90b..cb0afd9 100644
--- a/test/core/end2end/end2end_tests.h
+++ b/test/core/end2end/end2end_tests.h
@@ -72,8 +72,12 @@
 
 const char *get_host_override_string(const char *str,
                                      grpc_end2end_test_config config);
+/* Returns a pointer to a statically allocated slice: future invocations
+   overwrite past invocations, not threadsafe, etc... */
+const grpc_slice *get_host_override_slice(const char *str,
+                                          grpc_end2end_test_config config);
 
-void validate_host_override_string(const char *pattern, const char *str,
+void validate_host_override_string(const char *pattern, grpc_slice str,
                                    grpc_end2end_test_config config);
 
 #endif /* GRPC_TEST_CORE_END2END_END2END_TESTS_H */
diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c
index 966642f..8a37531 100644
--- a/test/core/end2end/fake_resolver.c
+++ b/test/core/end2end/fake_resolver.c
@@ -154,27 +154,54 @@
       grpc_uri_get_query_arg(args->uri, "lb_enabled");
   const bool lb_enabled =
       lb_enabled_qpart != NULL && strcmp("0", lb_enabled_qpart) != 0;
+
+  // Get the balancer's names.
+  const char* balancer_names =
+      grpc_uri_get_query_arg(args->uri, "balancer_names");
+  grpc_slice_buffer balancer_names_parts;
+  grpc_slice_buffer_init(&balancer_names_parts);
+  if (balancer_names != NULL) {
+    const grpc_slice balancer_names_slice =
+        grpc_slice_from_copied_string(balancer_names);
+    grpc_slice_split(balancer_names_slice, ",", &balancer_names_parts);
+    grpc_slice_unref(balancer_names_slice);
+  }
+
   // Construct addresses.
   grpc_slice path_slice =
       grpc_slice_new(args->uri->path, strlen(args->uri->path), do_nothing);
   grpc_slice_buffer path_parts;
   grpc_slice_buffer_init(&path_parts);
   grpc_slice_split(path_slice, ",", &path_parts);
+  if (balancer_names_parts.count > 0 &&
+      path_parts.count != balancer_names_parts.count) {
+    gpr_log(GPR_ERROR,
+            "Balancer names present but mismatched with number of addresses: "
+            "%lu balancer names != %lu addresses",
+            (unsigned long)balancer_names_parts.count,
+            (unsigned long)path_parts.count);
+    return NULL;
+  }
   grpc_lb_addresses* addresses =
       grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */);
   bool errors_found = false;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     grpc_uri ith_uri = *args->uri;
-    char* part_str = grpc_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
+    char* part_str = grpc_slice_to_c_string(path_parts.slices[i]);
     ith_uri.path = part_str;
     if (!parse_ipv4(&ith_uri, &addresses->addresses[i].address)) {
       errors_found = true;
     }
     gpr_free(part_str);
-    addresses->addresses[i].is_balancer = lb_enabled;
     if (errors_found) break;
+    addresses->addresses[i].is_balancer = lb_enabled;
+    addresses->addresses[i].balancer_name =
+        balancer_names_parts.count > 0
+            ? grpc_dump_slice(balancer_names_parts.slices[i], GPR_DUMP_ASCII)
+            : NULL;
   }
   grpc_slice_buffer_destroy_internal(exec_ctx, &path_parts);
+  grpc_slice_buffer_destroy_internal(exec_ctx, &balancer_names_parts);
   grpc_slice_unref(path_slice);
   if (errors_found) {
     grpc_lb_addresses_destroy(exec_ctx, addresses);
@@ -186,7 +213,7 @@
   r->channel_args = grpc_channel_args_copy(args->args);
   r->addresses = addresses;
   gpr_mu_init(&r->mu);
-  grpc_resolver_init(&r->base, &fake_resolver_vtable);
+  grpc_resolver_init(&r->base, &fake_resolver_vtable, args->combiner);
   return &r->base;
 }
 
diff --git a/test/core/end2end/fixtures/h2_full+trace.c b/test/core/end2end/fixtures/h2_full+trace.c
index 11a102a..0131637 100644
--- a/test/core/end2end/fixtures/h2_full+trace.c
+++ b/test/core/end2end/fixtures/h2_full+trace.c
@@ -117,9 +117,9 @@
   gpr_setenv("GRPC_TRACE", "doesnt-exist,http,all");
 
 #ifdef GRPC_POSIX_SOCKET
-  g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10.0 : 1.0;
+  g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10 : 1;
 #else
-  g_fixture_slowdown_factor = 10.0;
+  g_fixture_slowdown_factor = 10;
 #endif
 
   grpc_test_init(argc, argv);
diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c
index 83f759c..3351652 100644
--- a/test/core/end2end/fixtures/h2_oauth2.c
+++ b/test/core/end2end/fixtures/h2_oauth2.c
@@ -59,8 +59,8 @@
                                           const char *value) {
   size_t i;
   for (i = 0; i < md_count; i++) {
-    if (strcmp(key, md[i].key) == 0 && strlen(value) == md[i].value_length &&
-        memcmp(md[i].value, value, md[i].value_length) == 0) {
+    if (grpc_slice_str_cmp(md[i].key, key) == 0 &&
+        grpc_slice_str_cmp(md[i].value, value) == 0) {
       return &md[i];
     }
   }
@@ -74,7 +74,7 @@
                                    grpc_process_auth_metadata_done_cb cb,
                                    void *user_data) {
   const grpc_metadata *oauth2 =
-      find_metadata(md, md_count, "Authorization", oauth2_md);
+      find_metadata(md, md_count, "authorization", oauth2_md);
   test_processor_state *s;
 
   GPR_ASSERT(state != NULL);
@@ -93,7 +93,7 @@
                                    grpc_process_auth_metadata_done_cb cb,
                                    void *user_data) {
   const grpc_metadata *oauth2 =
-      find_metadata(md, md_count, "Authorization", oauth2_md);
+      find_metadata(md, md_count, "authorization", oauth2_md);
   test_processor_state *s;
   GPR_ASSERT(state != NULL);
   s = (test_processor_state *)state;
@@ -154,7 +154,7 @@
   grpc_channel_credentials *ssl_creds =
       grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
   grpc_call_credentials *oauth2_creds =
-      grpc_md_only_test_credentials_create("Authorization", oauth2_md, 1);
+      grpc_md_only_test_credentials_create("authorization", oauth2_md, 1);
   grpc_channel_credentials *ssl_oauth2_creds =
       grpc_composite_channel_credentials_create(ssl_creds, oauth2_creds, NULL);
   grpc_arg ssl_name_override = {GRPC_ARG_STRING,
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c
index 726ed87..edf42a4 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.c
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.c
@@ -154,9 +154,9 @@
      code paths in trace.c to be taken */
   gpr_setenv("GRPC_TRACE", "doesnt-exist,http,all");
 #ifdef GRPC_POSIX_SOCKET
-  g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10.0 : 1.0;
+  g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10 : 1;
 #else
-  g_fixture_slowdown_factor = 10.0;
+  g_fixture_slowdown_factor = 10;
 #endif
 
   grpc_test_init(argc, argv);
diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c
index 11af7be..6f9cf8f 100644
--- a/test/core/end2end/fixtures/h2_sockpair_1byte.c
+++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c
@@ -144,7 +144,7 @@
 int main(int argc, char **argv) {
   size_t i;
 
-  g_fixture_slowdown_factor = 2.0;
+  g_fixture_slowdown_factor = 2;
 
   grpc_test_init(argc, argv);
   grpc_end2end_tests_pre_init();
diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/fixtures/h2_ssl_cert.c
index ae49cc8..f62331e 100644
--- a/test/core/end2end/fixtures/h2_ssl_cert.c
+++ b/test/core/end2end/fixtures/h2_ssl_cert.c
@@ -275,7 +275,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -291,7 +291,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -321,9 +321,10 @@
   grpc_op *op;
   grpc_call_error error;
 
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr:1234");
   c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "foo.test.google.fr:1234", deadline,
-                               NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   memset(ops, 0, sizeof(ops));
diff --git a/test/core/end2end/fixtures/http_proxy.c b/test/core/end2end/fixtures/http_proxy.c
index b62082c..9ccb126 100644
--- a/test/core/end2end/fixtures/http_proxy.c
+++ b/test/core/end2end/fixtures/http_proxy.c
@@ -110,7 +110,7 @@
     grpc_endpoint_destroy(exec_ctx, conn->client_endpoint);
     if (conn->server_endpoint != NULL)
       grpc_endpoint_destroy(exec_ctx, conn->server_endpoint);
-    grpc_pollset_set_destroy(conn->pollset_set);
+    grpc_pollset_set_destroy(exec_ctx, conn->pollset_set);
     grpc_slice_buffer_destroy_internal(exec_ctx, &conn->client_read_buffer);
     grpc_slice_buffer_destroy_internal(exec_ctx,
                                        &conn->client_deferred_write_buffer);
@@ -132,10 +132,13 @@
                                     const char* prefix, grpc_error* error) {
   const char* msg = grpc_error_string(error);
   gpr_log(GPR_INFO, "%s: %s", prefix, msg);
-  grpc_error_free_string(msg);
-  grpc_endpoint_shutdown(exec_ctx, conn->client_endpoint);
-  if (conn->server_endpoint != NULL)
-    grpc_endpoint_shutdown(exec_ctx, conn->server_endpoint);
+
+  grpc_endpoint_shutdown(exec_ctx, conn->client_endpoint,
+                         GRPC_ERROR_REF(error));
+  if (conn->server_endpoint != NULL) {
+    grpc_endpoint_shutdown(exec_ctx, conn->server_endpoint,
+                           GRPC_ERROR_REF(error));
+  }
   proxy_connection_unref(exec_ctx, conn);
 }
 
@@ -451,7 +454,7 @@
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   GPR_ASSERT(port == proxy_port);
   // Start server.
-  proxy->pollset = gpr_malloc(grpc_pollset_size());
+  proxy->pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(proxy->pollset, &proxy->mu);
   grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, on_accept,
                         proxy);
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index 70d8da4..cee053e 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -80,8 +80,7 @@
 
   grpc_metadata_array p2s_trailing_metadata;
   grpc_status_code p2s_status;
-  char *p2s_status_details;
-  size_t p2s_status_details_capacity;
+  grpc_slice p2s_status_details;
 
   int c2p_server_cancelled;
 } proxy_call;
@@ -112,6 +111,7 @@
   grpc_server_register_completion_queue(proxy->server, proxy->cq, NULL);
   grpc_server_start(proxy->server);
 
+  grpc_call_details_init(&proxy->new_call_details);
   gpr_thd_options_set_joinable(&opt);
   GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt));
 
@@ -153,7 +153,7 @@
     grpc_metadata_array_destroy(&pc->c2p_initial_metadata);
     grpc_metadata_array_destroy(&pc->p2s_initial_metadata);
     grpc_metadata_array_destroy(&pc->p2s_trailing_metadata);
-    gpr_free(pc->p2s_status_details);
+    grpc_slice_unref(pc->p2s_status_details);
     gpr_free(pc);
   }
 }
@@ -309,7 +309,7 @@
     op.data.send_status_from_server.trailing_metadata =
         pc->p2s_trailing_metadata.metadata;
     op.data.send_status_from_server.status = pc->p2s_status;
-    op.data.send_status_from_server.status_details = pc->p2s_status_details;
+    op.data.send_status_from_server.status_details = &pc->p2s_status_details;
     refpc(pc, "on_c2p_sent_status");
     err = grpc_call_start_batch(pc->c2p, &op, 1,
                                 new_closure(on_c2p_sent_status, pc), NULL);
@@ -339,7 +339,7 @@
     pc->c2p = proxy->new_call;
     pc->p2s = grpc_channel_create_call(
         proxy->client, pc->c2p, GRPC_PROPAGATE_DEFAULTS, proxy->cq,
-        proxy->new_call_details.method, proxy->new_call_details.host,
+        proxy->new_call_details.method, &proxy->new_call_details.host,
         proxy->new_call_details.deadline, NULL);
     gpr_ref_init(&pc->refs, 1);
 
@@ -385,8 +385,6 @@
         &pc->p2s_trailing_metadata;
     op.data.recv_status_on_client.status = &pc->p2s_status;
     op.data.recv_status_on_client.status_details = &pc->p2s_status_details;
-    op.data.recv_status_on_client.status_details_capacity =
-        &pc->p2s_status_details_capacity;
     refpc(pc, "on_p2s_status");
     err = grpc_call_start_batch(pc->p2s, &op, 1, new_closure(on_p2s_status, pc),
                                 NULL);
@@ -402,6 +400,9 @@
 
     request_call(proxy);
 
+    grpc_call_details_destroy(&proxy->new_call_details);
+    grpc_call_details_init(&proxy->new_call_details);
+
     unrefpc(pc, "init");
   } else {
     GPR_ASSERT(proxy->new_call == NULL);
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index 690c1a4..0de8b94 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -44,6 +44,7 @@
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/tcp_client.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/transport/metadata.h"
 #include "test/core/end2end/data/ssl_test_data.h"
@@ -90,7 +91,7 @@
 
 static void end(input_stream *inp) { inp->cur = inp->end; }
 
-static char *read_string(input_stream *inp) {
+static char *read_string(input_stream *inp, bool *special) {
   char *str = NULL;
   size_t cap = 0;
   size_t sz = 0;
@@ -102,18 +103,56 @@
     }
     c = (char)next_byte(inp);
     str[sz++] = c;
-  } while (c != 0);
+  } while (c != 0 && c != 1);
+  if (special != NULL) {
+    *special = (c == 1);
+  }
+  if (c == 1) {
+    str[sz - 1] = 0;
+  }
   return str;
 }
 
-static void read_buffer(input_stream *inp, char **buffer, size_t *length) {
+static void read_buffer(input_stream *inp, char **buffer, size_t *length,
+                        bool *special) {
   *length = next_byte(inp);
+  if (*length == 255) {
+    if (special != NULL) *special = true;
+    *length = next_byte(inp);
+  } else {
+    if (special != NULL) *special = false;
+  }
   *buffer = gpr_malloc(*length);
   for (size_t i = 0; i < *length; i++) {
     (*buffer)[i] = (char)next_byte(inp);
   }
 }
 
+static grpc_slice maybe_intern(grpc_slice s, bool intern) {
+  grpc_slice r = intern ? grpc_slice_intern(s) : grpc_slice_ref(s);
+  grpc_slice_unref(s);
+  return r;
+}
+
+static grpc_slice read_string_like_slice(input_stream *inp) {
+  bool special;
+  char *s = read_string(inp, &special);
+  grpc_slice r = maybe_intern(grpc_slice_from_copied_string(s), special);
+  gpr_free(s);
+  return r;
+}
+
+static grpc_slice read_buffer_like_slice(input_stream *inp) {
+  char *buffer;
+  size_t length;
+  bool special;
+  read_buffer(inp, &buffer, &length, &special);
+  grpc_slice r =
+      maybe_intern(grpc_slice_from_copied_buffer(buffer, length), special);
+  gpr_free(buffer);
+  return r;
+}
+
 static uint32_t read_uint22(input_stream *inp) {
   uint8_t b = next_byte(inp);
   uint32_t x = b & 0x7f;
@@ -170,12 +209,12 @@
     switch (next_byte(inp)) {
       case 1:
         args[i].type = GRPC_ARG_STRING;
-        args[i].key = read_string(inp);
-        args[i].value.string = read_string(inp);
+        args[i].key = read_string(inp, NULL);
+        args[i].value.string = read_string(inp, NULL);
         break;
       case 2:
         args[i].type = GRPC_ARG_INTEGER;
-        args[i].key = read_string(inp);
+        args[i].key = read_string(inp, NULL);
         args[i].value.integer = read_int(inp);
         break;
       case 3:
@@ -217,7 +256,7 @@
                                       size_t num_builtins) {
   uint8_t b = next_byte(inp);
   if (b == 0) return NULL;
-  if (b == 1) return ctx->release[ctx->num_release++] = read_string(inp);
+  if (b == 1) return ctx->release[ctx->num_release++] = read_string(inp, NULL);
   if (b >= num_builtins + 1) {
     end(inp);
     return NULL;
@@ -403,7 +442,7 @@
   } else if (g_server != NULL) {
     grpc_endpoint *client;
     grpc_endpoint *server;
-    grpc_passthru_endpoint_create(&client, &server, g_resource_quota);
+    grpc_passthru_endpoint_create(&client, &server, g_resource_quota, NULL);
     *fc->ep = client;
 
     grpc_transport *transport =
@@ -508,8 +547,7 @@
   grpc_status_code status;
   grpc_metadata_array recv_initial_metadata;
   grpc_metadata_array recv_trailing_metadata;
-  char *recv_status_details;
-  size_t recv_status_details_capacity;
+  grpc_slice recv_status_details;
   int cancelled;
   int pending_ops;
   grpc_call_details call_details;
@@ -523,6 +561,11 @@
   size_t cap_to_free;
   void **to_free;
 
+  // array of slices to unref
+  size_t num_slices_to_unref;
+  size_t cap_slices_to_unref;
+  grpc_slice **slices_to_unref;
+
   struct call_state *next;
   struct call_state *prev;
 } call_state;
@@ -558,13 +601,18 @@
   call->next->prev = call->prev;
   grpc_metadata_array_destroy(&call->recv_initial_metadata);
   grpc_metadata_array_destroy(&call->recv_trailing_metadata);
-  gpr_free(call->recv_status_details);
+  grpc_slice_unref(call->recv_status_details);
   grpc_call_details_destroy(&call->call_details);
 
+  for (size_t i = 0; i < call->num_slices_to_unref; i++) {
+    grpc_slice_unref(*call->slices_to_unref[i]);
+    gpr_free(call->slices_to_unref[i]);
+  }
   for (size_t i = 0; i < call->num_to_free; i++) {
     gpr_free(call->to_free[i]);
   }
   gpr_free(call->to_free);
+  gpr_free(call->slices_to_unref);
 
   gpr_free(call);
 
@@ -580,6 +628,19 @@
   call->to_free[call->num_to_free++] = p;
 }
 
+static grpc_slice *add_slice_to_unref(call_state *call, grpc_slice s) {
+  if (call->num_slices_to_unref == call->cap_slices_to_unref) {
+    call->cap_slices_to_unref = GPR_MAX(8, 2 * call->cap_slices_to_unref);
+    call->slices_to_unref =
+        gpr_realloc(call->slices_to_unref,
+                    sizeof(*call->slices_to_unref) * call->cap_slices_to_unref);
+  }
+  call->slices_to_unref[call->num_slices_to_unref] =
+      gpr_malloc(sizeof(grpc_slice));
+  *call->slices_to_unref[call->num_slices_to_unref++] = s;
+  return call->slices_to_unref[call->num_slices_to_unref - 1];
+}
+
 static void read_metadata(input_stream *inp, size_t *count,
                           grpc_metadata **metadata, call_state *cs) {
   *count = next_byte(inp);
@@ -587,12 +648,11 @@
     *metadata = gpr_malloc(*count * sizeof(**metadata));
     memset(*metadata, 0, *count * sizeof(**metadata));
     for (size_t i = 0; i < *count; i++) {
-      (*metadata)[i].key = read_string(inp);
-      read_buffer(inp, (char **)&(*metadata)[i].value,
-                  &(*metadata)[i].value_length);
+      (*metadata)[i].key = read_string_like_slice(inp);
+      (*metadata)[i].value = read_buffer_like_slice(inp);
       (*metadata)[i].flags = read_uint32(inp);
-      add_to_free(cs, (void *)(*metadata)[i].key);
-      add_to_free(cs, (void *)(*metadata)[i].value);
+      add_slice_to_unref(cs, (*metadata)[i].key);
+      add_slice_to_unref(cs, (*metadata)[i].value);
     }
   } else {
     *metadata = gpr_malloc(1);
@@ -656,7 +716,7 @@
 }
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   if (squelch) gpr_set_log_function(dont_log);
   input_stream inp = {data, data + size};
   grpc_resolve_address = my_resolve_address;
@@ -742,7 +802,7 @@
       // create an insecure channel
       case 2: {
         if (g_channel == NULL) {
-          char *target = read_string(&inp);
+          char *target = read_string(&inp, NULL);
           char *target_uri;
           gpr_asprintf(&target_uri, "dns:%s", target);
           grpc_channel_args *args = read_args(&inp);
@@ -871,8 +931,8 @@
           parent_call = g_active_call->call;
         }
         uint32_t propagation_mask = read_uint32(&inp);
-        char *method = read_string(&inp);
-        char *host = read_string(&inp);
+        grpc_slice method = read_string_like_slice(&inp);
+        grpc_slice host = read_string_like_slice(&inp);
         gpr_timespec deadline =
             gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                          gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
@@ -881,12 +941,12 @@
           call_state *cs = new_call(g_active_call, CLIENT);
           cs->call =
               grpc_channel_create_call(g_channel, parent_call, propagation_mask,
-                                       cq, method, host, deadline, NULL);
+                                       cq, method, &host, deadline, NULL);
         } else {
           end(&inp);
         }
-        gpr_free(method);
-        gpr_free(host);
+        grpc_slice_unref(method);
+        grpc_slice_unref(host);
         break;
       }
       // switch the 'current' call
@@ -951,7 +1011,8 @@
                   g_active_call);
               op->data.send_status_from_server.status = next_byte(&inp);
               op->data.send_status_from_server.status_details =
-                  read_string(&inp);
+                  add_slice_to_unref(g_active_call,
+                                     read_buffer_like_slice(&inp));
               break;
             case GRPC_OP_RECV_INITIAL_METADATA:
               op->op = GRPC_OP_RECV_INITIAL_METADATA;
@@ -971,8 +1032,6 @@
                   &g_active_call->recv_trailing_metadata;
               op->data.recv_status_on_client.status_details =
                   &g_active_call->recv_status_details;
-              op->data.recv_status_on_client.status_details_capacity =
-                  &g_active_call->recv_status_details_capacity;
               break;
             case GRPC_OP_RECV_CLOSE_ON_SERVER:
               op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
@@ -1000,22 +1059,6 @@
           grpc_byte_buffer_destroy(g_active_call->send_message);
           g_active_call->send_message = NULL;
         }
-        for (i = 0; i < num_ops; i++) {
-          op = &ops[i];
-          switch (op->op) {
-            case GRPC_OP_SEND_STATUS_FROM_SERVER:
-              gpr_free((void *)op->data.send_status_from_server.status_details);
-              break;
-            case GRPC_OP_SEND_MESSAGE:
-            case GRPC_OP_SEND_INITIAL_METADATA:
-            case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
-            case GRPC_OP_RECV_INITIAL_METADATA:
-            case GRPC_OP_RECV_MESSAGE:
-            case GRPC_OP_RECV_STATUS_ON_CLIENT:
-            case GRPC_OP_RECV_CLOSE_ON_SERVER:
-              break;
-          }
-        }
         gpr_free(ops);
 
         break;
@@ -1060,14 +1103,14 @@
       }
       // enable a tracer
       case 17: {
-        char *tracer = read_string(&inp);
+        char *tracer = read_string(&inp, NULL);
         grpc_tracer_set_enabled(tracer, 1);
         gpr_free(tracer);
         break;
       }
       // disable a tracer
       case 18: {
-        char *tracer = read_string(&inp);
+        char *tracer = read_string(&inp, NULL);
         grpc_tracer_set_enabled(tracer, 0);
         gpr_free(tracer);
         break;
@@ -1109,7 +1152,7 @@
       // create a secure channel
       case 22: {
         if (g_channel == NULL) {
-          char *target = read_string(&inp);
+          char *target = read_string(&inp, NULL);
           char *target_uri;
           gpr_asprintf(&target_uri, "dns:%s", target);
           grpc_channel_args *args = read_args(&inp);
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/008d276f01f9371a5956cccf2eeeadb790728a84 b/test/core/end2end/fuzzers/api_fuzzer_corpus/008d276f01f9371a5956cccf2eeeadb790728a84
new file mode 100644
index 0000000..88f358c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/008d276f01f9371a5956cccf2eeeadb790728a84
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/00ba96baafa4595f2d41c2fcf0a27f4e9be5c44d b/test/core/end2end/fuzzers/api_fuzzer_corpus/00ba96baafa4595f2d41c2fcf0a27f4e9be5c44d
new file mode 100644
index 0000000..6945952
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/00ba96baafa4595f2d41c2fcf0a27f4e9be5c44d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0163bae995fe67a902eabf9f2644726d4767184c b/test/core/end2end/fuzzers/api_fuzzer_corpus/0163bae995fe67a902eabf9f2644726d4767184c
new file mode 100644
index 0000000..b0583e0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0163bae995fe67a902eabf9f2644726d4767184c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0242a9f4d4fafc96ee9ed762b610e3c68d6efdec b/test/core/end2end/fuzzers/api_fuzzer_corpus/0242a9f4d4fafc96ee9ed762b610e3c68d6efdec
new file mode 100644
index 0000000..392ad08
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0242a9f4d4fafc96ee9ed762b610e3c68d6efdec
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/039c25bc070936901fc95f63ce9cc3058158fb6d b/test/core/end2end/fuzzers/api_fuzzer_corpus/039c25bc070936901fc95f63ce9cc3058158fb6d
new file mode 100644
index 0000000..fd96a32
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/039c25bc070936901fc95f63ce9cc3058158fb6d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/03eb66a763e065772bbb09e9a55baf081814ff25 b/test/core/end2end/fuzzers/api_fuzzer_corpus/03eb66a763e065772bbb09e9a55baf081814ff25
new file mode 100644
index 0000000..c54a6b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/03eb66a763e065772bbb09e9a55baf081814ff25
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/053b47093c2145d00b8d53ea58b80afcc876109b b/test/core/end2end/fuzzers/api_fuzzer_corpus/053b47093c2145d00b8d53ea58b80afcc876109b
new file mode 100644
index 0000000..e08913c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/053b47093c2145d00b8d53ea58b80afcc876109b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/06a298ad14533924c9fcb2df0d462c44a206f64b b/test/core/end2end/fuzzers/api_fuzzer_corpus/06a298ad14533924c9fcb2df0d462c44a206f64b
new file mode 100644
index 0000000..cf961eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/06a298ad14533924c9fcb2df0d462c44a206f64b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/06d20c59bcbeb0deff39619455a713691191bccd b/test/core/end2end/fuzzers/api_fuzzer_corpus/06d20c59bcbeb0deff39619455a713691191bccd
new file mode 100644
index 0000000..87426c9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/06d20c59bcbeb0deff39619455a713691191bccd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/070aca38b5cd06626dfc98126ef1225595800427 b/test/core/end2end/fuzzers/api_fuzzer_corpus/070aca38b5cd06626dfc98126ef1225595800427
new file mode 100644
index 0000000..0be853b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/070aca38b5cd06626dfc98126ef1225595800427
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/07867ad24a27ff8675dc36a1d8da833f9ee9434b b/test/core/end2end/fuzzers/api_fuzzer_corpus/07867ad24a27ff8675dc36a1d8da833f9ee9434b
new file mode 100644
index 0000000..06986fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/07867ad24a27ff8675dc36a1d8da833f9ee9434b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/08398518b9b4e98d4625dfb063ab0b6d9399a239 b/test/core/end2end/fuzzers/api_fuzzer_corpus/08398518b9b4e98d4625dfb063ab0b6d9399a239
new file mode 100644
index 0000000..fc57193
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/08398518b9b4e98d4625dfb063ab0b6d9399a239
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0914e4f6ee18c9d15b8df1858a7745b86d875970 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0914e4f6ee18c9d15b8df1858a7745b86d875970
new file mode 100644
index 0000000..489dead
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0914e4f6ee18c9d15b8df1858a7745b86d875970
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/091f02cc858a89253748b7d1051b8728d0e34015 b/test/core/end2end/fuzzers/api_fuzzer_corpus/091f02cc858a89253748b7d1051b8728d0e34015
new file mode 100644
index 0000000..4435741
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/091f02cc858a89253748b7d1051b8728d0e34015
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/095e3fa32a271ef9326d4dcd59fbd003977fdcfa b/test/core/end2end/fuzzers/api_fuzzer_corpus/095e3fa32a271ef9326d4dcd59fbd003977fdcfa
new file mode 100644
index 0000000..d9b1ae3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/095e3fa32a271ef9326d4dcd59fbd003977fdcfa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/096f9413b1bf712e092cf8bd70754014d6242f12 b/test/core/end2end/fuzzers/api_fuzzer_corpus/096f9413b1bf712e092cf8bd70754014d6242f12
new file mode 100644
index 0000000..c04f03c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/096f9413b1bf712e092cf8bd70754014d6242f12
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/097f758de0f31691fac6637bf8ac5ac946d5b079 b/test/core/end2end/fuzzers/api_fuzzer_corpus/097f758de0f31691fac6637bf8ac5ac946d5b079
new file mode 100644
index 0000000..17554b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/097f758de0f31691fac6637bf8ac5ac946d5b079
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/099cc7faaaa2620df22c9bcd6e6d49730e4788b3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/099cc7faaaa2620df22c9bcd6e6d49730e4788b3
new file mode 100644
index 0000000..f16a04a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/099cc7faaaa2620df22c9bcd6e6d49730e4788b3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0a3f1f614446ded112775bbbc5c61513ad78e12e b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a3f1f614446ded112775bbbc5c61513ad78e12e
new file mode 100644
index 0000000..c8d28f8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a3f1f614446ded112775bbbc5c61513ad78e12e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0a4b84c2a50ba66f06c99e945912972cdcfc96be b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a4b84c2a50ba66f06c99e945912972cdcfc96be
new file mode 100644
index 0000000..d0f43e9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a4b84c2a50ba66f06c99e945912972cdcfc96be
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0a85889229b729883f4c0420d1a13d9f0a2ca7c2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a85889229b729883f4c0420d1a13d9f0a2ca7c2
new file mode 100644
index 0000000..dd537e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0a85889229b729883f4c0420d1a13d9f0a2ca7c2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0ab436006cb2ecd8ecb2400fed982886e4589360 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0ab436006cb2ecd8ecb2400fed982886e4589360
new file mode 100644
index 0000000..f6e83c8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0ab436006cb2ecd8ecb2400fed982886e4589360
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0c26c7da58087406c491efb8f8f721eb934e6a5a b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c26c7da58087406c491efb8f8f721eb934e6a5a
new file mode 100644
index 0000000..e6a2e76
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0c26c7da58087406c491efb8f8f721eb934e6a5a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0cd9696699bd190463ecef91968624601b64cd8b b/test/core/end2end/fuzzers/api_fuzzer_corpus/0cd9696699bd190463ecef91968624601b64cd8b
new file mode 100644
index 0000000..92125ef
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0cd9696699bd190463ecef91968624601b64cd8b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d25b57b2ac671377f8042015896619c09a2f9b5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d25b57b2ac671377f8042015896619c09a2f9b5
new file mode 100644
index 0000000..5312ff2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d25b57b2ac671377f8042015896619c09a2f9b5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0dfc84a6703bdbe9a6acb72e178353d5d69f5814 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0dfc84a6703bdbe9a6acb72e178353d5d69f5814
new file mode 100644
index 0000000..119f151
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0dfc84a6703bdbe9a6acb72e178353d5d69f5814
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0e7a05178db60007ff4a8dea0e22b60825976c51 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e7a05178db60007ff4a8dea0e22b60825976c51
new file mode 100644
index 0000000..ac4d9dc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0e7a05178db60007ff4a8dea0e22b60825976c51
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0ec11a92c1830b4c2f56a0979dd9e3c7162bd624 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0ec11a92c1830b4c2f56a0979dd9e3c7162bd624
new file mode 100644
index 0000000..cdd1a44
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0ec11a92c1830b4c2f56a0979dd9e3c7162bd624
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0f01df12331467c4eed400465254eda05eaeb110 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f01df12331467c4eed400465254eda05eaeb110
new file mode 100644
index 0000000..09bf4db
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0f01df12331467c4eed400465254eda05eaeb110
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0feaff8d6ad28109f35d6c6080504456b242c8ce b/test/core/end2end/fuzzers/api_fuzzer_corpus/0feaff8d6ad28109f35d6c6080504456b242c8ce
new file mode 100644
index 0000000..40ae0b5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0feaff8d6ad28109f35d6c6080504456b242c8ce
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/10b47823e11c988222f5f778146f9cf922b286bf b/test/core/end2end/fuzzers/api_fuzzer_corpus/10b47823e11c988222f5f778146f9cf922b286bf
new file mode 100644
index 0000000..d0412a2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/10b47823e11c988222f5f778146f9cf922b286bf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/122b6fc72956541812dd653b726b073b77ca33be b/test/core/end2end/fuzzers/api_fuzzer_corpus/122b6fc72956541812dd653b726b073b77ca33be
new file mode 100644
index 0000000..e6eb181
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/122b6fc72956541812dd653b726b073b77ca33be
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/128a7ef7f9b87c4f299d3cafe2dfdb9b161756bd b/test/core/end2end/fuzzers/api_fuzzer_corpus/128a7ef7f9b87c4f299d3cafe2dfdb9b161756bd
new file mode 100644
index 0000000..9be7c77
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/128a7ef7f9b87c4f299d3cafe2dfdb9b161756bd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/14ee9fbfe5284650e3a3de83ecc3e09abdc48c16 b/test/core/end2end/fuzzers/api_fuzzer_corpus/14ee9fbfe5284650e3a3de83ecc3e09abdc48c16
new file mode 100644
index 0000000..54d8626
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/14ee9fbfe5284650e3a3de83ecc3e09abdc48c16
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/163cf93cebfb32d617830aa4e69e8b5f59bd3a08 b/test/core/end2end/fuzzers/api_fuzzer_corpus/163cf93cebfb32d617830aa4e69e8b5f59bd3a08
new file mode 100644
index 0000000..0a02d52
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/163cf93cebfb32d617830aa4e69e8b5f59bd3a08
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/174ea33060bccea880dfdcfa12c5349e8eb4cb2a b/test/core/end2end/fuzzers/api_fuzzer_corpus/174ea33060bccea880dfdcfa12c5349e8eb4cb2a
new file mode 100644
index 0000000..da32e95
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/174ea33060bccea880dfdcfa12c5349e8eb4cb2a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/17582452219fc4a27058a789f416a56631461296 b/test/core/end2end/fuzzers/api_fuzzer_corpus/17582452219fc4a27058a789f416a56631461296
new file mode 100644
index 0000000..80a5965
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/17582452219fc4a27058a789f416a56631461296
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1776f4c32c11490c65b81d0b7ae2ece4a3d1e9a7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1776f4c32c11490c65b81d0b7ae2ece4a3d1e9a7
new file mode 100644
index 0000000..64ceda1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1776f4c32c11490c65b81d0b7ae2ece4a3d1e9a7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/17a1354d2bfe982e9db1bac550fe01dd105f81c3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/17a1354d2bfe982e9db1bac550fe01dd105f81c3
new file mode 100644
index 0000000..6918b8a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/17a1354d2bfe982e9db1bac550fe01dd105f81c3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/17bc3a2ae619ef05ad35b147f4916c0453ebacf1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/17bc3a2ae619ef05ad35b147f4916c0453ebacf1
new file mode 100644
index 0000000..c7c2613
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/17bc3a2ae619ef05ad35b147f4916c0453ebacf1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/17e562d437fd283e58a5621c33b13191333b279f b/test/core/end2end/fuzzers/api_fuzzer_corpus/17e562d437fd283e58a5621c33b13191333b279f
new file mode 100644
index 0000000..28b70b3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/17e562d437fd283e58a5621c33b13191333b279f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1847f224b543fd0592e9cf365b8eddb61c140d82 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1847f224b543fd0592e9cf365b8eddb61c140d82
new file mode 100644
index 0000000..f8c75b5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1847f224b543fd0592e9cf365b8eddb61c140d82
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/19fdd6cdeee7a5cbc991d0e3242c23d5aaff2fbf b/test/core/end2end/fuzzers/api_fuzzer_corpus/19fdd6cdeee7a5cbc991d0e3242c23d5aaff2fbf
new file mode 100644
index 0000000..38d23fa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/19fdd6cdeee7a5cbc991d0e3242c23d5aaff2fbf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1b331dfc1d9d535063f0cc6f7a709499a5f8cb59 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b331dfc1d9d535063f0cc6f7a709499a5f8cb59
new file mode 100644
index 0000000..b67ad37
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b331dfc1d9d535063f0cc6f7a709499a5f8cb59
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1b50ba2e44a359f37205ae476682495cff96838d b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b50ba2e44a359f37205ae476682495cff96838d
new file mode 100644
index 0000000..bc8e233
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1b50ba2e44a359f37205ae476682495cff96838d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1c0dc85faed94bb89bc90f87799d7383cf9907cf b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c0dc85faed94bb89bc90f87799d7383cf9907cf
new file mode 100644
index 0000000..c83ac85
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c0dc85faed94bb89bc90f87799d7383cf9907cf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1c968074e9dcd8e9922e6c01ecfedcaf7b2fe5a3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c968074e9dcd8e9922e6c01ecfedcaf7b2fe5a3
new file mode 100644
index 0000000..2591059
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1c968074e9dcd8e9922e6c01ecfedcaf7b2fe5a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1ca16103f5175b0607b579e0c3734b59843e27b0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1ca16103f5175b0607b579e0c3734b59843e27b0
new file mode 100644
index 0000000..006d8e8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1ca16103f5175b0607b579e0c3734b59843e27b0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1cae148c387cd20a1742d902543c2c8396589479 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1cae148c387cd20a1742d902543c2c8396589479
new file mode 100644
index 0000000..3869d83
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1cae148c387cd20a1742d902543c2c8396589479
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1cfd4875b6708b439f1db655abfdd57c1141348a b/test/core/end2end/fuzzers/api_fuzzer_corpus/1cfd4875b6708b439f1db655abfdd57c1141348a
new file mode 100644
index 0000000..37a9bcf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1cfd4875b6708b439f1db655abfdd57c1141348a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1d10780f4cb83cb9f6762548ae133d2115c4354f b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d10780f4cb83cb9f6762548ae133d2115c4354f
new file mode 100644
index 0000000..a4c1921
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1d10780f4cb83cb9f6762548ae133d2115c4354f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1dba0d6c34b03b19e648e2fc9cb3aa7a13e713a2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1dba0d6c34b03b19e648e2fc9cb3aa7a13e713a2
new file mode 100644
index 0000000..ffa1c18
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1dba0d6c34b03b19e648e2fc9cb3aa7a13e713a2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1de191d81c4c7bf0e026bff0a040165c084fd630 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1de191d81c4c7bf0e026bff0a040165c084fd630
new file mode 100644
index 0000000..52fdbc5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1de191d81c4c7bf0e026bff0a040165c084fd630
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1e1f1e0230004479b502603a1b60552192559679 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1e1f1e0230004479b502603a1b60552192559679
new file mode 100644
index 0000000..18b642c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1e1f1e0230004479b502603a1b60552192559679
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1f3f61bbe6ea0c7e9b447f134742b3e7909b9198 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1f3f61bbe6ea0c7e9b447f134742b3e7909b9198
new file mode 100644
index 0000000..27491ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1f3f61bbe6ea0c7e9b447f134742b3e7909b9198
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/224b2255a1bd250102481abc3e823090650e231e b/test/core/end2end/fuzzers/api_fuzzer_corpus/224b2255a1bd250102481abc3e823090650e231e
new file mode 100644
index 0000000..6dee8f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/224b2255a1bd250102481abc3e823090650e231e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/22c7bfb3460529c77255e9cb82ef8f7d8381f8f3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/22c7bfb3460529c77255e9cb82ef8f7d8381f8f3
new file mode 100644
index 0000000..b5f6a85
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/22c7bfb3460529c77255e9cb82ef8f7d8381f8f3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/23746fe5e477430aec8b12e9d7de0f86f6a6e191 b/test/core/end2end/fuzzers/api_fuzzer_corpus/23746fe5e477430aec8b12e9d7de0f86f6a6e191
new file mode 100644
index 0000000..735003e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/23746fe5e477430aec8b12e9d7de0f86f6a6e191
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/247a7d3e0061dd0f32c3f6b2fc43a08e2cc8cf72 b/test/core/end2end/fuzzers/api_fuzzer_corpus/247a7d3e0061dd0f32c3f6b2fc43a08e2cc8cf72
new file mode 100644
index 0000000..667761e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/247a7d3e0061dd0f32c3f6b2fc43a08e2cc8cf72
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/25c05b84c4b4f1a93f0f72d368c3c3644b564881 b/test/core/end2end/fuzzers/api_fuzzer_corpus/25c05b84c4b4f1a93f0f72d368c3c3644b564881
new file mode 100644
index 0000000..0cde771
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/25c05b84c4b4f1a93f0f72d368c3c3644b564881
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/26794761df5dc7f093d2395b81a32af5e6b54392 b/test/core/end2end/fuzzers/api_fuzzer_corpus/26794761df5dc7f093d2395b81a32af5e6b54392
new file mode 100644
index 0000000..1eaa5be
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/26794761df5dc7f093d2395b81a32af5e6b54392
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/268d8763bb7846f4c9ebb4fbea476a5bc8fcc389 b/test/core/end2end/fuzzers/api_fuzzer_corpus/268d8763bb7846f4c9ebb4fbea476a5bc8fcc389
new file mode 100644
index 0000000..abf4177
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/268d8763bb7846f4c9ebb4fbea476a5bc8fcc389
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/289c2b6211858aa4a46b5b489bc4c9dd47828d21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/289c2b6211858aa4a46b5b489bc4c9dd47828d21
new file mode 100644
index 0000000..3e05110
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/289c2b6211858aa4a46b5b489bc4c9dd47828d21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/28cbfc7c1b760d216cc592a273088b31833ee707 b/test/core/end2end/fuzzers/api_fuzzer_corpus/28cbfc7c1b760d216cc592a273088b31833ee707
new file mode 100644
index 0000000..17031ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/28cbfc7c1b760d216cc592a273088b31833ee707
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/28fc3136371b5bcac84045ab6cc93e77298760e2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/28fc3136371b5bcac84045ab6cc93e77298760e2
new file mode 100644
index 0000000..c31dfa7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/28fc3136371b5bcac84045ab6cc93e77298760e2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2a4fc709f61977f0f6c75760af2b33007ecd5941 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a4fc709f61977f0f6c75760af2b33007ecd5941
new file mode 100644
index 0000000..8c978eb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2a4fc709f61977f0f6c75760af2b33007ecd5941
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2bb76eff88c5af98c4b8828047837fe97b50cfeb b/test/core/end2end/fuzzers/api_fuzzer_corpus/2bb76eff88c5af98c4b8828047837fe97b50cfeb
new file mode 100644
index 0000000..0e8dcdb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2bb76eff88c5af98c4b8828047837fe97b50cfeb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2ce3268455c461a30eb30f4792087df411548c13 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ce3268455c461a30eb30f4792087df411548c13
new file mode 100644
index 0000000..366221f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2ce3268455c461a30eb30f4792087df411548c13
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2d03c424dd0677a68f28bb94536f49844d79d00a b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d03c424dd0677a68f28bb94536f49844d79d00a
new file mode 100644
index 0000000..a4fb251
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d03c424dd0677a68f28bb94536f49844d79d00a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2d743ec0a0826177cfa7ffb335c0034f482e70e5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d743ec0a0826177cfa7ffb335c0034f482e70e5
new file mode 100644
index 0000000..5449b34
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2d743ec0a0826177cfa7ffb335c0034f482e70e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2dbe958ef23ade1b8bbb9669e590fa99454970b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2dbe958ef23ade1b8bbb9669e590fa99454970b4
new file mode 100644
index 0000000..e03e3b8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2dbe958ef23ade1b8bbb9669e590fa99454970b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2df7ea9c0c488fc8f79d33b6bce5667a2f051a65 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2df7ea9c0c488fc8f79d33b6bce5667a2f051a65
new file mode 100644
index 0000000..61278e1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2df7ea9c0c488fc8f79d33b6bce5667a2f051a65
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2feac28b1f508d6086f4cb0972800a77e1d01201 b/test/core/end2end/fuzzers/api_fuzzer_corpus/2feac28b1f508d6086f4cb0972800a77e1d01201
new file mode 100644
index 0000000..da5b452
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2feac28b1f508d6086f4cb0972800a77e1d01201
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/30738789e20323323196dd3e6435fa278e73279e b/test/core/end2end/fuzzers/api_fuzzer_corpus/30738789e20323323196dd3e6435fa278e73279e
new file mode 100644
index 0000000..a85ff98
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/30738789e20323323196dd3e6435fa278e73279e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/307aaef3b3982cf8d4780a1f896d5392037c5db2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/307aaef3b3982cf8d4780a1f896d5392037c5db2
new file mode 100644
index 0000000..f38bf0e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/307aaef3b3982cf8d4780a1f896d5392037c5db2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3082fa77cc2942ae425a6577d1f9c0dddd2949be b/test/core/end2end/fuzzers/api_fuzzer_corpus/3082fa77cc2942ae425a6577d1f9c0dddd2949be
new file mode 100644
index 0000000..380f280
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3082fa77cc2942ae425a6577d1f9c0dddd2949be
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/308fbf16b3f3747423b2ff69ef5930b01ca9b728 b/test/core/end2end/fuzzers/api_fuzzer_corpus/308fbf16b3f3747423b2ff69ef5930b01ca9b728
new file mode 100644
index 0000000..3cd23c5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/308fbf16b3f3747423b2ff69ef5930b01ca9b728
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/30d2e4b3cac45cbcfe76459c90c49e085914c154 b/test/core/end2end/fuzzers/api_fuzzer_corpus/30d2e4b3cac45cbcfe76459c90c49e085914c154
new file mode 100644
index 0000000..1fbfcfe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/30d2e4b3cac45cbcfe76459c90c49e085914c154
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/315d27e12f2214a56fb9901dacff14852ff2ac0f b/test/core/end2end/fuzzers/api_fuzzer_corpus/315d27e12f2214a56fb9901dacff14852ff2ac0f
new file mode 100644
index 0000000..379a157
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/315d27e12f2214a56fb9901dacff14852ff2ac0f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/31d8226b1d767fc895e87d7feede0e2d7c6c0b66 b/test/core/end2end/fuzzers/api_fuzzer_corpus/31d8226b1d767fc895e87d7feede0e2d7c6c0b66
new file mode 100644
index 0000000..7ace4ff
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/31d8226b1d767fc895e87d7feede0e2d7c6c0b66
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/33252c0d4edb12370235c0179abd87a5efb59d29 b/test/core/end2end/fuzzers/api_fuzzer_corpus/33252c0d4edb12370235c0179abd87a5efb59d29
new file mode 100644
index 0000000..378afc0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/33252c0d4edb12370235c0179abd87a5efb59d29
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/33d926a04c1868c3393b3129968ffd32049a1c64 b/test/core/end2end/fuzzers/api_fuzzer_corpus/33d926a04c1868c3393b3129968ffd32049a1c64
new file mode 100644
index 0000000..dc8950f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/33d926a04c1868c3393b3129968ffd32049a1c64
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/33e01fe9738c887b159ca5add342b22c13e526cf b/test/core/end2end/fuzzers/api_fuzzer_corpus/33e01fe9738c887b159ca5add342b22c13e526cf
new file mode 100644
index 0000000..9b3060c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/33e01fe9738c887b159ca5add342b22c13e526cf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/33f0e1b78dd158df720604cbb4c9a0c90eece435 b/test/core/end2end/fuzzers/api_fuzzer_corpus/33f0e1b78dd158df720604cbb4c9a0c90eece435
new file mode 100644
index 0000000..df5e442
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/33f0e1b78dd158df720604cbb4c9a0c90eece435
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/34e2445f42fd82c5ce229782a93764def3aae0e7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/34e2445f42fd82c5ce229782a93764def3aae0e7
new file mode 100644
index 0000000..7445223
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/34e2445f42fd82c5ce229782a93764def3aae0e7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/352599b2850ac5a96ec656788c897c4b36114cc4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/352599b2850ac5a96ec656788c897c4b36114cc4
new file mode 100644
index 0000000..4e28b81
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/352599b2850ac5a96ec656788c897c4b36114cc4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/35d6503b48b5acc5486a158696ae98a98f46e1a4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/35d6503b48b5acc5486a158696ae98a98f46e1a4
new file mode 100644
index 0000000..348387f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/35d6503b48b5acc5486a158696ae98a98f46e1a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/35ea066b0fc90521bd8401ef4c52cdc9897d35d4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/35ea066b0fc90521bd8401ef4c52cdc9897d35d4
new file mode 100644
index 0000000..e56a34b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/35ea066b0fc90521bd8401ef4c52cdc9897d35d4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/35f172b0168cd0b2da4509c3463c2502274e01a6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/35f172b0168cd0b2da4509c3463c2502274e01a6
new file mode 100644
index 0000000..f3798b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/35f172b0168cd0b2da4509c3463c2502274e01a6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3698d88414f52b7c4759bfdadb53161b226faf8c b/test/core/end2end/fuzzers/api_fuzzer_corpus/3698d88414f52b7c4759bfdadb53161b226faf8c
new file mode 100644
index 0000000..9450612
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3698d88414f52b7c4759bfdadb53161b226faf8c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/36dd4f4239b63b9cf379b354de0dc72e6356fba5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/36dd4f4239b63b9cf379b354de0dc72e6356fba5
new file mode 100644
index 0000000..214d1b6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/36dd4f4239b63b9cf379b354de0dc72e6356fba5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/38259d219a41c1bc60e3867dc60e3473f98cef64 b/test/core/end2end/fuzzers/api_fuzzer_corpus/38259d219a41c1bc60e3867dc60e3473f98cef64
new file mode 100644
index 0000000..22707d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/38259d219a41c1bc60e3867dc60e3473f98cef64
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/390daee799863cdd0533f35b15b5c0a4f5d79a79 b/test/core/end2end/fuzzers/api_fuzzer_corpus/390daee799863cdd0533f35b15b5c0a4f5d79a79
new file mode 100644
index 0000000..6feaf9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/390daee799863cdd0533f35b15b5c0a4f5d79a79
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3a3346314bb9ddaf14877b653cfd506b6ad34fab b/test/core/end2end/fuzzers/api_fuzzer_corpus/3a3346314bb9ddaf14877b653cfd506b6ad34fab
new file mode 100644
index 0000000..1695b94
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3a3346314bb9ddaf14877b653cfd506b6ad34fab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3c942f9491b1e8b5bb9761a4dbb1bc7165850dfc b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c942f9491b1e8b5bb9761a4dbb1bc7165850dfc
new file mode 100644
index 0000000..a53d26d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c942f9491b1e8b5bb9761a4dbb1bc7165850dfc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3c9a414ad8fcc53c3271bbc8375086d8d1fa450c b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c9a414ad8fcc53c3271bbc8375086d8d1fa450c
new file mode 100644
index 0000000..e46e0ab
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3c9a414ad8fcc53c3271bbc8375086d8d1fa450c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3cac506501825fadf2e4adf7619d16f72cfd8832 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3cac506501825fadf2e4adf7619d16f72cfd8832
new file mode 100644
index 0000000..62447e4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3cac506501825fadf2e4adf7619d16f72cfd8832
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3cc56c99c6046f0d66c50c4062d90608064fd742 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3cc56c99c6046f0d66c50c4062d90608064fd742
new file mode 100644
index 0000000..4dbb2b9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3cc56c99c6046f0d66c50c4062d90608064fd742
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3d929a8f8e77e038ddaecf9d149189cfeeec30fc b/test/core/end2end/fuzzers/api_fuzzer_corpus/3d929a8f8e77e038ddaecf9d149189cfeeec30fc
new file mode 100644
index 0000000..b636301
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3d929a8f8e77e038ddaecf9d149189cfeeec30fc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3de19989758b5b68b29af3dfc6c0e55d414dca32 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3de19989758b5b68b29af3dfc6c0e55d414dca32
new file mode 100644
index 0000000..e51ac9d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3de19989758b5b68b29af3dfc6c0e55d414dca32
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3e82319f1a44ea9224d65feb07ee0ef622709dac b/test/core/end2end/fuzzers/api_fuzzer_corpus/3e82319f1a44ea9224d65feb07ee0ef622709dac
new file mode 100644
index 0000000..26735fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3e82319f1a44ea9224d65feb07ee0ef622709dac
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/3f2429e3255ae36fecb57559b57d2b0cb88f5dd1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f2429e3255ae36fecb57559b57d2b0cb88f5dd1
new file mode 100644
index 0000000..8341994
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/3f2429e3255ae36fecb57559b57d2b0cb88f5dd1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4004d9ccc668572796770fb3401376844e1574ae b/test/core/end2end/fuzzers/api_fuzzer_corpus/4004d9ccc668572796770fb3401376844e1574ae
new file mode 100644
index 0000000..8168723
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4004d9ccc668572796770fb3401376844e1574ae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/409d7e2c0173b5a00a475f79e2fbdbe596d8368a b/test/core/end2end/fuzzers/api_fuzzer_corpus/409d7e2c0173b5a00a475f79e2fbdbe596d8368a
new file mode 100644
index 0000000..75d8f1c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/409d7e2c0173b5a00a475f79e2fbdbe596d8368a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/41bda7ff09175f821992adf4314a8ec3007ffe55 b/test/core/end2end/fuzzers/api_fuzzer_corpus/41bda7ff09175f821992adf4314a8ec3007ffe55
new file mode 100644
index 0000000..a89e88e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/41bda7ff09175f821992adf4314a8ec3007ffe55
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/421feb3fe383541082a65a447a51b4af991ceb7e b/test/core/end2end/fuzzers/api_fuzzer_corpus/421feb3fe383541082a65a447a51b4af991ceb7e
new file mode 100644
index 0000000..45223cd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/421feb3fe383541082a65a447a51b4af991ceb7e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/42231300ca5cf30d18f55b66020926882c64248c b/test/core/end2end/fuzzers/api_fuzzer_corpus/42231300ca5cf30d18f55b66020926882c64248c
new file mode 100644
index 0000000..0119532
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/42231300ca5cf30d18f55b66020926882c64248c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4239c3636053665277d07bafda37ee84c114b13a b/test/core/end2end/fuzzers/api_fuzzer_corpus/4239c3636053665277d07bafda37ee84c114b13a
new file mode 100644
index 0000000..04acde1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4239c3636053665277d07bafda37ee84c114b13a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/424b6a20be32318d920d83aa2a292a0aba013a1b b/test/core/end2end/fuzzers/api_fuzzer_corpus/424b6a20be32318d920d83aa2a292a0aba013a1b
new file mode 100644
index 0000000..00026e7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/424b6a20be32318d920d83aa2a292a0aba013a1b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/426b7f180ab26cf276a223246d4d6bd972ccf55a b/test/core/end2end/fuzzers/api_fuzzer_corpus/426b7f180ab26cf276a223246d4d6bd972ccf55a
new file mode 100644
index 0000000..3e0a69e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/426b7f180ab26cf276a223246d4d6bd972ccf55a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/428cce92c42645f4cc4060a8cb9cef3a803c0341 b/test/core/end2end/fuzzers/api_fuzzer_corpus/428cce92c42645f4cc4060a8cb9cef3a803c0341
new file mode 100644
index 0000000..39faa0d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/428cce92c42645f4cc4060a8cb9cef3a803c0341
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/43cdc82b082bbdc4d7d23437a7f761f1ca32ca73 b/test/core/end2end/fuzzers/api_fuzzer_corpus/43cdc82b082bbdc4d7d23437a7f761f1ca32ca73
new file mode 100644
index 0000000..c8250c8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/43cdc82b082bbdc4d7d23437a7f761f1ca32ca73
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/43f8e0abe3f647350ab1d8d368cca9af6ca47729 b/test/core/end2end/fuzzers/api_fuzzer_corpus/43f8e0abe3f647350ab1d8d368cca9af6ca47729
new file mode 100644
index 0000000..344491e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/43f8e0abe3f647350ab1d8d368cca9af6ca47729
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/448fc1dc939aa7f398f1577e418630abecc0a1d7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/448fc1dc939aa7f398f1577e418630abecc0a1d7
new file mode 100644
index 0000000..d5f6314
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/448fc1dc939aa7f398f1577e418630abecc0a1d7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4523e89844538d8de502907f143c35624182f76c b/test/core/end2end/fuzzers/api_fuzzer_corpus/4523e89844538d8de502907f143c35624182f76c
new file mode 100644
index 0000000..9f89f26
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4523e89844538d8de502907f143c35624182f76c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/453861de5ab948236f13ebff66c8e82e4e789db6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/453861de5ab948236f13ebff66c8e82e4e789db6
new file mode 100644
index 0000000..9ebd8ae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/453861de5ab948236f13ebff66c8e82e4e789db6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/46171f477d11338f4cc948915350772d54319200 b/test/core/end2end/fuzzers/api_fuzzer_corpus/46171f477d11338f4cc948915350772d54319200
new file mode 100644
index 0000000..df03266
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/46171f477d11338f4cc948915350772d54319200
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/46e1492e19d0cffdadc1050cc22d505b4e057759 b/test/core/end2end/fuzzers/api_fuzzer_corpus/46e1492e19d0cffdadc1050cc22d505b4e057759
new file mode 100644
index 0000000..34bdf1f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/46e1492e19d0cffdadc1050cc22d505b4e057759
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4725b858491e1517af1032efba6bb198f39fd62d b/test/core/end2end/fuzzers/api_fuzzer_corpus/4725b858491e1517af1032efba6bb198f39fd62d
new file mode 100644
index 0000000..860a36c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4725b858491e1517af1032efba6bb198f39fd62d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/48062d4824e8ba697cdd16a46b85d82ff445e649 b/test/core/end2end/fuzzers/api_fuzzer_corpus/48062d4824e8ba697cdd16a46b85d82ff445e649
new file mode 100644
index 0000000..f472b3b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/48062d4824e8ba697cdd16a46b85d82ff445e649
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4857011f92ceaed4fee4d7612e1c46930903c95b b/test/core/end2end/fuzzers/api_fuzzer_corpus/4857011f92ceaed4fee4d7612e1c46930903c95b
new file mode 100644
index 0000000..e94c7cb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4857011f92ceaed4fee4d7612e1c46930903c95b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/48c1691a919f1055f748e43cd799770f00c1c38a b/test/core/end2end/fuzzers/api_fuzzer_corpus/48c1691a919f1055f748e43cd799770f00c1c38a
new file mode 100644
index 0000000..3f0b5ed
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/48c1691a919f1055f748e43cd799770f00c1c38a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/49254390bbc7e7b9eb58ddb1ac54a1e7eacee168 b/test/core/end2end/fuzzers/api_fuzzer_corpus/49254390bbc7e7b9eb58ddb1ac54a1e7eacee168
new file mode 100644
index 0000000..b5418cf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/49254390bbc7e7b9eb58ddb1ac54a1e7eacee168
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/49d0085058d7fa81247f51b802c0f4206854b4dc b/test/core/end2end/fuzzers/api_fuzzer_corpus/49d0085058d7fa81247f51b802c0f4206854b4dc
new file mode 100644
index 0000000..052fa85
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/49d0085058d7fa81247f51b802c0f4206854b4dc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4a5a1abe7b402338c625013caa9bc8464a3d0bf2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a5a1abe7b402338c625013caa9bc8464a3d0bf2
new file mode 100644
index 0000000..7ad87be
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4a5a1abe7b402338c625013caa9bc8464a3d0bf2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4ad1a61051d0db46638b774c61392b9d1c360410 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4ad1a61051d0db46638b774c61392b9d1c360410
new file mode 100644
index 0000000..08cdf0e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4ad1a61051d0db46638b774c61392b9d1c360410
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4aecde7ffaea881f42e693858b25c334df711b27 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4aecde7ffaea881f42e693858b25c334df711b27
new file mode 100644
index 0000000..651d85f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4aecde7ffaea881f42e693858b25c334df711b27
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4b0e9a84edc3eb0e6c377e860f5ecfca1bf64baa b/test/core/end2end/fuzzers/api_fuzzer_corpus/4b0e9a84edc3eb0e6c377e860f5ecfca1bf64baa
new file mode 100644
index 0000000..23a3627
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4b0e9a84edc3eb0e6c377e860f5ecfca1bf64baa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/4b303d7f245a569f507013af0b3afb2f033b6741 b/test/core/end2end/fuzzers/api_fuzzer_corpus/4b303d7f245a569f507013af0b3afb2f033b6741
new file mode 100644
index 0000000..47d9819
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/4b303d7f245a569f507013af0b3afb2f033b6741
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5035db01a56a34061837c4d0214f6e5112d81ff3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5035db01a56a34061837c4d0214f6e5112d81ff3
new file mode 100644
index 0000000..a2e1b25
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5035db01a56a34061837c4d0214f6e5112d81ff3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/503649137cea18ced8a57e7c644162bee8885ed1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/503649137cea18ced8a57e7c644162bee8885ed1
new file mode 100644
index 0000000..58fba3d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/503649137cea18ced8a57e7c644162bee8885ed1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/51716d5683d5c762298fdfa6b57ecf17d6892fe6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/51716d5683d5c762298fdfa6b57ecf17d6892fe6
new file mode 100644
index 0000000..a8d3674
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/51716d5683d5c762298fdfa6b57ecf17d6892fe6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/51adadd4662ab165a203afdbdbc470b62ac24d36 b/test/core/end2end/fuzzers/api_fuzzer_corpus/51adadd4662ab165a203afdbdbc470b62ac24d36
new file mode 100644
index 0000000..c27014a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/51adadd4662ab165a203afdbdbc470b62ac24d36
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/51ea84d5a790d3d2495be453f5341c41b6153644 b/test/core/end2end/fuzzers/api_fuzzer_corpus/51ea84d5a790d3d2495be453f5341c41b6153644
new file mode 100644
index 0000000..df8ee08
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/51ea84d5a790d3d2495be453f5341c41b6153644
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/52ac4e5a6c433b7e135e817b797f9bc85d4c619a b/test/core/end2end/fuzzers/api_fuzzer_corpus/52ac4e5a6c433b7e135e817b797f9bc85d4c619a
new file mode 100644
index 0000000..44746e4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/52ac4e5a6c433b7e135e817b797f9bc85d4c619a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/536b5c0bf942c03bf9d4a4cc27c97c1230128ede b/test/core/end2end/fuzzers/api_fuzzer_corpus/536b5c0bf942c03bf9d4a4cc27c97c1230128ede
new file mode 100644
index 0000000..f6d08b9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/536b5c0bf942c03bf9d4a4cc27c97c1230128ede
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/53e7030d5de06dcf80e1a60aa467e6e31bec6515 b/test/core/end2end/fuzzers/api_fuzzer_corpus/53e7030d5de06dcf80e1a60aa467e6e31bec6515
new file mode 100644
index 0000000..dd161f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/53e7030d5de06dcf80e1a60aa467e6e31bec6515
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/54168e5030c8a7cdd58162dee7c2583bb4caaf64 b/test/core/end2end/fuzzers/api_fuzzer_corpus/54168e5030c8a7cdd58162dee7c2583bb4caaf64
new file mode 100644
index 0000000..459a76b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/54168e5030c8a7cdd58162dee7c2583bb4caaf64
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5547a3544fc5c634024d546366704547dd72cc2b b/test/core/end2end/fuzzers/api_fuzzer_corpus/5547a3544fc5c634024d546366704547dd72cc2b
new file mode 100644
index 0000000..9e6f5b6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5547a3544fc5c634024d546366704547dd72cc2b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5559428fa9a1f1701e81eec11a3571be403bf627 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5559428fa9a1f1701e81eec11a3571be403bf627
new file mode 100644
index 0000000..1809298
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5559428fa9a1f1701e81eec11a3571be403bf627
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/559d537675dd3fc5e0c6d40e94133e9016014f6c b/test/core/end2end/fuzzers/api_fuzzer_corpus/559d537675dd3fc5e0c6d40e94133e9016014f6c
new file mode 100644
index 0000000..25327f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/559d537675dd3fc5e0c6d40e94133e9016014f6c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/55a71f74f233ea8ce88967c5660aaa532fbc985c b/test/core/end2end/fuzzers/api_fuzzer_corpus/55a71f74f233ea8ce88967c5660aaa532fbc985c
new file mode 100644
index 0000000..d02a29d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/55a71f74f233ea8ce88967c5660aaa532fbc985c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/55da9fe903905e9852dedf6b664a4a589efeeec5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/55da9fe903905e9852dedf6b664a4a589efeeec5
new file mode 100644
index 0000000..8118bbb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/55da9fe903905e9852dedf6b664a4a589efeeec5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/567026bafbad3be6a7bd430577e7d39ec3d56af6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/567026bafbad3be6a7bd430577e7d39ec3d56af6
new file mode 100644
index 0000000..1d6e37a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/567026bafbad3be6a7bd430577e7d39ec3d56af6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/56f240463ef197b49c7e271e74412f62909974dc b/test/core/end2end/fuzzers/api_fuzzer_corpus/56f240463ef197b49c7e271e74412f62909974dc
new file mode 100644
index 0000000..4f77004
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/56f240463ef197b49c7e271e74412f62909974dc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/57b087d753a6af79c0b58ca2c9aa5c92bc18a6a5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/57b087d753a6af79c0b58ca2c9aa5c92bc18a6a5
new file mode 100644
index 0000000..af1031c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/57b087d753a6af79c0b58ca2c9aa5c92bc18a6a5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/59b547627a6b1aef96f6c5e3b7dc08c3e1244368 b/test/core/end2end/fuzzers/api_fuzzer_corpus/59b547627a6b1aef96f6c5e3b7dc08c3e1244368
new file mode 100644
index 0000000..efc8af9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/59b547627a6b1aef96f6c5e3b7dc08c3e1244368
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5ac0e42338f7b064f5c23697f1174a10b42e7ed8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ac0e42338f7b064f5c23697f1174a10b42e7ed8
new file mode 100644
index 0000000..1cce5ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ac0e42338f7b064f5c23697f1174a10b42e7ed8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5ac8cb08604c86b9e8ca24482ca963eddac2efbe b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ac8cb08604c86b9e8ca24482ca963eddac2efbe
new file mode 100644
index 0000000..9a2cafd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5ac8cb08604c86b9e8ca24482ca963eddac2efbe
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5bc4eddc2a2881d4b6b4f9532f4fb381e4cc9529 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5bc4eddc2a2881d4b6b4f9532f4fb381e4cc9529
new file mode 100644
index 0000000..9fa502f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5bc4eddc2a2881d4b6b4f9532f4fb381e4cc9529
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5be0001be32d9e619769c7cc6cb9f541efe4996c b/test/core/end2end/fuzzers/api_fuzzer_corpus/5be0001be32d9e619769c7cc6cb9f541efe4996c
new file mode 100644
index 0000000..c42fa29
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5be0001be32d9e619769c7cc6cb9f541efe4996c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5c6debdb92eb9089773cc8d092d7f62d521ae029 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c6debdb92eb9089773cc8d092d7f62d521ae029
new file mode 100644
index 0000000..ee6dfef
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5c6debdb92eb9089773cc8d092d7f62d521ae029
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5cfdc00a568d97b09e720a72eac7e5fbbf76247b b/test/core/end2end/fuzzers/api_fuzzer_corpus/5cfdc00a568d97b09e720a72eac7e5fbbf76247b
new file mode 100644
index 0000000..6a74f12
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5cfdc00a568d97b09e720a72eac7e5fbbf76247b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5da1a1a4ee88d2a2b6e9470dd7be9e2dd9eecc4d b/test/core/end2end/fuzzers/api_fuzzer_corpus/5da1a1a4ee88d2a2b6e9470dd7be9e2dd9eecc4d
new file mode 100644
index 0000000..65b8542
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5da1a1a4ee88d2a2b6e9470dd7be9e2dd9eecc4d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5e0c4179d297f5bafe86b9e256bf75d54cfd1fb0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5e0c4179d297f5bafe86b9e256bf75d54cfd1fb0
new file mode 100644
index 0000000..e8de3ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5e0c4179d297f5bafe86b9e256bf75d54cfd1fb0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5eeb786fa5735ef9b98c40e205f2eba24223acfd b/test/core/end2end/fuzzers/api_fuzzer_corpus/5eeb786fa5735ef9b98c40e205f2eba24223acfd
new file mode 100644
index 0000000..783110d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5eeb786fa5735ef9b98c40e205f2eba24223acfd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5f3a4ed52525d1db60b45d79057a6e276395e562 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f3a4ed52525d1db60b45d79057a6e276395e562
new file mode 100644
index 0000000..25d6cda
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f3a4ed52525d1db60b45d79057a6e276395e562
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5fbffd9d324ad078bf6f5fdd39e5e4a27afd5965 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5fbffd9d324ad078bf6f5fdd39e5e4a27afd5965
new file mode 100644
index 0000000..2f4a3d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5fbffd9d324ad078bf6f5fdd39e5e4a27afd5965
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6042b1bbaf3ceac51c11a472ea07a75e822b7bc5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6042b1bbaf3ceac51c11a472ea07a75e822b7bc5
new file mode 100644
index 0000000..1a4e8af
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6042b1bbaf3ceac51c11a472ea07a75e822b7bc5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/60b4c79213b97204d1e4f6819ad1ed5f6e191789 b/test/core/end2end/fuzzers/api_fuzzer_corpus/60b4c79213b97204d1e4f6819ad1ed5f6e191789
new file mode 100644
index 0000000..2c44e5d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/60b4c79213b97204d1e4f6819ad1ed5f6e191789
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/60eec02f3b3aa23b12261ed00163d122b24ab5af b/test/core/end2end/fuzzers/api_fuzzer_corpus/60eec02f3b3aa23b12261ed00163d122b24ab5af
new file mode 100644
index 0000000..5db7404
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/60eec02f3b3aa23b12261ed00163d122b24ab5af
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6108ac96de85e973db42982eff9d2f877a36699d b/test/core/end2end/fuzzers/api_fuzzer_corpus/6108ac96de85e973db42982eff9d2f877a36699d
new file mode 100644
index 0000000..8959111
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6108ac96de85e973db42982eff9d2f877a36699d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/614dbc86b17270ef1d5ab705ecbe88c742815ce7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/614dbc86b17270ef1d5ab705ecbe88c742815ce7
new file mode 100644
index 0000000..8fdff18
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/614dbc86b17270ef1d5ab705ecbe88c742815ce7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/62515c0e559e40838126e5be6ede5440875a3f70 b/test/core/end2end/fuzzers/api_fuzzer_corpus/62515c0e559e40838126e5be6ede5440875a3f70
new file mode 100644
index 0000000..3dc4c18
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/62515c0e559e40838126e5be6ede5440875a3f70
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/63f1e7c7eb4d0ee635c3794993d2e2132cba72d4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/63f1e7c7eb4d0ee635c3794993d2e2132cba72d4
new file mode 100644
index 0000000..722c8a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/63f1e7c7eb4d0ee635c3794993d2e2132cba72d4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/64656ddf81738f914ead8003c19d0148c54f34d6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/64656ddf81738f914ead8003c19d0148c54f34d6
new file mode 100644
index 0000000..daf5bc1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/64656ddf81738f914ead8003c19d0148c54f34d6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/64d1666dc1b1126bb99e3792040dff64b336ae36 b/test/core/end2end/fuzzers/api_fuzzer_corpus/64d1666dc1b1126bb99e3792040dff64b336ae36
new file mode 100644
index 0000000..f5a526c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/64d1666dc1b1126bb99e3792040dff64b336ae36
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/64d410e245db26eb7996c20bee1e3dfd77c43ebc b/test/core/end2end/fuzzers/api_fuzzer_corpus/64d410e245db26eb7996c20bee1e3dfd77c43ebc
new file mode 100644
index 0000000..dd97b42
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/64d410e245db26eb7996c20bee1e3dfd77c43ebc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/671d63b9968444308d4908eb6a26bccdf32e5e29 b/test/core/end2end/fuzzers/api_fuzzer_corpus/671d63b9968444308d4908eb6a26bccdf32e5e29
new file mode 100644
index 0000000..38c69c7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/671d63b9968444308d4908eb6a26bccdf32e5e29
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6757865ccfef9bf8f1ba4302be9767758390fa92 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6757865ccfef9bf8f1ba4302be9767758390fa92
new file mode 100644
index 0000000..4c2914d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6757865ccfef9bf8f1ba4302be9767758390fa92
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/681b758cad3bbce4bde2d1a78a2ec4600c59b05c b/test/core/end2end/fuzzers/api_fuzzer_corpus/681b758cad3bbce4bde2d1a78a2ec4600c59b05c
new file mode 100644
index 0000000..d54a2af
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/681b758cad3bbce4bde2d1a78a2ec4600c59b05c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/68359027351be494040cc9ae6d4ccfc248fe6fcd b/test/core/end2end/fuzzers/api_fuzzer_corpus/68359027351be494040cc9ae6d4ccfc248fe6fcd
new file mode 100644
index 0000000..554a83b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/68359027351be494040cc9ae6d4ccfc248fe6fcd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6951632faa6eee58b6480b7cae00ee8ea1223658 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6951632faa6eee58b6480b7cae00ee8ea1223658
new file mode 100644
index 0000000..76d8c7d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6951632faa6eee58b6480b7cae00ee8ea1223658
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/69c6c28a67fe1b5ea32cab0f06564c59ec3fcbab b/test/core/end2end/fuzzers/api_fuzzer_corpus/69c6c28a67fe1b5ea32cab0f06564c59ec3fcbab
new file mode 100644
index 0000000..1d17649
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/69c6c28a67fe1b5ea32cab0f06564c59ec3fcbab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6a2b1a1222017169ff83695bb42bf760c8126a2d b/test/core/end2end/fuzzers/api_fuzzer_corpus/6a2b1a1222017169ff83695bb42bf760c8126a2d
new file mode 100644
index 0000000..f255057
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6a2b1a1222017169ff83695bb42bf760c8126a2d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6a3dee1cefadc15954dafe424c73b78a3b5c1b22 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6a3dee1cefadc15954dafe424c73b78a3b5c1b22
new file mode 100644
index 0000000..3dee8d0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6a3dee1cefadc15954dafe424c73b78a3b5c1b22
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ad3a1170ef884a884a6f340101549df624bf5a4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ad3a1170ef884a884a6f340101549df624bf5a4
new file mode 100644
index 0000000..27cea9e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ad3a1170ef884a884a6f340101549df624bf5a4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ae25d59c9f771291edddc6c71d01c855883b99b b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ae25d59c9f771291edddc6c71d01c855883b99b
new file mode 100644
index 0000000..dede6d1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ae25d59c9f771291edddc6c71d01c855883b99b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6cb17148d52be437332b6fd6f2fc8328bfb63fb0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6cb17148d52be437332b6fd6f2fc8328bfb63fb0
new file mode 100644
index 0000000..36d98fe
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6cb17148d52be437332b6fd6f2fc8328bfb63fb0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ea192b1d4c4577ca7511f8ce5027b31b2e0d75d b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ea192b1d4c4577ca7511f8ce5027b31b2e0d75d
new file mode 100644
index 0000000..a31fcf5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ea192b1d4c4577ca7511f8ce5027b31b2e0d75d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6ed943877a76ab6b17443e5b194012d9008612ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ed943877a76ab6b17443e5b194012d9008612ad
new file mode 100644
index 0000000..3507876
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6ed943877a76ab6b17443e5b194012d9008612ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6eef551288136e9fb2d9de210b14148746203472 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6eef551288136e9fb2d9de210b14148746203472
new file mode 100644
index 0000000..8f838a4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6eef551288136e9fb2d9de210b14148746203472
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/70cf4c8bdd833f8c62d8c89ef50d50008457f5ac b/test/core/end2end/fuzzers/api_fuzzer_corpus/70cf4c8bdd833f8c62d8c89ef50d50008457f5ac
new file mode 100644
index 0000000..f40f24f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/70cf4c8bdd833f8c62d8c89ef50d50008457f5ac
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/71403746b8e54a5f9b6fa1882a7ff5322180dd01 b/test/core/end2end/fuzzers/api_fuzzer_corpus/71403746b8e54a5f9b6fa1882a7ff5322180dd01
new file mode 100644
index 0000000..ce9f217
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/71403746b8e54a5f9b6fa1882a7ff5322180dd01
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/71961e53698b07bfd57e9ea37067e0dd52298a3d b/test/core/end2end/fuzzers/api_fuzzer_corpus/71961e53698b07bfd57e9ea37067e0dd52298a3d
new file mode 100644
index 0000000..21a263f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/71961e53698b07bfd57e9ea37067e0dd52298a3d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/71a0dd688553c753919c58d00c8e8db130726b3b b/test/core/end2end/fuzzers/api_fuzzer_corpus/71a0dd688553c753919c58d00c8e8db130726b3b
new file mode 100644
index 0000000..940e579
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/71a0dd688553c753919c58d00c8e8db130726b3b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/71cbd5e4e98344dd16df8b21546439cdb0879e0f b/test/core/end2end/fuzzers/api_fuzzer_corpus/71cbd5e4e98344dd16df8b21546439cdb0879e0f
new file mode 100644
index 0000000..3ca83e1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/71cbd5e4e98344dd16df8b21546439cdb0879e0f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/72031f24261c32d2e3bb2c7909a9315227172730 b/test/core/end2end/fuzzers/api_fuzzer_corpus/72031f24261c32d2e3bb2c7909a9315227172730
new file mode 100644
index 0000000..b02f72e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/72031f24261c32d2e3bb2c7909a9315227172730
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/746477e7e8f093f87cb6924ab6476cda9689607d b/test/core/end2end/fuzzers/api_fuzzer_corpus/746477e7e8f093f87cb6924ab6476cda9689607d
new file mode 100644
index 0000000..e348c19
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/746477e7e8f093f87cb6924ab6476cda9689607d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/750668bd25d3c4d5c8ff863185749d31978b88e5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/750668bd25d3c4d5c8ff863185749d31978b88e5
new file mode 100644
index 0000000..7d4f440
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/750668bd25d3c4d5c8ff863185749d31978b88e5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/755e5b679c1bb2720590e166d5047588a0e2f8b0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/755e5b679c1bb2720590e166d5047588a0e2f8b0
new file mode 100644
index 0000000..35af128
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/755e5b679c1bb2720590e166d5047588a0e2f8b0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/75af1ed0b83b24a1d5201038a4b382d0ace6222f b/test/core/end2end/fuzzers/api_fuzzer_corpus/75af1ed0b83b24a1d5201038a4b382d0ace6222f
new file mode 100644
index 0000000..7040b2f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/75af1ed0b83b24a1d5201038a4b382d0ace6222f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/75cd5b751f530f494c224304b4024d490032e65a b/test/core/end2end/fuzzers/api_fuzzer_corpus/75cd5b751f530f494c224304b4024d490032e65a
new file mode 100644
index 0000000..3424038
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/75cd5b751f530f494c224304b4024d490032e65a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/75f9b79cacbfef018bb131af2e2ba0735b2640ec b/test/core/end2end/fuzzers/api_fuzzer_corpus/75f9b79cacbfef018bb131af2e2ba0735b2640ec
new file mode 100644
index 0000000..0bbc39c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/75f9b79cacbfef018bb131af2e2ba0735b2640ec
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/76116b26156d91b16a70f28a126ed5f05ce55548 b/test/core/end2end/fuzzers/api_fuzzer_corpus/76116b26156d91b16a70f28a126ed5f05ce55548
new file mode 100644
index 0000000..9789045
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/76116b26156d91b16a70f28a126ed5f05ce55548
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/766995b9faa25c3b2c825413e5e9a702721de7fa b/test/core/end2end/fuzzers/api_fuzzer_corpus/766995b9faa25c3b2c825413e5e9a702721de7fa
new file mode 100644
index 0000000..4c281a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/766995b9faa25c3b2c825413e5e9a702721de7fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7752153d87017b85112a49ea95aa25ca78d24431 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7752153d87017b85112a49ea95aa25ca78d24431
new file mode 100644
index 0000000..8e9b21a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7752153d87017b85112a49ea95aa25ca78d24431
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/77f4f436f910c45f216fe4d3f9b631612ed09cf6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/77f4f436f910c45f216fe4d3f9b631612ed09cf6
new file mode 100644
index 0000000..8e31ee6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/77f4f436f910c45f216fe4d3f9b631612ed09cf6
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/780fc96dea7f78bb9d1a074efbd966b03d78d653 b/test/core/end2end/fuzzers/api_fuzzer_corpus/780fc96dea7f78bb9d1a074efbd966b03d78d653
new file mode 100644
index 0000000..56d52f3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/780fc96dea7f78bb9d1a074efbd966b03d78d653
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/783484ad9e15085e9039c7504aac71af1ad549a2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/783484ad9e15085e9039c7504aac71af1ad549a2
new file mode 100644
index 0000000..cdee9cf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/783484ad9e15085e9039c7504aac71af1ad549a2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/784ca396c157df8ba93bbe1e12c6d32609ef05a1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/784ca396c157df8ba93bbe1e12c6d32609ef05a1
new file mode 100644
index 0000000..d601edf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/784ca396c157df8ba93bbe1e12c6d32609ef05a1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/78e43d163fc8226d72b979c0fe6e1593ef3cb542 b/test/core/end2end/fuzzers/api_fuzzer_corpus/78e43d163fc8226d72b979c0fe6e1593ef3cb542
new file mode 100644
index 0000000..e3470ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/78e43d163fc8226d72b979c0fe6e1593ef3cb542
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/79163c87e1c3340d05799cf27f1e898a932d1001 b/test/core/end2end/fuzzers/api_fuzzer_corpus/79163c87e1c3340d05799cf27f1e898a932d1001
new file mode 100644
index 0000000..705aef2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/79163c87e1c3340d05799cf27f1e898a932d1001
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/795912f4ca380c73a3a3c956b1cba1e9051d92bf b/test/core/end2end/fuzzers/api_fuzzer_corpus/795912f4ca380c73a3a3c956b1cba1e9051d92bf
new file mode 100644
index 0000000..2972f6c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/795912f4ca380c73a3a3c956b1cba1e9051d92bf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7b3a99b69df9931fe12dfce5d8c5153f43bf4fd9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7b3a99b69df9931fe12dfce5d8c5153f43bf4fd9
new file mode 100644
index 0000000..561c5f7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7b3a99b69df9931fe12dfce5d8c5153f43bf4fd9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7b5a71e770bf9eed928f5e552a7659f8ad8a8b84 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7b5a71e770bf9eed928f5e552a7659f8ad8a8b84
new file mode 100644
index 0000000..3b5933e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7b5a71e770bf9eed928f5e552a7659f8ad8a8b84
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7cae7e5c67636a72a00785e04cc55af57b9e1318 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7cae7e5c67636a72a00785e04cc55af57b9e1318
new file mode 100644
index 0000000..be188e6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7cae7e5c67636a72a00785e04cc55af57b9e1318
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7e75ea44aa7347c2f827beecb27e3bf5b1907b8a b/test/core/end2end/fuzzers/api_fuzzer_corpus/7e75ea44aa7347c2f827beecb27e3bf5b1907b8a
new file mode 100644
index 0000000..c596373
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7e75ea44aa7347c2f827beecb27e3bf5b1907b8a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7fb64b5785ebe699ca50327c88c1d8b99432fa23 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7fb64b5785ebe699ca50327c88c1d8b99432fa23
new file mode 100644
index 0000000..21802ec
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7fb64b5785ebe699ca50327c88c1d8b99432fa23
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7ff449b555102deaeea7245b5a370dd0820d2691 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7ff449b555102deaeea7245b5a370dd0820d2691
new file mode 100644
index 0000000..d0e0587
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7ff449b555102deaeea7245b5a370dd0820d2691
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8005d0a23f43613949321e9fc761180cdcd569c8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8005d0a23f43613949321e9fc761180cdcd569c8
new file mode 100644
index 0000000..1a2385c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8005d0a23f43613949321e9fc761180cdcd569c8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/807a48bd33ce375438dbc158c1531891c5b54a51 b/test/core/end2end/fuzzers/api_fuzzer_corpus/807a48bd33ce375438dbc158c1531891c5b54a51
new file mode 100644
index 0000000..4fd3b4c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/807a48bd33ce375438dbc158c1531891c5b54a51
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/80d4266aee0b8b7dca74696dde949ebfaa052535 b/test/core/end2end/fuzzers/api_fuzzer_corpus/80d4266aee0b8b7dca74696dde949ebfaa052535
new file mode 100644
index 0000000..2658532
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/80d4266aee0b8b7dca74696dde949ebfaa052535
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/817570ac3bbeab63961d78aa2fef496e87c7e056 b/test/core/end2end/fuzzers/api_fuzzer_corpus/817570ac3bbeab63961d78aa2fef496e87c7e056
new file mode 100644
index 0000000..36adfeb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/817570ac3bbeab63961d78aa2fef496e87c7e056
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/823ef8523d3d3d90578d32e09e6822eb9ed42ecf b/test/core/end2end/fuzzers/api_fuzzer_corpus/823ef8523d3d3d90578d32e09e6822eb9ed42ecf
new file mode 100644
index 0000000..530dd55
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/823ef8523d3d3d90578d32e09e6822eb9ed42ecf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/826c36b53a0f249c139de4aec6fb113a70af3b6a b/test/core/end2end/fuzzers/api_fuzzer_corpus/826c36b53a0f249c139de4aec6fb113a70af3b6a
new file mode 100644
index 0000000..108f715
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/826c36b53a0f249c139de4aec6fb113a70af3b6a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/82731abc38788755495b1bac7b58bc0f12e4bdd1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/82731abc38788755495b1bac7b58bc0f12e4bdd1
new file mode 100644
index 0000000..20c7c70
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/82731abc38788755495b1bac7b58bc0f12e4bdd1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/835062d78983dae5747ab4e207d227869ce90733 b/test/core/end2end/fuzzers/api_fuzzer_corpus/835062d78983dae5747ab4e207d227869ce90733
new file mode 100644
index 0000000..1422c06
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/835062d78983dae5747ab4e207d227869ce90733
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/83776278a4997b0d178602c8419f3e6481dec01d b/test/core/end2end/fuzzers/api_fuzzer_corpus/83776278a4997b0d178602c8419f3e6481dec01d
new file mode 100644
index 0000000..2570ea8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/83776278a4997b0d178602c8419f3e6481dec01d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/837db5272d730107ae362fcd3cb2c21e5f1ea53e b/test/core/end2end/fuzzers/api_fuzzer_corpus/837db5272d730107ae362fcd3cb2c21e5f1ea53e
new file mode 100644
index 0000000..53d45b5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/837db5272d730107ae362fcd3cb2c21e5f1ea53e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/83a2a19743bb77278aba8cce1d04529d2cb0a744 b/test/core/end2end/fuzzers/api_fuzzer_corpus/83a2a19743bb77278aba8cce1d04529d2cb0a744
new file mode 100644
index 0000000..3bf333b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/83a2a19743bb77278aba8cce1d04529d2cb0a744
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/853a546c5435e9eb9f2d13898755abeaf93d51b1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/853a546c5435e9eb9f2d13898755abeaf93d51b1
new file mode 100644
index 0000000..6464ace
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/853a546c5435e9eb9f2d13898755abeaf93d51b1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8644486ad9579f43b8c6f34b423c2c1159b20a9a b/test/core/end2end/fuzzers/api_fuzzer_corpus/8644486ad9579f43b8c6f34b423c2c1159b20a9a
new file mode 100644
index 0000000..2bc1290
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8644486ad9579f43b8c6f34b423c2c1159b20a9a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/86906b52f5fdad0955f5a93dd26ff420e4a58078 b/test/core/end2end/fuzzers/api_fuzzer_corpus/86906b52f5fdad0955f5a93dd26ff420e4a58078
new file mode 100644
index 0000000..17b1b02
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/86906b52f5fdad0955f5a93dd26ff420e4a58078
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/87a34188d51bc8b43bd7d9097958097e70154960 b/test/core/end2end/fuzzers/api_fuzzer_corpus/87a34188d51bc8b43bd7d9097958097e70154960
new file mode 100644
index 0000000..a90fb52
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/87a34188d51bc8b43bd7d9097958097e70154960
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/87a4605e106399e71e689468a23ba11e7f17de2b b/test/core/end2end/fuzzers/api_fuzzer_corpus/87a4605e106399e71e689468a23ba11e7f17de2b
new file mode 100644
index 0000000..c9a66bd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/87a4605e106399e71e689468a23ba11e7f17de2b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/89cdf2f9a9682277284c24819a0cd336bbb04d60 b/test/core/end2end/fuzzers/api_fuzzer_corpus/89cdf2f9a9682277284c24819a0cd336bbb04d60
new file mode 100644
index 0000000..9501a65
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/89cdf2f9a9682277284c24819a0cd336bbb04d60
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8adec341bcbd14fb0bee52926141a4a5b3a885e2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8adec341bcbd14fb0bee52926141a4a5b3a885e2
new file mode 100644
index 0000000..270c4ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8adec341bcbd14fb0bee52926141a4a5b3a885e2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8b43d6ab6c1034fba9757ce801e237da089f1898 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b43d6ab6c1034fba9757ce801e237da089f1898
new file mode 100644
index 0000000..782654e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8b43d6ab6c1034fba9757ce801e237da089f1898
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8c00268431d8fb83ee306f0a49bee4af8728c0b0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c00268431d8fb83ee306f0a49bee4af8728c0b0
new file mode 100644
index 0000000..95211f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c00268431d8fb83ee306f0a49bee4af8728c0b0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8c5d9191880e9753a747e7ccd7824483bcd7568a b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c5d9191880e9753a747e7ccd7824483bcd7568a
new file mode 100644
index 0000000..de4f90e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8c5d9191880e9753a747e7ccd7824483bcd7568a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8cbb67da0e40816cf4bedf4fa6ce176563fc0487 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8cbb67da0e40816cf4bedf4fa6ce176563fc0487
new file mode 100644
index 0000000..aaded62
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8cbb67da0e40816cf4bedf4fa6ce176563fc0487
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8d54be1edc097b319d26ee1a08b1da06bafd0bbc b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d54be1edc097b319d26ee1a08b1da06bafd0bbc
new file mode 100644
index 0000000..020792a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8d54be1edc097b319d26ee1a08b1da06bafd0bbc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8dfdb04ef558fba84dcbfa65a6aa318b10988fa9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8dfdb04ef558fba84dcbfa65a6aa318b10988fa9
new file mode 100644
index 0000000..7e71dc6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8dfdb04ef558fba84dcbfa65a6aa318b10988fa9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8e49b880f6e9514963c8f82bc6c7131ab104200f b/test/core/end2end/fuzzers/api_fuzzer_corpus/8e49b880f6e9514963c8f82bc6c7131ab104200f
new file mode 100644
index 0000000..944d3e7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8e49b880f6e9514963c8f82bc6c7131ab104200f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8e6332b7d5234f6a1a153f91131ea33f0a5535d8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8e6332b7d5234f6a1a153f91131ea33f0a5535d8
new file mode 100644
index 0000000..c790e8c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8e6332b7d5234f6a1a153f91131ea33f0a5535d8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8ea9969bced02fd855c7de7edb12f074226f6dab b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ea9969bced02fd855c7de7edb12f074226f6dab
new file mode 100644
index 0000000..531ba64
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ea9969bced02fd855c7de7edb12f074226f6dab
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8efa9ad7c934a3c3cc01470ee1c21d7063f7b209 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8efa9ad7c934a3c3cc01470ee1c21d7063f7b209
new file mode 100644
index 0000000..c2dcd01
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8efa9ad7c934a3c3cc01470ee1c21d7063f7b209
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8f332e450d6a489fed2627f387cf0d0db7bacd37 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f332e450d6a489fed2627f387cf0d0db7bacd37
new file mode 100644
index 0000000..740dd57
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f332e450d6a489fed2627f387cf0d0db7bacd37
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8f71f51eba1aba1d839b19801c594eab968a892e b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f71f51eba1aba1d839b19801c594eab968a892e
new file mode 100644
index 0000000..ef4b4e1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f71f51eba1aba1d839b19801c594eab968a892e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8f840f0a04cce56098d395939b446589ee67da0c b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f840f0a04cce56098d395939b446589ee67da0c
new file mode 100644
index 0000000..d72b78c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8f840f0a04cce56098d395939b446589ee67da0c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8fba35a2ec8e2eb182eeacd23592c92932c64200 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8fba35a2ec8e2eb182eeacd23592c92932c64200
new file mode 100644
index 0000000..351f16a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8fba35a2ec8e2eb182eeacd23592c92932c64200
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/902ad49db6c0518017e8438d1ee61e0841fda6e7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/902ad49db6c0518017e8438d1ee61e0841fda6e7
new file mode 100644
index 0000000..586cd39
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/902ad49db6c0518017e8438d1ee61e0841fda6e7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/91236da3b95886937ab487700d8c72b40e6b9477 b/test/core/end2end/fuzzers/api_fuzzer_corpus/91236da3b95886937ab487700d8c72b40e6b9477
new file mode 100644
index 0000000..da27462
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/91236da3b95886937ab487700d8c72b40e6b9477
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/91491f410776eb726c8a5face925c703737ed916 b/test/core/end2end/fuzzers/api_fuzzer_corpus/91491f410776eb726c8a5face925c703737ed916
new file mode 100644
index 0000000..5adc950
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/91491f410776eb726c8a5face925c703737ed916
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/91980bd25cd4827c2e0c9ebb028d03ef226d0e73 b/test/core/end2end/fuzzers/api_fuzzer_corpus/91980bd25cd4827c2e0c9ebb028d03ef226d0e73
new file mode 100644
index 0000000..8510caa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/91980bd25cd4827c2e0c9ebb028d03ef226d0e73
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/92c816d98f9f8669f43b46b22d5da21464d9ef41 b/test/core/end2end/fuzzers/api_fuzzer_corpus/92c816d98f9f8669f43b46b22d5da21464d9ef41
new file mode 100644
index 0000000..c000647
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/92c816d98f9f8669f43b46b22d5da21464d9ef41
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/939a61533db8868591c514fc41c7dfb4232e3e4f b/test/core/end2end/fuzzers/api_fuzzer_corpus/939a61533db8868591c514fc41c7dfb4232e3e4f
new file mode 100644
index 0000000..c21081b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/939a61533db8868591c514fc41c7dfb4232e3e4f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/943924f902d02a4358ba2ae693087033d30e862b b/test/core/end2end/fuzzers/api_fuzzer_corpus/943924f902d02a4358ba2ae693087033d30e862b
new file mode 100644
index 0000000..c879d78
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/943924f902d02a4358ba2ae693087033d30e862b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/946f3ee9686789790301935574f412b9cf5cdeec b/test/core/end2end/fuzzers/api_fuzzer_corpus/946f3ee9686789790301935574f412b9cf5cdeec
new file mode 100644
index 0000000..a627547
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/946f3ee9686789790301935574f412b9cf5cdeec
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/958d48d95d2c2ff8b177ebd2149b9d9a89908f48 b/test/core/end2end/fuzzers/api_fuzzer_corpus/958d48d95d2c2ff8b177ebd2149b9d9a89908f48
new file mode 100644
index 0000000..14d8c6a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/958d48d95d2c2ff8b177ebd2149b9d9a89908f48
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/95e73caecc0ab06beaa9b84125adcb2e6eee2eff b/test/core/end2end/fuzzers/api_fuzzer_corpus/95e73caecc0ab06beaa9b84125adcb2e6eee2eff
new file mode 100644
index 0000000..67fecc0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/95e73caecc0ab06beaa9b84125adcb2e6eee2eff
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9625913195b7d7a5337016e8f9a29c8f3d6ad435 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9625913195b7d7a5337016e8f9a29c8f3d6ad435
new file mode 100644
index 0000000..26233fc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9625913195b7d7a5337016e8f9a29c8f3d6ad435
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/963c2fa0d8197bb8b6c7bbfcb43a9ae1ec29f2c7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/963c2fa0d8197bb8b6c7bbfcb43a9ae1ec29f2c7
new file mode 100644
index 0000000..3420d46
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/963c2fa0d8197bb8b6c7bbfcb43a9ae1ec29f2c7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/973f74081ad8c1d91ad1b0bfc10061de72d1b1bc b/test/core/end2end/fuzzers/api_fuzzer_corpus/973f74081ad8c1d91ad1b0bfc10061de72d1b1bc
new file mode 100644
index 0000000..ae0e4e3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/973f74081ad8c1d91ad1b0bfc10061de72d1b1bc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/974be67fe5188cfa77f7db943dfdaa0a4a2c4e82 b/test/core/end2end/fuzzers/api_fuzzer_corpus/974be67fe5188cfa77f7db943dfdaa0a4a2c4e82
new file mode 100644
index 0000000..c6f1c5a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/974be67fe5188cfa77f7db943dfdaa0a4a2c4e82
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/976ed70e538943fc60d5b339528c70a69161d6a1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/976ed70e538943fc60d5b339528c70a69161d6a1
new file mode 100644
index 0000000..21c265d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/976ed70e538943fc60d5b339528c70a69161d6a1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/97b87b4a9d1846c2f2277f7291c545be955257e3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/97b87b4a9d1846c2f2277f7291c545be955257e3
new file mode 100644
index 0000000..90c4026
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/97b87b4a9d1846c2f2277f7291c545be955257e3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/97d261c920f2802c97343e07847c98afa3ff46a3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/97d261c920f2802c97343e07847c98afa3ff46a3
new file mode 100644
index 0000000..2861755
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/97d261c920f2802c97343e07847c98afa3ff46a3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/97f7a51a0bb869d09f9f1bd7a4f93c5d859c89eb b/test/core/end2end/fuzzers/api_fuzzer_corpus/97f7a51a0bb869d09f9f1bd7a4f93c5d859c89eb
new file mode 100644
index 0000000..1bb271f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/97f7a51a0bb869d09f9f1bd7a4f93c5d859c89eb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/98a661d328f1ad6277c802604126d91965d6fda8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/98a661d328f1ad6277c802604126d91965d6fda8
new file mode 100644
index 0000000..ee68d20
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/98a661d328f1ad6277c802604126d91965d6fda8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9916b65305d28acf75a17495b9f44d7b839b948f b/test/core/end2end/fuzzers/api_fuzzer_corpus/9916b65305d28acf75a17495b9f44d7b839b948f
new file mode 100644
index 0000000..40a6dac
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9916b65305d28acf75a17495b9f44d7b839b948f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/99789b6e9a0932dc95b686cf380872175603918f b/test/core/end2end/fuzzers/api_fuzzer_corpus/99789b6e9a0932dc95b686cf380872175603918f
new file mode 100644
index 0000000..fe02035
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/99789b6e9a0932dc95b686cf380872175603918f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/99bb7db7244a6cb2bc0e6c275739f051f83b335a b/test/core/end2end/fuzzers/api_fuzzer_corpus/99bb7db7244a6cb2bc0e6c275739f051f83b335a
new file mode 100644
index 0000000..c14b6d8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/99bb7db7244a6cb2bc0e6c275739f051f83b335a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9b922c2b47217bbc8c91fce66fc666d626cee86a b/test/core/end2end/fuzzers/api_fuzzer_corpus/9b922c2b47217bbc8c91fce66fc666d626cee86a
new file mode 100644
index 0000000..1295369
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9b922c2b47217bbc8c91fce66fc666d626cee86a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9c052499ada417d5038f8cc7da62e6acae9ba9ae b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c052499ada417d5038f8cc7da62e6acae9ba9ae
new file mode 100644
index 0000000..ccee196
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c052499ada417d5038f8cc7da62e6acae9ba9ae
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9c78f9e53f09be45b2dac44dc8452880e7bed04b b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c78f9e53f09be45b2dac44dc8452880e7bed04b
new file mode 100644
index 0000000..ae93ae8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9c78f9e53f09be45b2dac44dc8452880e7bed04b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9ca8f5c67662fa6726db2680978e443d80785a9f b/test/core/end2end/fuzzers/api_fuzzer_corpus/9ca8f5c67662fa6726db2680978e443d80785a9f
new file mode 100644
index 0000000..4954b72
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9ca8f5c67662fa6726db2680978e443d80785a9f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9cc4eeecbb2df8b130cca5e455a0f6b8a6e00660 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9cc4eeecbb2df8b130cca5e455a0f6b8a6e00660
new file mode 100644
index 0000000..86f991e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9cc4eeecbb2df8b130cca5e455a0f6b8a6e00660
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9d43466b9c4b8736cde82e337d9a9f881db82d11 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d43466b9c4b8736cde82e337d9a9f881db82d11
new file mode 100644
index 0000000..0656982
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d43466b9c4b8736cde82e337d9a9f881db82d11
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9d5d9a28271a6d21850feb249cfe27aa0a31130c b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d5d9a28271a6d21850feb249cfe27aa0a31130c
new file mode 100644
index 0000000..c99b47e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9d5d9a28271a6d21850feb249cfe27aa0a31130c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9e273a94bf3c60f1c7875874c81d0b9309428752 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9e273a94bf3c60f1c7875874c81d0b9309428752
new file mode 100644
index 0000000..8c91bb1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9e273a94bf3c60f1c7875874c81d0b9309428752
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/9f1c4ea38c9fb86a62693f202b26b1be3c7b2d37 b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f1c4ea38c9fb86a62693f202b26b1be3c7b2d37
new file mode 100644
index 0000000..8f11fb5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/9f1c4ea38c9fb86a62693f202b26b1be3c7b2d37
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a1f59f79257ae56e6e6039d3fe838ca050f40385 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1f59f79257ae56e6e6039d3fe838ca050f40385
new file mode 100644
index 0000000..79bc6c9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a1f59f79257ae56e6e6039d3fe838ca050f40385
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a2180525f267c6d6b8f7501b100b97aef0d87f83 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a2180525f267c6d6b8f7501b100b97aef0d87f83
new file mode 100644
index 0000000..4a6f0c6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a2180525f267c6d6b8f7501b100b97aef0d87f83
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a270e4304cc0dcd2c67b78c0495dedb10419f0af b/test/core/end2end/fuzzers/api_fuzzer_corpus/a270e4304cc0dcd2c67b78c0495dedb10419f0af
new file mode 100644
index 0000000..733f4cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a270e4304cc0dcd2c67b78c0495dedb10419f0af
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a2d2b12575edfb559872c4f2ce63e95fdf68b774 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a2d2b12575edfb559872c4f2ce63e95fdf68b774
new file mode 100644
index 0000000..b948759
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a2d2b12575edfb559872c4f2ce63e95fdf68b774
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a31a10de37eda6db8ecc2270b6a368985a38a44b b/test/core/end2end/fuzzers/api_fuzzer_corpus/a31a10de37eda6db8ecc2270b6a368985a38a44b
new file mode 100644
index 0000000..3df44fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a31a10de37eda6db8ecc2270b6a368985a38a44b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a4da7f4642cfaf355445834075d3b4d04cf8b218 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a4da7f4642cfaf355445834075d3b4d04cf8b218
new file mode 100644
index 0000000..5c306ad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a4da7f4642cfaf355445834075d3b4d04cf8b218
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a5be9b0f094ec76d5f082f4e06dafb5a01c066c1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a5be9b0f094ec76d5f082f4e06dafb5a01c066c1
new file mode 100644
index 0000000..e64aae2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a5be9b0f094ec76d5f082f4e06dafb5a01c066c1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a62651154d1e5c33e154ea4b57f042be89feed9c b/test/core/end2end/fuzzers/api_fuzzer_corpus/a62651154d1e5c33e154ea4b57f042be89feed9c
new file mode 100644
index 0000000..56535f1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a62651154d1e5c33e154ea4b57f042be89feed9c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a65bda38b60ae084a5dcc3b616660aa338feef17 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a65bda38b60ae084a5dcc3b616660aa338feef17
new file mode 100644
index 0000000..cd75375
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a65bda38b60ae084a5dcc3b616660aa338feef17
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a6a11f05565197ecb9cbf3a2ddf826564b425e74 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a6a11f05565197ecb9cbf3a2ddf826564b425e74
new file mode 100644
index 0000000..2203ea0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a6a11f05565197ecb9cbf3a2ddf826564b425e74
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a71ab47d9ad32e10acc8b9772a331cae045fb424 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a71ab47d9ad32e10acc8b9772a331cae045fb424
new file mode 100644
index 0000000..0dd072b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a71ab47d9ad32e10acc8b9772a331cae045fb424
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a881a2dcd16f595644c1543ccf047b7ae5bb7fa4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a881a2dcd16f595644c1543ccf047b7ae5bb7fa4
new file mode 100644
index 0000000..cd6c17b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a881a2dcd16f595644c1543ccf047b7ae5bb7fa4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a8c0a166004ee637f22f5838960c8f4320738694 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8c0a166004ee637f22f5838960c8f4320738694
new file mode 100644
index 0000000..c654a53
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a8c0a166004ee637f22f5838960c8f4320738694
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a9e6f164e912d8964ae28f383dca6d980dcd4b94 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a9e6f164e912d8964ae28f383dca6d980dcd4b94
new file mode 100644
index 0000000..121daf9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a9e6f164e912d8964ae28f383dca6d980dcd4b94
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa05527f894960d22773d0e1c96e8ad9293e3910 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa05527f894960d22773d0e1c96e8ad9293e3910
new file mode 100644
index 0000000..6362b42
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa05527f894960d22773d0e1c96e8ad9293e3910
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa103991d1d90adf0af592c050c1d39532690f73 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa103991d1d90adf0af592c050c1d39532690f73
new file mode 100644
index 0000000..abf072f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa103991d1d90adf0af592c050c1d39532690f73
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa26dbb6bb031702e07e82a70162de89e31dbb60 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa26dbb6bb031702e07e82a70162de89e31dbb60
new file mode 100644
index 0000000..e5a8443
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa26dbb6bb031702e07e82a70162de89e31dbb60
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa2b2a1240b9ddfba14035695084096f93a4eea5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa2b2a1240b9ddfba14035695084096f93a4eea5
new file mode 100644
index 0000000..ba0fbce
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa2b2a1240b9ddfba14035695084096f93a4eea5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa58c60840b27f80a9779d2f4fc76154e12b7dc5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa58c60840b27f80a9779d2f4fc76154e12b7dc5
new file mode 100644
index 0000000..6dafb63
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa58c60840b27f80a9779d2f4fc76154e12b7dc5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa682b09b1e785fe0ed7edc6b14a4e8e5282e043 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa682b09b1e785fe0ed7edc6b14a4e8e5282e043
new file mode 100644
index 0000000..28028a3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa682b09b1e785fe0ed7edc6b14a4e8e5282e043
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aa7e9b09e36bec073300d107795b7dc63eafbeb9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa7e9b09e36bec073300d107795b7dc63eafbeb9
new file mode 100644
index 0000000..2209278
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aa7e9b09e36bec073300d107795b7dc63eafbeb9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/abd5de7b5e9218d19a57c47d2ccd6a1bc022c7fb b/test/core/end2end/fuzzers/api_fuzzer_corpus/abd5de7b5e9218d19a57c47d2ccd6a1bc022c7fb
new file mode 100644
index 0000000..5d8ebd3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/abd5de7b5e9218d19a57c47d2ccd6a1bc022c7fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/acb33ec3207ddd5f641f8f989faa888bcc70385c b/test/core/end2end/fuzzers/api_fuzzer_corpus/acb33ec3207ddd5f641f8f989faa888bcc70385c
new file mode 100644
index 0000000..4d14b56
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/acb33ec3207ddd5f641f8f989faa888bcc70385c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/adc78556e789c046d7f82b77e967a9e7fdf6cdac b/test/core/end2end/fuzzers/api_fuzzer_corpus/adc78556e789c046d7f82b77e967a9e7fdf6cdac
new file mode 100644
index 0000000..1934f3b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/adc78556e789c046d7f82b77e967a9e7fdf6cdac
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/adf88d50a752961142e1a3fc4eeba380e6089a5f b/test/core/end2end/fuzzers/api_fuzzer_corpus/adf88d50a752961142e1a3fc4eeba380e6089a5f
new file mode 100644
index 0000000..74f1f0c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/adf88d50a752961142e1a3fc4eeba380e6089a5f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/aed35edde0a0395829c43b45a34f537b9c6fc23a b/test/core/end2end/fuzzers/api_fuzzer_corpus/aed35edde0a0395829c43b45a34f537b9c6fc23a
new file mode 100644
index 0000000..1592e17
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/aed35edde0a0395829c43b45a34f537b9c6fc23a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/af9d0bbc10db557c0ef9ab55a6f217b4f76a87db b/test/core/end2end/fuzzers/api_fuzzer_corpus/af9d0bbc10db557c0ef9ab55a6f217b4f76a87db
new file mode 100644
index 0000000..de43084
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/af9d0bbc10db557c0ef9ab55a6f217b4f76a87db
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b09e64aa807db006a219bd1b9faf1a2e00dc6d33 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b09e64aa807db006a219bd1b9faf1a2e00dc6d33
new file mode 100644
index 0000000..50548fa
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b09e64aa807db006a219bd1b9faf1a2e00dc6d33
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b0c9bc430c79f064b61d8cad076b072c9c014804 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b0c9bc430c79f064b61d8cad076b072c9c014804
new file mode 100644
index 0000000..3b75171
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b0c9bc430c79f064b61d8cad076b072c9c014804
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b233e6287f4208a2ae8f89fe25caf0a33b7b4e51 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b233e6287f4208a2ae8f89fe25caf0a33b7b4e51
new file mode 100644
index 0000000..6ff2926
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b233e6287f4208a2ae8f89fe25caf0a33b7b4e51
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b36c3e5841c6aed7b0d439bd3b9c6d922d56c70b b/test/core/end2end/fuzzers/api_fuzzer_corpus/b36c3e5841c6aed7b0d439bd3b9c6d922d56c70b
new file mode 100644
index 0000000..4c5fc29
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b36c3e5841c6aed7b0d439bd3b9c6d922d56c70b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b39f27387a256019038cddb91f65651c01afb825 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b39f27387a256019038cddb91f65651c01afb825
new file mode 100644
index 0000000..a1e335b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b39f27387a256019038cddb91f65651c01afb825
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b4b0f04d9a771ea9575d9cc484947fcadf4ef5bd b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4b0f04d9a771ea9575d9cc484947fcadf4ef5bd
new file mode 100644
index 0000000..02e99ac
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b4b0f04d9a771ea9575d9cc484947fcadf4ef5bd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b501cbf4c085ce0b75e4031810bf99f91905fb06 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b501cbf4c085ce0b75e4031810bf99f91905fb06
new file mode 100644
index 0000000..6c4e46a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b501cbf4c085ce0b75e4031810bf99f91905fb06
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b53a90f0ad5e8026e0354e149ed8b4782fda00ad b/test/core/end2end/fuzzers/api_fuzzer_corpus/b53a90f0ad5e8026e0354e149ed8b4782fda00ad
new file mode 100644
index 0000000..59ba6f0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b53a90f0ad5e8026e0354e149ed8b4782fda00ad
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b55d66dbf3f2b795062e5a53379c2f63cab17062 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b55d66dbf3f2b795062e5a53379c2f63cab17062
new file mode 100644
index 0000000..c0464c3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b55d66dbf3f2b795062e5a53379c2f63cab17062
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b6f721156f8dc6a353555929e459e61bab8b394a b/test/core/end2end/fuzzers/api_fuzzer_corpus/b6f721156f8dc6a353555929e459e61bab8b394a
new file mode 100644
index 0000000..43986ea
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b6f721156f8dc6a353555929e459e61bab8b394a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b8845fbdf002c64053d7fa3e60add56f0a030992 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8845fbdf002c64053d7fa3e60add56f0a030992
new file mode 100644
index 0000000..b6823a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8845fbdf002c64053d7fa3e60add56f0a030992
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b88619bb22a3b2585cad3ace194fcdd8c6b63104 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b88619bb22a3b2585cad3ace194fcdd8c6b63104
new file mode 100644
index 0000000..903049d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b88619bb22a3b2585cad3ace194fcdd8c6b63104
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b8bc377e53ca54ae4e30f437b69e270040c35f65 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8bc377e53ca54ae4e30f437b69e270040c35f65
new file mode 100644
index 0000000..44934bb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b8bc377e53ca54ae4e30f437b69e270040c35f65
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b94e1db2cd1236075bb8772b72c64991d442e584 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b94e1db2cd1236075bb8772b72c64991d442e584
new file mode 100644
index 0000000..154e8b8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b94e1db2cd1236075bb8772b72c64991d442e584
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b9a7faa77ddf3a7e206e4d06f5d9d8de7d9c7df8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9a7faa77ddf3a7e206e4d06f5d9d8de7d9c7df8
new file mode 100644
index 0000000..e17d915
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9a7faa77ddf3a7e206e4d06f5d9d8de7d9c7df8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b9d799eb148e4d8a8a235e385ca8302a8acc3896 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9d799eb148e4d8a8a235e385ca8302a8acc3896
new file mode 100644
index 0000000..fb5a09d
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b9d799eb148e4d8a8a235e385ca8302a8acc3896
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/baee7b89cd2017f450c37137628688f25979b3bb b/test/core/end2end/fuzzers/api_fuzzer_corpus/baee7b89cd2017f450c37137628688f25979b3bb
new file mode 100644
index 0000000..aea662c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/baee7b89cd2017f450c37137628688f25979b3bb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/baf7b33805daf027e037e406d3442b3444108ac0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/baf7b33805daf027e037e406d3442b3444108ac0
new file mode 100644
index 0000000..230c450
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/baf7b33805daf027e037e406d3442b3444108ac0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bb426bb115461f351e57f64c0378e331f74ed5fc b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb426bb115461f351e57f64c0378e331f74ed5fc
new file mode 100644
index 0000000..12c6be1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bb426bb115461f351e57f64c0378e331f74ed5fc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bbb2429766a7c4ef9cb7110d567fd48cd6507dc5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bbb2429766a7c4ef9cb7110d567fd48cd6507dc5
new file mode 100644
index 0000000..017a477
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bbb2429766a7c4ef9cb7110d567fd48cd6507dc5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc330aa616a792ff22a8c7428dcdb4d99accbe4b b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc330aa616a792ff22a8c7428dcdb4d99accbe4b
new file mode 100644
index 0000000..a046eae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc330aa616a792ff22a8c7428dcdb4d99accbe4b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bc42e00a7d67fb68df3cb5893908c04884b6ad5e b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc42e00a7d67fb68df3cb5893908c04884b6ad5e
new file mode 100644
index 0000000..af4a348
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bc42e00a7d67fb68df3cb5893908c04884b6ad5e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bcc655cbb7334db02fc7fe9d29bd49fd6ee4ee91 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bcc655cbb7334db02fc7fe9d29bd49fd6ee4ee91
new file mode 100644
index 0000000..7d914ef
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bcc655cbb7334db02fc7fe9d29bd49fd6ee4ee91
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bd4f7f4d43ceaec0429ddc248cd438284813cc64 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd4f7f4d43ceaec0429ddc248cd438284813cc64
new file mode 100644
index 0000000..f509885
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bd4f7f4d43ceaec0429ddc248cd438284813cc64
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bed4e119b86e8dd0a6c60cb96cc2f9e66d0a8857 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bed4e119b86e8dd0a6c60cb96cc2f9e66d0a8857
new file mode 100644
index 0000000..ad1a137
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bed4e119b86e8dd0a6c60cb96cc2f9e66d0a8857
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bfafd0d497ccd035d6ef1478509c93a9d2443513 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bfafd0d497ccd035d6ef1478509c93a9d2443513
new file mode 100644
index 0000000..579f28c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bfafd0d497ccd035d6ef1478509c93a9d2443513
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/bfb3ae60341e80c10de105fa0f9a01f134033225 b/test/core/end2end/fuzzers/api_fuzzer_corpus/bfb3ae60341e80c10de105fa0f9a01f134033225
new file mode 100644
index 0000000..c5fdc4c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/bfb3ae60341e80c10de105fa0f9a01f134033225
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c1e5524945b3e3eabedfbb675be9e9ea99a36b94 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1e5524945b3e3eabedfbb675be9e9ea99a36b94
new file mode 100644
index 0000000..12bb8f2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c1e5524945b3e3eabedfbb675be9e9ea99a36b94
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c29f3256e632a713aeb3ef647fff014a9be01a8d b/test/core/end2end/fuzzers/api_fuzzer_corpus/c29f3256e632a713aeb3ef647fff014a9be01a8d
new file mode 100644
index 0000000..000e18c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c29f3256e632a713aeb3ef647fff014a9be01a8d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c41f43520da236f84dd0e2157644d316ca6fac37 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c41f43520da236f84dd0e2157644d316ca6fac37
new file mode 100644
index 0000000..17026cc
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c41f43520da236f84dd0e2157644d316ca6fac37
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c5535d6d801d315d78792c9956a82711d0d5a803 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5535d6d801d315d78792c9956a82711d0d5a803
new file mode 100644
index 0000000..1f779a6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5535d6d801d315d78792c9956a82711d0d5a803
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c6ec8562082eda6ea9ae1cc27f33b920b93589e4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c6ec8562082eda6ea9ae1cc27f33b920b93589e4
new file mode 100644
index 0000000..1b8ebd0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c6ec8562082eda6ea9ae1cc27f33b920b93589e4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c6f9e7ce30494ccbf3a1f49bed7107d976e3cc4e b/test/core/end2end/fuzzers/api_fuzzer_corpus/c6f9e7ce30494ccbf3a1f49bed7107d976e3cc4e
new file mode 100644
index 0000000..0091fd2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c6f9e7ce30494ccbf3a1f49bed7107d976e3cc4e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c71747c667c94062a03ec0f0468212e7ac222c57 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c71747c667c94062a03ec0f0468212e7ac222c57
new file mode 100644
index 0000000..cde0a42
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c71747c667c94062a03ec0f0468212e7ac222c57
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c767f1416feb8d7a2899ab276a4846e10f59531c b/test/core/end2end/fuzzers/api_fuzzer_corpus/c767f1416feb8d7a2899ab276a4846e10f59531c
new file mode 100644
index 0000000..7c1932f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c767f1416feb8d7a2899ab276a4846e10f59531c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c8b448134c9d165968599402c9633719573afd8d b/test/core/end2end/fuzzers/api_fuzzer_corpus/c8b448134c9d165968599402c9633719573afd8d
new file mode 100644
index 0000000..c13b096
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c8b448134c9d165968599402c9633719573afd8d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c955c8f169185554e8e1d45ded89db29c3164917 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c955c8f169185554e8e1d45ded89db29c3164917
new file mode 100644
index 0000000..0eb3d9c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c955c8f169185554e8e1d45ded89db29c3164917
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c9f81864507c264369dd22c72aeb16f1cb1742b0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c9f81864507c264369dd22c72aeb16f1cb1742b0
new file mode 100644
index 0000000..0331bad
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c9f81864507c264369dd22c72aeb16f1cb1742b0
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cb4f23427bca81db8ccf5f03bdb0c60418a20a74 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cb4f23427bca81db8ccf5f03bdb0c60418a20a74
new file mode 100644
index 0000000..39eb594
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cb4f23427bca81db8ccf5f03bdb0c60418a20a74
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cce1a22e2c3532ddb85af19d2f17cc7a11ca1050 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cce1a22e2c3532ddb85af19d2f17cc7a11ca1050
new file mode 100644
index 0000000..f2685ff
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cce1a22e2c3532ddb85af19d2f17cc7a11ca1050
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cd2b1fed5910041aca30e39210ee21d4ebb80469 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd2b1fed5910041aca30e39210ee21d4ebb80469
new file mode 100644
index 0000000..92e009a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd2b1fed5910041aca30e39210ee21d4ebb80469
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4ccfa79f65f31716296e690f3a76007edde2e3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4ccfa79f65f31716296e690f3a76007edde2e3
new file mode 100644
index 0000000..2a19daf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cd4ccfa79f65f31716296e690f3a76007edde2e3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ce4a157481d32f9c2ec106f257278d3159e6bd21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ce4a157481d32f9c2ec106f257278d3159e6bd21
new file mode 100644
index 0000000..dc0a837
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ce4a157481d32f9c2ec106f257278d3159e6bd21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ceb98039ba87c5c326c904f275490b25c7d90f1c b/test/core/end2end/fuzzers/api_fuzzer_corpus/ceb98039ba87c5c326c904f275490b25c7d90f1c
new file mode 100644
index 0000000..e6ac3a8
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ceb98039ba87c5c326c904f275490b25c7d90f1c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/cee29e303670fdd259d375da8345d6e49ba971b4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/cee29e303670fdd259d375da8345d6e49ba971b4
new file mode 100644
index 0000000..246dec4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/cee29e303670fdd259d375da8345d6e49ba971b4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960
new file mode 100644
index 0000000..70ca3a3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5834320218423296 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5834320218423296
new file mode 100644
index 0000000..65cc6a2
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5834320218423296
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-177af631195e806f4056847cea4d09b5eb28cf8a b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-177af631195e806f4056847cea4d09b5eb28cf8a
new file mode 100644
index 0000000..344825c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-177af631195e806f4056847cea4d09b5eb28cf8a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-373224be81ff98db60e9f81536f16a9ef92792d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-373224be81ff98db60e9f81536f16a9ef92792d5
new file mode 100644
index 0000000..bebaf9c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-373224be81ff98db60e9f81536f16a9ef92792d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-59b587d15c0bcdb985417cd7a133cecfcc232698 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-59b587d15c0bcdb985417cd7a133cecfcc232698
new file mode 100644
index 0000000..3fa8011
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-59b587d15c0bcdb985417cd7a133cecfcc232698
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5d73de981fb75553a7b2606e111716ee9f2af844 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5d73de981fb75553a7b2606e111716ee9f2af844
new file mode 100644
index 0000000..6c25c18
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5d73de981fb75553a7b2606e111716ee9f2af844
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5fc15c2ee9c70fd834588cbd256cfb52cdcbcb8d b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5fc15c2ee9c70fd834588cbd256cfb52cdcbcb8d
new file mode 100644
index 0000000..ce2ffbb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5fc15c2ee9c70fd834588cbd256cfb52cdcbcb8d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-60a3f7ed4abddaa6a7c837ace86d048fa15e288b b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-60a3f7ed4abddaa6a7c837ace86d048fa15e288b
new file mode 100644
index 0000000..3e441c9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-60a3f7ed4abddaa6a7c837ace86d048fa15e288b
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b208a1eb5ef9f229f309492329323f485768fa74 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b208a1eb5ef9f229f309492329323f485768fa74
new file mode 100644
index 0000000..e7a6aed
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b208a1eb5ef9f229f309492329323f485768fa74
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b5ae6881c767a7769bb957ac379f22aafe4ef05e b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b5ae6881c767a7769bb957ac379f22aafe4ef05e
new file mode 100644
index 0000000..3518dff
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b5ae6881c767a7769bb957ac379f22aafe4ef05e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d0a8deab4d26bc005d022184c311c1ce4d5327bb b/test/core/end2end/fuzzers/api_fuzzer_corpus/d0a8deab4d26bc005d022184c311c1ce4d5327bb
new file mode 100644
index 0000000..e6490ff
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d0a8deab4d26bc005d022184c311c1ce4d5327bb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d0d622fa3916e800e959a3fc2c90e213d518e5f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d0d622fa3916e800e959a3fc2c90e213d518e5f4
new file mode 100644
index 0000000..0de93e6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d0d622fa3916e800e959a3fc2c90e213d518e5f4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d123c89b3cafd995bf401032699fc7dba60f8de4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d123c89b3cafd995bf401032699fc7dba60f8de4
new file mode 100644
index 0000000..0c90e71
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d123c89b3cafd995bf401032699fc7dba60f8de4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d263d6004c2cc33cd9d157dd31ff604870c4d6fb b/test/core/end2end/fuzzers/api_fuzzer_corpus/d263d6004c2cc33cd9d157dd31ff604870c4d6fb
new file mode 100644
index 0000000..ca1f987
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d263d6004c2cc33cd9d157dd31ff604870c4d6fb
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d29859445bfeff04ca22b20408f9aa0e2e161abc b/test/core/end2end/fuzzers/api_fuzzer_corpus/d29859445bfeff04ca22b20408f9aa0e2e161abc
new file mode 100644
index 0000000..9177f89
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d29859445bfeff04ca22b20408f9aa0e2e161abc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d2ba1c23045223aa6f4c107f91d57786befae604 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2ba1c23045223aa6f4c107f91d57786befae604
new file mode 100644
index 0000000..94600a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2ba1c23045223aa6f4c107f91d57786befae604
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d2e66d1fdf0110212c632268aec5b06130db3e21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2e66d1fdf0110212c632268aec5b06130db3e21
new file mode 100644
index 0000000..e4fec6c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2e66d1fdf0110212c632268aec5b06130db3e21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d2f7c85e3c87ad5b71ad423aa4a9d97a8191d867 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2f7c85e3c87ad5b71ad423aa4a9d97a8191d867
new file mode 100644
index 0000000..4b5d543
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d2f7c85e3c87ad5b71ad423aa4a9d97a8191d867
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d4bd740db31b0e9925ce331c9c7d2fae5c1d15f2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d4bd740db31b0e9925ce331c9c7d2fae5c1d15f2
new file mode 100644
index 0000000..91e2851
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d4bd740db31b0e9925ce331c9c7d2fae5c1d15f2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d5dad7a599e22cff371d595a5014475301670892 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d5dad7a599e22cff371d595a5014475301670892
new file mode 100644
index 0000000..20b04dd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d5dad7a599e22cff371d595a5014475301670892
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d6b689f1b878d6914ced5d24f21c599c203594d4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/d6b689f1b878d6914ced5d24f21c599c203594d4
new file mode 100644
index 0000000..b26a7a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d6b689f1b878d6914ced5d24f21c599c203594d4
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/d716fb79cd7dd78d2ff66dc8a0e2acef9a93f98a b/test/core/end2end/fuzzers/api_fuzzer_corpus/d716fb79cd7dd78d2ff66dc8a0e2acef9a93f98a
new file mode 100644
index 0000000..1006f60
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/d716fb79cd7dd78d2ff66dc8a0e2acef9a93f98a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/da57f06258c4f0de07611263dfba8be669dd780c b/test/core/end2end/fuzzers/api_fuzzer_corpus/da57f06258c4f0de07611263dfba8be669dd780c
new file mode 100644
index 0000000..c6435f7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/da57f06258c4f0de07611263dfba8be669dd780c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/da97ec2d11daf27fe924513c463810c867b88983 b/test/core/end2end/fuzzers/api_fuzzer_corpus/da97ec2d11daf27fe924513c463810c867b88983
new file mode 100644
index 0000000..b293ff0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/da97ec2d11daf27fe924513c463810c867b88983
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/daed40229642eab256927f3bfb0288e036eab89f b/test/core/end2end/fuzzers/api_fuzzer_corpus/daed40229642eab256927f3bfb0288e036eab89f
new file mode 100644
index 0000000..a9903db
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/daed40229642eab256927f3bfb0288e036eab89f
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/db25df0fa146d02874114b8605000e0135ff12dd b/test/core/end2end/fuzzers/api_fuzzer_corpus/db25df0fa146d02874114b8605000e0135ff12dd
new file mode 100644
index 0000000..841f40f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/db25df0fa146d02874114b8605000e0135ff12dd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dcaa24f054af09a755c794ac4c3485ee682437a9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dcaa24f054af09a755c794ac4c3485ee682437a9
new file mode 100644
index 0000000..975d946
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dcaa24f054af09a755c794ac4c3485ee682437a9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dcc039d81106cd60cd611ff540d4669ebd10fe68 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dcc039d81106cd60cd611ff540d4669ebd10fe68
new file mode 100644
index 0000000..8c1536a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dcc039d81106cd60cd611ff540d4669ebd10fe68
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dd229da166c3bec675e882d17092238cf7d245f3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/dd229da166c3bec675e882d17092238cf7d245f3
new file mode 100644
index 0000000..2a994d9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dd229da166c3bec675e882d17092238cf7d245f3
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/dda7f9e8860f0e132312f57e3640402f33df308a b/test/core/end2end/fuzzers/api_fuzzer_corpus/dda7f9e8860f0e132312f57e3640402f33df308a
new file mode 100644
index 0000000..f530f36
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/dda7f9e8860f0e132312f57e3640402f33df308a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ddd34e967b1460902af2d01818605e208c5c7524 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ddd34e967b1460902af2d01818605e208c5c7524
new file mode 100644
index 0000000..c3d7d78
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ddd34e967b1460902af2d01818605e208c5c7524
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/de45c55043f63ec680e990b1edf1f0cc60ebbf4e b/test/core/end2end/fuzzers/api_fuzzer_corpus/de45c55043f63ec680e990b1edf1f0cc60ebbf4e
new file mode 100644
index 0000000..fab7ebb
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/de45c55043f63ec680e990b1edf1f0cc60ebbf4e
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/df29cf0d3cd5cfd27a98b506fffee64476398bba b/test/core/end2end/fuzzers/api_fuzzer_corpus/df29cf0d3cd5cfd27a98b506fffee64476398bba
new file mode 100644
index 0000000..d40b23c
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/df29cf0d3cd5cfd27a98b506fffee64476398bba
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e13344aeec0694c50eed41ae1b78e6d2ac4a4c6c b/test/core/end2end/fuzzers/api_fuzzer_corpus/e13344aeec0694c50eed41ae1b78e6d2ac4a4c6c
new file mode 100644
index 0000000..3be56d3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e13344aeec0694c50eed41ae1b78e6d2ac4a4c6c
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e37b4c7b64414d4705d934f8a723a50dcbf42571 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e37b4c7b64414d4705d934f8a723a50dcbf42571
new file mode 100644
index 0000000..bc13609
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e37b4c7b64414d4705d934f8a723a50dcbf42571
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e4068f14a046ce3ee7f1920cbd210b6e876c07ec b/test/core/end2end/fuzzers/api_fuzzer_corpus/e4068f14a046ce3ee7f1920cbd210b6e876c07ec
new file mode 100644
index 0000000..6ddb7d6
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e4068f14a046ce3ee7f1920cbd210b6e876c07ec
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e452ab01690d7e326f5ef52f4a312d066c087a24 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e452ab01690d7e326f5ef52f4a312d066c087a24
new file mode 100644
index 0000000..ff74e95
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e452ab01690d7e326f5ef52f4a312d066c087a24
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e52ac2e3cad2e544488a01822115cb37d10a76ce b/test/core/end2end/fuzzers/api_fuzzer_corpus/e52ac2e3cad2e544488a01822115cb37d10a76ce
new file mode 100644
index 0000000..b3bb240
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e52ac2e3cad2e544488a01822115cb37d10a76ce
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e609da99f76fa36e4b9060650cbc3597af458b01 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e609da99f76fa36e4b9060650cbc3597af458b01
new file mode 100644
index 0000000..9dac995
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e609da99f76fa36e4b9060650cbc3597af458b01
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e6b74f64e8bdfdf98177aee58b8729ff2aa7ffb2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e6b74f64e8bdfdf98177aee58b8729ff2aa7ffb2
new file mode 100644
index 0000000..cc01151
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e6b74f64e8bdfdf98177aee58b8729ff2aa7ffb2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e709e8861c09e29cdae73e337587a63fb0ccf76d b/test/core/end2end/fuzzers/api_fuzzer_corpus/e709e8861c09e29cdae73e337587a63fb0ccf76d
new file mode 100644
index 0000000..a481542
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e709e8861c09e29cdae73e337587a63fb0ccf76d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e839090caa1b1bfa8898eea683f5d5c9f1ed6dd1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e839090caa1b1bfa8898eea683f5d5c9f1ed6dd1
new file mode 100644
index 0000000..af332ba
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e839090caa1b1bfa8898eea683f5d5c9f1ed6dd1
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e97beccbdbb6e29eb476efec4ea2c96c310e6615 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e97beccbdbb6e29eb476efec4ea2c96c310e6615
new file mode 100644
index 0000000..1c33e4f
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e97beccbdbb6e29eb476efec4ea2c96c310e6615
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e9932127668f9de0743fc639dca31acedbfc68fd b/test/core/end2end/fuzzers/api_fuzzer_corpus/e9932127668f9de0743fc639dca31acedbfc68fd
new file mode 100644
index 0000000..62fe8fd
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e9932127668f9de0743fc639dca31acedbfc68fd
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e9d470cdf421f6c6c9eefd7f84bd09df6a8994b2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/e9d470cdf421f6c6c9eefd7f84bd09df6a8994b2
new file mode 100644
index 0000000..3d19da0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e9d470cdf421f6c6c9eefd7f84bd09df6a8994b2
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eacf4905e489566a3e5fcaaeac9fe91cbf916e06 b/test/core/end2end/fuzzers/api_fuzzer_corpus/eacf4905e489566a3e5fcaaeac9fe91cbf916e06
new file mode 100644
index 0000000..44f3e00
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eacf4905e489566a3e5fcaaeac9fe91cbf916e06
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eaddce3919388311104c50b9089461ff59c8ac14 b/test/core/end2end/fuzzers/api_fuzzer_corpus/eaddce3919388311104c50b9089461ff59c8ac14
new file mode 100644
index 0000000..d81c34e
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eaddce3919388311104c50b9089461ff59c8ac14
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ec55cbebe6db506acf7af9e5d26386630319623d b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec55cbebe6db506acf7af9e5d26386630319623d
new file mode 100644
index 0000000..14ebab0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec55cbebe6db506acf7af9e5d26386630319623d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ed47f70f76dadbb6744ede3eb7016f585c9fe59a b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed47f70f76dadbb6744ede3eb7016f585c9fe59a
new file mode 100644
index 0000000..be50868
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed47f70f76dadbb6744ede3eb7016f585c9fe59a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ed7d0b055e59602ec752162db7afc2b36ac7800a b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed7d0b055e59602ec752162db7afc2b36ac7800a
new file mode 100644
index 0000000..73c5db3
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ed7d0b055e59602ec752162db7afc2b36ac7800a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/edecc59c5809796f266abd8df4d5ecf6aae304ca b/test/core/end2end/fuzzers/api_fuzzer_corpus/edecc59c5809796f266abd8df4d5ecf6aae304ca
new file mode 100644
index 0000000..805106a
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/edecc59c5809796f266abd8df4d5ecf6aae304ca
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ee42f876c500996016a9f4a989147e5c2b5019fa b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee42f876c500996016a9f4a989147e5c2b5019fa
new file mode 100644
index 0000000..7977081
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee42f876c500996016a9f4a989147e5c2b5019fa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ee90aa84710c6a218a84b49ca6bc5d0e7a324220 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee90aa84710c6a218a84b49ca6bc5d0e7a324220
new file mode 100644
index 0000000..095b254
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee90aa84710c6a218a84b49ca6bc5d0e7a324220
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ef20d859b09ca00a80782df7097881ec4299cd25 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef20d859b09ca00a80782df7097881ec4299cd25
new file mode 100644
index 0000000..f4077be
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef20d859b09ca00a80782df7097881ec4299cd25
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ef24beeeff80ec8ad728919794e9de4a06cf7daa b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef24beeeff80ec8ad728919794e9de4a06cf7daa
new file mode 100644
index 0000000..39b8ac4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ef24beeeff80ec8ad728919794e9de4a06cf7daa
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/efa40f9e7f8a5ba4649dbad1a66ff9cc6bc699b8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/efa40f9e7f8a5ba4649dbad1a66ff9cc6bc699b8
new file mode 100644
index 0000000..8927909
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/efa40f9e7f8a5ba4649dbad1a66ff9cc6bc699b8
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f09c5cabe569b5c22a16d7d584074d54d9343edc b/test/core/end2end/fuzzers/api_fuzzer_corpus/f09c5cabe569b5c22a16d7d584074d54d9343edc
new file mode 100644
index 0000000..58644e1
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f09c5cabe569b5c22a16d7d584074d54d9343edc
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f1b2889ae7091d6a14332343fe7a2bffd81039a7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f1b2889ae7091d6a14332343fe7a2bffd81039a7
new file mode 100644
index 0000000..e7f2807
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f1b2889ae7091d6a14332343fe7a2bffd81039a7
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f2b838edb5715e9f0f73897ed74eddaede87a43a b/test/core/end2end/fuzzers/api_fuzzer_corpus/f2b838edb5715e9f0f73897ed74eddaede87a43a
new file mode 100644
index 0000000..bcffbae
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f2b838edb5715e9f0f73897ed74eddaede87a43a
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f3b3769d79f1d9586c575c27dff353f343ceacaf b/test/core/end2end/fuzzers/api_fuzzer_corpus/f3b3769d79f1d9586c575c27dff353f343ceacaf
new file mode 100644
index 0000000..034f198
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f3b3769d79f1d9586c575c27dff353f343ceacaf
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f3cad6a2ea4ebfd40568d4992d68784e82de2b20 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f3cad6a2ea4ebfd40568d4992d68784e82de2b20
new file mode 100644
index 0000000..7a5e86b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f3cad6a2ea4ebfd40568d4992d68784e82de2b20
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f503f8d526eaec9bab6cae97d09207deefa85d8d b/test/core/end2end/fuzzers/api_fuzzer_corpus/f503f8d526eaec9bab6cae97d09207deefa85d8d
new file mode 100644
index 0000000..6bdb2b0
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f503f8d526eaec9bab6cae97d09207deefa85d8d
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f575224a90d142bcd971b4f1634f4dc4988f8b15 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f575224a90d142bcd971b4f1634f4dc4988f8b15
new file mode 100644
index 0000000..b4e7db9
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f575224a90d142bcd971b4f1634f4dc4988f8b15
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f7623c34b3b5fb243fe589d881e4e8489f578f21 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7623c34b3b5fb243fe589d881e4e8489f578f21
new file mode 100644
index 0000000..46076b5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f7623c34b3b5fb243fe589d881e4e8489f578f21
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f875ad5830cb0b5d387a267e0200eb3027d025d5 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f875ad5830cb0b5d387a267e0200eb3027d025d5
new file mode 100644
index 0000000..dccc89b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f875ad5830cb0b5d387a267e0200eb3027d025d5
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f9048c4c18e729b6f49e929876ec30866deb16a9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f9048c4c18e729b6f49e929876ec30866deb16a9
new file mode 100644
index 0000000..7c90eda
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f9048c4c18e729b6f49e929876ec30866deb16a9
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f92897ee60bd24634aa1582f162c1c8f4b249148 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f92897ee60bd24634aa1582f162c1c8f4b249148
new file mode 100644
index 0000000..758adaf
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f92897ee60bd24634aa1582f162c1c8f4b249148
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb17c3fec47ab446ee737ab4c7fa8cb85688d5be b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb17c3fec47ab446ee737ab4c7fa8cb85688d5be
new file mode 100644
index 0000000..2deefec
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb17c3fec47ab446ee737ab4c7fa8cb85688d5be
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fc824337cead8b9e5229119c85c284fdd8e2d391 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc824337cead8b9e5229119c85c284fdd8e2d391
new file mode 100644
index 0000000..20ca7b5
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fc824337cead8b9e5229119c85c284fdd8e2d391
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fd05ad1a9d183c2a25d820aca9940caacbaa0660 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fd05ad1a9d183c2a25d820aca9940caacbaa0660
new file mode 100644
index 0000000..3261a7b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fd05ad1a9d183c2a25d820aca9940caacbaa0660
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fd4f7d5d3d21c75ccb5cde9491bf952bae753390 b/test/core/end2end/fuzzers/api_fuzzer_corpus/fd4f7d5d3d21c75ccb5cde9491bf952bae753390
new file mode 100644
index 0000000..fc7226b
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fd4f7d5d3d21c75ccb5cde9491bf952bae753390
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fe786c056e1e068e9cb9a94d7e10cee1593436bc b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe786c056e1e068e9cb9a94d7e10cee1593436bc
new file mode 100644
index 0000000..28b1302
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fe786c056e1e068e9cb9a94d7e10cee1593436bc
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer.c b/test/core/end2end/fuzzers/client_fuzzer.c
index ab708bc..e7e7dbe 100644
--- a/test/core/end2end/fuzzers/client_fuzzer.c
+++ b/test/core/end2end/fuzzers/client_fuzzer.c
@@ -37,6 +37,7 @@
 #include <grpc/support/alloc.h>
 
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/channel.h"
 #include "test/core/util/memory_counters.h"
 #include "test/core/util/mock_endpoint.h"
@@ -51,7 +52,7 @@
 static void dont_log(gpr_log_func_args *args) {}
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   struct grpc_memory_counters counters;
   if (squelch) gpr_set_log_function(dont_log);
   if (leak_check) grpc_memory_counters_init();
@@ -71,9 +72,10 @@
 
   grpc_channel *channel = grpc_channel_create(
       &exec_ctx, "test-target", NULL, GRPC_CLIENT_DIRECT_CHANNEL, transport);
-  grpc_call *call =
-      grpc_channel_create_call(channel, NULL, 0, cq, "/foo", "localhost",
-                               gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  grpc_slice host = grpc_slice_from_static_string("localhost");
+  grpc_call *call = grpc_channel_create_call(
+      channel, NULL, 0, cq, grpc_slice_from_static_string("/foo"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 
   grpc_metadata_array initial_metadata_recv;
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -81,8 +83,7 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_metadata_array_init(&trailing_metadata_recv);
   grpc_status_code status;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details = grpc_empty_slice();
 
   grpc_op ops[6];
   memset(ops, 0, sizeof(ops));
@@ -110,7 +111,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -155,7 +155,7 @@
   grpc_completion_queue_destroy(cq);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_channel_destroy(channel);
   if (response_payload_recv != NULL) {
     grpc_byte_buffer_destroy(response_payload_recv);
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/175f16901997fdee41ac9ec88f7e018d46d774e7 b/test/core/end2end/fuzzers/client_fuzzer_corpus/175f16901997fdee41ac9ec88f7e018d46d774e7
new file mode 100644
index 0000000..1cf8151
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/175f16901997fdee41ac9ec88f7e018d46d774e7
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/26f250ae38865f030176a8801ce992536351a326 b/test/core/end2end/fuzzers/client_fuzzer_corpus/26f250ae38865f030176a8801ce992536351a326
new file mode 100644
index 0000000..6c970a4
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/26f250ae38865f030176a8801ce992536351a326
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3233f2ab3b6c9431289ef7dc4f40676d0128bcad b/test/core/end2end/fuzzers/client_fuzzer_corpus/3233f2ab3b6c9431289ef7dc4f40676d0128bcad
new file mode 100644
index 0000000..64eef00
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3233f2ab3b6c9431289ef7dc4f40676d0128bcad
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3656614c7b0dc11d4dd7e1826f77fa96a88c420f b/test/core/end2end/fuzzers/client_fuzzer_corpus/3656614c7b0dc11d4dd7e1826f77fa96a88c420f
new file mode 100644
index 0000000..fb9667c
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3656614c7b0dc11d4dd7e1826f77fa96a88c420f
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/3dec1981e8677ec6ad2517feba29869d53f8d884 b/test/core/end2end/fuzzers/client_fuzzer_corpus/3dec1981e8677ec6ad2517feba29869d53f8d884
new file mode 100644
index 0000000..92ff8bc
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/3dec1981e8677ec6ad2517feba29869d53f8d884
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/4bed84590a55b06d7eb30d8faa4b00a881ba9b2c b/test/core/end2end/fuzzers/client_fuzzer_corpus/4bed84590a55b06d7eb30d8faa4b00a881ba9b2c
new file mode 100644
index 0000000..3e3365e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/4bed84590a55b06d7eb30d8faa4b00a881ba9b2c
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/591d46b83d2e6babc0ce3c753c4606a10c46d7ce b/test/core/end2end/fuzzers/client_fuzzer_corpus/591d46b83d2e6babc0ce3c753c4606a10c46d7ce
new file mode 100644
index 0000000..addaccb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/591d46b83d2e6babc0ce3c753c4606a10c46d7ce
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5a52d683c9342dd301b0e699db36175aad715e1d b/test/core/end2end/fuzzers/client_fuzzer_corpus/5a52d683c9342dd301b0e699db36175aad715e1d
new file mode 100644
index 0000000..e9e09a1
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5a52d683c9342dd301b0e699db36175aad715e1d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/5b7ff7c113c2bcf125271d22c937f758a0cd2ee4 b/test/core/end2end/fuzzers/client_fuzzer_corpus/5b7ff7c113c2bcf125271d22c937f758a0cd2ee4
new file mode 100644
index 0000000..2ccc02d
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/5b7ff7c113c2bcf125271d22c937f758a0cd2ee4
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/616e55354ba3517ce6762d6cd56600f97915e646 b/test/core/end2end/fuzzers/client_fuzzer_corpus/616e55354ba3517ce6762d6cd56600f97915e646
new file mode 100644
index 0000000..ccaeedb
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/616e55354ba3517ce6762d6cd56600f97915e646
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/7a9a12b15c798b88f1a599779f52d14edf9f4ef5 b/test/core/end2end/fuzzers/client_fuzzer_corpus/7a9a12b15c798b88f1a599779f52d14edf9f4ef5
new file mode 100644
index 0000000..05e8c39
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/7a9a12b15c798b88f1a599779f52d14edf9f4ef5
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8f05b8da748cc04e64b688c4b435fe64699bd481 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8f05b8da748cc04e64b688c4b435fe64699bd481
new file mode 100644
index 0000000..53a4403
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8f05b8da748cc04e64b688c4b435fe64699bd481
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/8fd758e2603f1e3772cfcd295ff0f951988d7648 b/test/core/end2end/fuzzers/client_fuzzer_corpus/8fd758e2603f1e3772cfcd295ff0f951988d7648
new file mode 100644
index 0000000..33a7bd8
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/8fd758e2603f1e3772cfcd295ff0f951988d7648
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9018925b5e791ae4b3ae9c84b8a4d47d86671c2d b/test/core/end2end/fuzzers/client_fuzzer_corpus/9018925b5e791ae4b3ae9c84b8a4d47d86671c2d
new file mode 100644
index 0000000..fccac2a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9018925b5e791ae4b3ae9c84b8a4d47d86671c2d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/9912de197918ac0e305f0c0107f863823e8ae818 b/test/core/end2end/fuzzers/client_fuzzer_corpus/9912de197918ac0e305f0c0107f863823e8ae818
new file mode 100644
index 0000000..5304b1e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/9912de197918ac0e305f0c0107f863823e8ae818
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ab90bebd4c017827a6d5de61511445df81169eb6 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ab90bebd4c017827a6d5de61511445df81169eb6
new file mode 100644
index 0000000..3cdcdf9
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ab90bebd4c017827a6d5de61511445df81169eb6
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/b26a3a83d0b319ce13a9ae164e90fa6da1b05a57 b/test/core/end2end/fuzzers/client_fuzzer_corpus/b26a3a83d0b319ce13a9ae164e90fa6da1b05a57
new file mode 100644
index 0000000..908355a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/b26a3a83d0b319ce13a9ae164e90fa6da1b05a57
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ba25be123c630bd3e4aeb9bda6304dd1a7e51365 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ba25be123c630bd3e4aeb9bda6304dd1a7e51365
new file mode 100644
index 0000000..1f1b88a
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ba25be123c630bd3e4aeb9bda6304dd1a7e51365
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c77ee0b6cb21ab7b7cf222c7f6563b3b1b1b6eed b/test/core/end2end/fuzzers/client_fuzzer_corpus/c77ee0b6cb21ab7b7cf222c7f6563b3b1b1b6eed
new file mode 100644
index 0000000..3f14a28
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c77ee0b6cb21ab7b7cf222c7f6563b3b1b1b6eed
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/c7b17d6ae5f3b155532a5a9bf0239c098c35eec1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/c7b17d6ae5f3b155532a5a9bf0239c098c35eec1
new file mode 100644
index 0000000..e0d5825
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/c7b17d6ae5f3b155532a5a9bf0239c098c35eec1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/ccc36ee2c6a0daad65a4d929599fda5cd38b8fd1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/ccc36ee2c6a0daad65a4d929599fda5cd38b8fd1
new file mode 100644
index 0000000..e612b05
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/ccc36ee2c6a0daad65a4d929599fda5cd38b8fd1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-133500314833c9037b34a4c34ad779dd78a0fa8d b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-133500314833c9037b34a4c34ad779dd78a0fa8d
new file mode 100644
index 0000000..e475765
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/crash-133500314833c9037b34a4c34ad779dd78a0fa8d
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/d3141a71cdaa7a0915c8c55abf2c940b0fd00172 b/test/core/end2end/fuzzers/client_fuzzer_corpus/d3141a71cdaa7a0915c8c55abf2c940b0fd00172
new file mode 100644
index 0000000..e2881da
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/d3141a71cdaa7a0915c8c55abf2c940b0fd00172
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/de9b9a35e1e7040e842b597b8d2fe4cd602e67f1 b/test/core/end2end/fuzzers/client_fuzzer_corpus/de9b9a35e1e7040e842b597b8d2fe4cd602e67f1
new file mode 100644
index 0000000..7b8d43e
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/de9b9a35e1e7040e842b597b8d2fe4cd602e67f1
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e5319a8570a762bbdd67135b49579097324e369a b/test/core/end2end/fuzzers/client_fuzzer_corpus/e5319a8570a762bbdd67135b49579097324e369a
new file mode 100644
index 0000000..128aef0
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e5319a8570a762bbdd67135b49579097324e369a
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/e5e276acd665ccb47f868fe3bc36e647bbb840bd b/test/core/end2end/fuzzers/client_fuzzer_corpus/e5e276acd665ccb47f868fe3bc36e647bbb840bd
new file mode 100644
index 0000000..05b14a7
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/e5e276acd665ccb47f868fe3bc36e647bbb840bd
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer_corpus/f69aa5666fd60c1b6814198f12d049abb0e9f148 b/test/core/end2end/fuzzers/client_fuzzer_corpus/f69aa5666fd60c1b6814198f12d049abb0e9f148
new file mode 100644
index 0000000..380bac2
--- /dev/null
+++ b/test/core/end2end/fuzzers/client_fuzzer_corpus/f69aa5666fd60c1b6814198f12d049abb0e9f148
Binary files differ
diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary
index 12db0ff..6b96785 100644
--- a/test/core/end2end/fuzzers/hpack.dictionary
+++ b/test/core/end2end/fuzzers/hpack.dictionary
@@ -1,24 +1,61 @@
 # hpack fuzzing dictionary
+"\x05:path"
+"\x07:method"
+"\x07:status"
+"\x0A:authority"
+"\x07:scheme"
+"\x02te"
+"\x0Cgrpc-message"
+"\x0Bgrpc-status"
+"\x10grpc-payload-bin"
+"\x0Dgrpc-encoding"
+"\x14grpc-accept-encoding"
+"\x0Ccontent-type"
+"\x1Egrpc-internal-encoding-request"
+"\x0Auser-agent"
+"\x04host"
+"\x08lb-token"
+"\x0Cgrpc-timeout"
+"\x10grpc-tracing-bin"
+"\x0Egrpc-stats-bin"
+"\x00"
+"\x13grpc.wait_for_ready"
+"\x0Cgrpc.timeout"
+"\x1Egrpc.max_request_message_bytes"
+"\x1Fgrpc.max_response_message_bytes"
+"$/grpc.lb.v1.LoadBalancer/BalanceLoad"
 "\x010"
 "\x011"
 "\x012"
+"\x08identity"
+"\x04gzip"
+"\x07deflate"
+"\x08trailers"
+"\x10application/grpc"
+"\x04POST"
 "\x03200"
+"\x03404"
+"\x04http"
+"\x05https"
+"\x04grpc"
+"\x03GET"
+"\x03PUT"
+"\x01/"
+"\x0B/index.html"
 "\x03204"
 "\x03206"
 "\x03304"
 "\x03400"
-"\x03404"
 "\x03500"
-"\x06accept"
 "\x0Eaccept-charset"
 "\x0Faccept-encoding"
+"\x0Dgzip, deflate"
 "\x0Faccept-language"
 "\x0Daccept-ranges"
+"\x06accept"
 "\x1Baccess-control-allow-origin"
 "\x03age"
 "\x05allow"
-"\x10application/grpc"
-"\x0A:authority"
 "\x0Dauthorization"
 "\x0Dcache-control"
 "\x13content-disposition"
@@ -27,81 +64,71 @@
 "\x0Econtent-length"
 "\x10content-location"
 "\x0Dcontent-range"
-"\x0Ccontent-type"
 "\x06cookie"
 "\x04date"
-"\x07deflate"
-"\x0Cdeflate,gzip"
-"\x00"
 "\x04etag"
 "\x06expect"
 "\x07expires"
 "\x04from"
-"\x03GET"
-"\x04grpc"
-"\x14grpc-accept-encoding"
-"\x0Dgrpc-encoding"
-"\x1Egrpc-internal-encoding-request"
-"\x0Cgrpc-message"
-"\x10grpc-payload-bin"
-"\x0Egrpc-stats-bin"
-"\x0Bgrpc-status"
-"\x0Cgrpc-timeout"
-"\x10grpc-tracing-bin"
-"\x04gzip"
-"\x0Dgzip, deflate"
-"\x04host"
-"\x04http"
-"\x05https"
-"\x08identity"
-"\x10identity,deflate"
-"\x15identity,deflate,gzip"
-"\x0Didentity,gzip"
 "\x08if-match"
 "\x11if-modified-since"
 "\x0Dif-none-match"
 "\x08if-range"
 "\x13if-unmodified-since"
 "\x0Dlast-modified"
-"\x0Blb-cost-bin"
-"\x08lb-token"
 "\x04link"
 "\x08location"
 "\x0Cmax-forwards"
-"\x07:method"
-"\x05:path"
-"\x04POST"
 "\x12proxy-authenticate"
 "\x13proxy-authorization"
-"\x03PUT"
 "\x05range"
 "\x07referer"
 "\x07refresh"
 "\x0Bretry-after"
-"\x07:scheme"
 "\x06server"
 "\x0Aset-cookie"
-"\x01/"
-"\x0B/index.html"
-"\x07:status"
 "\x19strict-transport-security"
-"\x02te"
-"\x08trailers"
 "\x11transfer-encoding"
-"\x0Auser-agent"
 "\x04vary"
 "\x03via"
 "\x10www-authenticate"
+"\x10identity,deflate"
+"\x0Didentity,gzip"
+"\x0Cdeflate,gzip"
+"\x15identity,deflate,gzip"
+"\x00\x0Bgrpc-status\x010"
+"\x00\x0Bgrpc-status\x011"
+"\x00\x0Bgrpc-status\x012"
+"\x00\x0Dgrpc-encoding\x08identity"
+"\x00\x0Dgrpc-encoding\x04gzip"
+"\x00\x0Dgrpc-encoding\x07deflate"
+"\x00\x02te\x08trailers"
+"\x00\x0Ccontent-type\x10application/grpc"
+"\x00\x07:method\x04POST"
+"\x00\x07:status\x03200"
+"\x00\x07:status\x03404"
+"\x00\x07:scheme\x04http"
+"\x00\x07:scheme\x05https"
+"\x00\x07:scheme\x04grpc"
+"\x00\x0A:authority\x00"
+"\x00\x07:method\x03GET"
+"\x00\x07:method\x03PUT"
+"\x00\x05:path\x01/"
+"\x00\x05:path\x0B/index.html"
+"\x00\x07:status\x03204"
+"\x00\x07:status\x03206"
+"\x00\x07:status\x03304"
+"\x00\x07:status\x03400"
+"\x00\x07:status\x03500"
 "\x00\x0Eaccept-charset\x00"
-"\x00\x06accept\x00"
 "\x00\x0Faccept-encoding\x00"
 "\x00\x0Faccept-encoding\x0Dgzip, deflate"
 "\x00\x0Faccept-language\x00"
 "\x00\x0Daccept-ranges\x00"
+"\x00\x06accept\x00"
 "\x00\x1Baccess-control-allow-origin\x00"
 "\x00\x03age\x00"
 "\x00\x05allow\x00"
-"\x00\x0A:authority\x00"
 "\x00\x0Dauthorization\x00"
 "\x00\x0Dcache-control\x00"
 "\x00\x13content-disposition\x00"
@@ -110,7 +137,6 @@
 "\x00\x0Econtent-length\x00"
 "\x00\x10content-location\x00"
 "\x00\x0Dcontent-range\x00"
-"\x00\x0Ccontent-type\x10application/grpc"
 "\x00\x0Ccontent-type\x00"
 "\x00\x06cookie\x00"
 "\x00\x04date\x00"
@@ -118,19 +144,6 @@
 "\x00\x06expect\x00"
 "\x00\x07expires\x00"
 "\x00\x04from\x00"
-"\x00\x14grpc-accept-encoding\x07deflate"
-"\x00\x14grpc-accept-encoding\x0Cdeflate,gzip"
-"\x00\x14grpc-accept-encoding\x04gzip"
-"\x00\x14grpc-accept-encoding\x08identity"
-"\x00\x14grpc-accept-encoding\x10identity,deflate"
-"\x00\x14grpc-accept-encoding\x15identity,deflate,gzip"
-"\x00\x14grpc-accept-encoding\x0Didentity,gzip"
-"\x00\x0Dgrpc-encoding\x07deflate"
-"\x00\x0Dgrpc-encoding\x04gzip"
-"\x00\x0Dgrpc-encoding\x08identity"
-"\x00\x0Bgrpc-status\x010"
-"\x00\x0Bgrpc-status\x011"
-"\x00\x0Bgrpc-status\x012"
 "\x00\x04host\x00"
 "\x00\x08if-match\x00"
 "\x00\x11if-modified-since\x00"
@@ -138,38 +151,28 @@
 "\x00\x08if-range\x00"
 "\x00\x13if-unmodified-since\x00"
 "\x00\x0Dlast-modified\x00"
-"\x00\x0Blb-cost-bin\x00"
 "\x00\x08lb-token\x00"
 "\x00\x04link\x00"
 "\x00\x08location\x00"
 "\x00\x0Cmax-forwards\x00"
-"\x00\x07:method\x03GET"
-"\x00\x07:method\x04POST"
-"\x00\x07:method\x03PUT"
-"\x00\x05:path\x01/"
-"\x00\x05:path\x0B/index.html"
 "\x00\x12proxy-authenticate\x00"
 "\x00\x13proxy-authorization\x00"
 "\x00\x05range\x00"
 "\x00\x07referer\x00"
 "\x00\x07refresh\x00"
 "\x00\x0Bretry-after\x00"
-"\x00\x07:scheme\x04grpc"
-"\x00\x07:scheme\x04http"
-"\x00\x07:scheme\x05https"
 "\x00\x06server\x00"
 "\x00\x0Aset-cookie\x00"
-"\x00\x07:status\x03200"
-"\x00\x07:status\x03204"
-"\x00\x07:status\x03206"
-"\x00\x07:status\x03304"
-"\x00\x07:status\x03400"
-"\x00\x07:status\x03404"
-"\x00\x07:status\x03500"
 "\x00\x19strict-transport-security\x00"
-"\x00\x02te\x08trailers"
 "\x00\x11transfer-encoding\x00"
 "\x00\x0Auser-agent\x00"
 "\x00\x04vary\x00"
 "\x00\x03via\x00"
 "\x00\x10www-authenticate\x00"
+"\x00\x14grpc-accept-encoding\x08identity"
+"\x00\x14grpc-accept-encoding\x07deflate"
+"\x00\x14grpc-accept-encoding\x10identity,deflate"
+"\x00\x14grpc-accept-encoding\x04gzip"
+"\x00\x14grpc-accept-encoding\x0Didentity,gzip"
+"\x00\x14grpc-accept-encoding\x0Cdeflate,gzip"
+"\x00\x14grpc-accept-encoding\x15identity,deflate,gzip"
diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c
index 115fb06..186542d 100644
--- a/test/core/end2end/fuzzers/server_fuzzer.c
+++ b/test/core/end2end/fuzzers/server_fuzzer.c
@@ -34,6 +34,7 @@
 #include <grpc/grpc.h>
 
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/memory_counters.h"
 #include "test/core/util/mock_endpoint.h"
@@ -49,7 +50,7 @@
 static void dont_log(gpr_log_func_args *args) {}
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   struct grpc_memory_counters counters;
   if (squelch) gpr_set_log_function(dont_log);
   if (leak_check) grpc_memory_counters_init();
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/084e9e02b8f2ed41ff9c22fef80e522e491227c5 b/test/core/end2end/fuzzers/server_fuzzer_corpus/084e9e02b8f2ed41ff9c22fef80e522e491227c5
new file mode 100644
index 0000000..dceac83
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/084e9e02b8f2ed41ff9c22fef80e522e491227c5
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/0c129f78eacfb0d0d3c89dd4e578724096a3cea0 b/test/core/end2end/fuzzers/server_fuzzer_corpus/0c129f78eacfb0d0d3c89dd4e578724096a3cea0
new file mode 100644
index 0000000..98fcc6d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/0c129f78eacfb0d0d3c89dd4e578724096a3cea0
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/129382aa11fa2922053fa47ba691dddb98901260 b/test/core/end2end/fuzzers/server_fuzzer_corpus/129382aa11fa2922053fa47ba691dddb98901260
new file mode 100644
index 0000000..aaab740
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/129382aa11fa2922053fa47ba691dddb98901260
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/1353e447b7b10fb3eabb02863a1fc5bc9bb50460 b/test/core/end2end/fuzzers/server_fuzzer_corpus/1353e447b7b10fb3eabb02863a1fc5bc9bb50460
new file mode 100644
index 0000000..80c0509
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/1353e447b7b10fb3eabb02863a1fc5bc9bb50460
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/3b55d09b98e3982d6f80913a792463c3974766db b/test/core/end2end/fuzzers/server_fuzzer_corpus/3b55d09b98e3982d6f80913a792463c3974766db
new file mode 100644
index 0000000..ef3d868
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/3b55d09b98e3982d6f80913a792463c3974766db
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/416160124b3b64fc9355f24dd789b3d1fd097b8b b/test/core/end2end/fuzzers/server_fuzzer_corpus/416160124b3b64fc9355f24dd789b3d1fd097b8b
new file mode 100644
index 0000000..896d760
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/416160124b3b64fc9355f24dd789b3d1fd097b8b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/47563391b73b6ef4bf987014c3e631fe2555a377 b/test/core/end2end/fuzzers/server_fuzzer_corpus/47563391b73b6ef4bf987014c3e631fe2555a377
new file mode 100644
index 0000000..ed9f1c8
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/47563391b73b6ef4bf987014c3e631fe2555a377
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6c0ec181e81b915071766762f5d78e9b1ccc9128 b/test/core/end2end/fuzzers/server_fuzzer_corpus/6c0ec181e81b915071766762f5d78e9b1ccc9128
new file mode 100644
index 0000000..e373c1e
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6c0ec181e81b915071766762f5d78e9b1ccc9128
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/6c66271b74a11f4e7065a6acbc86e4611e7e0dcc b/test/core/end2end/fuzzers/server_fuzzer_corpus/6c66271b74a11f4e7065a6acbc86e4611e7e0dcc
new file mode 100644
index 0000000..c4a5dd5
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/6c66271b74a11f4e7065a6acbc86e4611e7e0dcc
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/72db978194609ac138bca393650740a3eae8f448 b/test/core/end2end/fuzzers/server_fuzzer_corpus/72db978194609ac138bca393650740a3eae8f448
new file mode 100644
index 0000000..8d3023a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/72db978194609ac138bca393650740a3eae8f448
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/7df75412d12894fc501bd2d8493fe9e5a753ad88 b/test/core/end2end/fuzzers/server_fuzzer_corpus/7df75412d12894fc501bd2d8493fe9e5a753ad88
new file mode 100644
index 0000000..d2200a2
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/7df75412d12894fc501bd2d8493fe9e5a753ad88
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/92f1df2266f34a097e96dd22188d8633832d37b1 b/test/core/end2end/fuzzers/server_fuzzer_corpus/92f1df2266f34a097e96dd22188d8633832d37b1
new file mode 100644
index 0000000..16a928d
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/92f1df2266f34a097e96dd22188d8633832d37b1
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/947f53c0978672e59be452395670fa949a33cb4f b/test/core/end2end/fuzzers/server_fuzzer_corpus/947f53c0978672e59be452395670fa949a33cb4f
new file mode 100644
index 0000000..1c1f163
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/947f53c0978672e59be452395670fa949a33cb4f
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a40c3ba87b4206142b134f67485859b7c9b7c75c b/test/core/end2end/fuzzers/server_fuzzer_corpus/a40c3ba87b4206142b134f67485859b7c9b7c75c
new file mode 100644
index 0000000..6cc09b4
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a40c3ba87b4206142b134f67485859b7c9b7c75c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/a8305e9bb4a544eaef27e8bd21b4faabf524a84e b/test/core/end2end/fuzzers/server_fuzzer_corpus/a8305e9bb4a544eaef27e8bd21b4faabf524a84e
new file mode 100644
index 0000000..9476948
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/a8305e9bb4a544eaef27e8bd21b4faabf524a84e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/ac4e19c9fe290afc54bbb1e5f6cfe84a9c1f3c29 b/test/core/end2end/fuzzers/server_fuzzer_corpus/ac4e19c9fe290afc54bbb1e5f6cfe84a9c1f3c29
new file mode 100644
index 0000000..6fb218b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/ac4e19c9fe290afc54bbb1e5f6cfe84a9c1f3c29
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/ae297426638eb5a0611324f403c3189515274f1b b/test/core/end2end/fuzzers/server_fuzzer_corpus/ae297426638eb5a0611324f403c3189515274f1b
new file mode 100644
index 0000000..9540cb5
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/ae297426638eb5a0611324f403c3189515274f1b
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/b74dcd9c2780f145e09a27d2e03119576889a301 b/test/core/end2end/fuzzers/server_fuzzer_corpus/b74dcd9c2780f145e09a27d2e03119576889a301
new file mode 100644
index 0000000..ffe5b3b
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/b74dcd9c2780f145e09a27d2e03119576889a301
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/c39c0192d0d4f2b24f05c25a9e669cc091bff9e9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/c39c0192d0d4f2b24f05c25a9e669cc091bff9e9
new file mode 100644
index 0000000..0da0378
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/c39c0192d0d4f2b24f05c25a9e669cc091bff9e9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-73923add5066617ae08f187b79d2639b4fd96138 b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-73923add5066617ae08f187b79d2639b4fd96138
new file mode 100644
index 0000000..a06f3ce
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-73923add5066617ae08f187b79d2639b4fd96138
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-901723090ff2042ecc5a008ccd7ae0845c1681cb b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-901723090ff2042ecc5a008ccd7ae0845c1681cb
new file mode 100644
index 0000000..9f90983
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/crash-901723090ff2042ecc5a008ccd7ae0845c1681cb
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/d297b3f84e3dee9f74bf1162718aff66a11a7f5c b/test/core/end2end/fuzzers/server_fuzzer_corpus/d297b3f84e3dee9f74bf1162718aff66a11a7f5c
new file mode 100644
index 0000000..e619ae5
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/d297b3f84e3dee9f74bf1162718aff66a11a7f5c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/e021c5b9815f02ee9d1e5a003cbf3500e19db13c b/test/core/end2end/fuzzers/server_fuzzer_corpus/e021c5b9815f02ee9d1e5a003cbf3500e19db13c
new file mode 100644
index 0000000..a3ae822
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/e021c5b9815f02ee9d1e5a003cbf3500e19db13c
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fc162db40f87facb73cff20751e23af2e1f5296e b/test/core/end2end/fuzzers/server_fuzzer_corpus/fc162db40f87facb73cff20751e23af2e1f5296e
new file mode 100644
index 0000000..d63d69c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fc162db40f87facb73cff20751e23af2e1f5296e
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fcb1dea251d1ce74e30351f13a3f71e3debec3d2 b/test/core/end2end/fuzzers/server_fuzzer_corpus/fcb1dea251d1ce74e30351f13a3f71e3debec3d2
new file mode 100644
index 0000000..84d6c21
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fcb1dea251d1ce74e30351f13a3f71e3debec3d2
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/fe740f8c4ffd07f79456c8cee24ef556ee348f55 b/test/core/end2end/fuzzers/server_fuzzer_corpus/fe740f8c4ffd07f79456c8cee24ef556ee348f55
new file mode 100644
index 0000000..3391a83
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/fe740f8c4ffd07f79456c8cee24ef556ee348f55
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-03c6f209b2f144734c83d81ed452839d9e244fe9 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-03c6f209b2f144734c83d81ed452839d9e244fe9
new file mode 100644
index 0000000..f9ce44a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-03c6f209b2f144734c83d81ed452839d9e244fe9
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-129ecb5e7b80616f36791e3580844e520f2ba7d3 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-129ecb5e7b80616f36791e3580844e520f2ba7d3
new file mode 100644
index 0000000..b11defd
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-129ecb5e7b80616f36791e3580844e520f2ba7d3
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-30408c9d13f29804168fc62a0818cc894c6375ae b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-30408c9d13f29804168fc62a0818cc894c6375ae
new file mode 100644
index 0000000..0eff0f1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-30408c9d13f29804168fc62a0818cc894c6375ae
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-33d8bf197de7131be78244e10fbb0da5055cf266 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-33d8bf197de7131be78244e10fbb0da5055cf266
new file mode 100644
index 0000000..170119f
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-33d8bf197de7131be78244e10fbb0da5055cf266
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-51cdbfa3e97a46ceefde405e6ab087a109c26907 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-51cdbfa3e97a46ceefde405e6ab087a109c26907
new file mode 100644
index 0000000..aeecff3
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-51cdbfa3e97a46ceefde405e6ab087a109c26907
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-523cb1bca5ad56690c618b4ceac7fceca1113b9d b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-523cb1bca5ad56690c618b4ceac7fceca1113b9d
new file mode 100644
index 0000000..b725ec1
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-523cb1bca5ad56690c618b4ceac7fceca1113b9d
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a877fe99fd0e92721d162bc252bf72a4f67ba1ea b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a877fe99fd0e92721d162bc252bf72a4f67ba1ea
new file mode 100644
index 0000000..718794a
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a877fe99fd0e92721d162bc252bf72a4f67ba1ea
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bd9d24f5c7c915174b6ca9d1a3573e16e0edee12 b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bd9d24f5c7c915174b6ca9d1a3573e16e0edee12
new file mode 100644
index 0000000..fa1e6fa
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bd9d24f5c7c915174b6ca9d1a3573e16e0edee12
Binary files differ
diff --git a/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f3c688876395bf7a529f29f7b91532726cf5cbce b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f3c688876395bf7a529f29f7b91532726cf5cbce
new file mode 100644
index 0000000..b66722c
--- /dev/null
+++ b/test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f3c688876395bf7a529f29f7b91532726cf5cbce
Binary files differ
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index bcb7136..0c74953 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -91,6 +91,7 @@
 
 # maps test names to options
 END2END_TESTS = {
+    'authority_not_supported': default_test_options,
     'bad_hostname': default_test_options,
     'binary_metadata': default_test_options,
     'resource_quota_server': default_test_options._replace(large_writes=True,
@@ -118,6 +119,7 @@
     'high_initial_seqno': default_test_options,
     'idempotent_request': default_test_options,
     'invoke_large_request': default_test_options,
+    'keepalive_timeout': default_test_options._replace(proxyable=False),
     'large_metadata': default_test_options,
     'max_concurrent_streams': default_test_options._replace(proxyable=False),
     'max_message_length': default_test_options,
@@ -142,7 +144,6 @@
     'simple_request': default_test_options,
     'streaming_error_response': default_test_options,
     'trailing_metadata': default_test_options,
-    'authority_not_supported': default_test_options,
     'write_buffering': default_test_options,
     'write_buffering_at_end': default_test_options,
 }
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 95c06de..431c699 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -106,6 +106,7 @@
     'high_initial_seqno': test_options(),
     'idempotent_request': test_options(),
     'invoke_large_request': test_options(),
+    'keepalive_timeout': test_options(proxyable=False),
     'large_metadata': test_options(),
     'max_concurrent_streams': test_options(proxyable=False),
     'max_message_length': test_options(),
diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c
index 8e90464..a9634bf 100644
--- a/test/core/end2end/goaway_server_test.c
+++ b/test/core/end2end/goaway_server_test.c
@@ -107,8 +107,7 @@
   grpc_metadata_array request_metadata1;
   grpc_call_details request_details1;
   grpc_status_code status1;
-  char *details1 = NULL;
-  size_t details_capacity1 = 0;
+  grpc_slice details1;
   grpc_metadata_array_init(&trailing_metadata_recv1);
   grpc_metadata_array_init(&request_metadata1);
   grpc_call_details_init(&request_details1);
@@ -117,8 +116,7 @@
   grpc_metadata_array request_metadata2;
   grpc_call_details request_details2;
   grpc_status_code status2;
-  char *details2 = NULL;
-  size_t details_capacity2 = 0;
+  grpc_slice details2;
   grpc_metadata_array_init(&trailing_metadata_recv2);
   grpc_metadata_array_init(&request_metadata2);
   grpc_call_details_init(&request_details2);
@@ -143,9 +141,11 @@
   /* create a channel that picks first amongst the servers */
   grpc_channel *chan = grpc_insecure_channel_create("test", &client_args, NULL);
   /* and an initial call to them */
-  grpc_call *call1 = grpc_channel_create_call(
-      chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo", "127.0.0.1",
-      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20), NULL);
+  grpc_slice host = grpc_slice_from_static_string("127.0.0.1");
+  grpc_call *call1 =
+      grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+                               grpc_slice_from_static_string("/foo"), &host,
+                               grpc_timeout_seconds_to_deadline(20), NULL);
   /* send initial metadata to probe connectivity */
   memset(ops, 0, sizeof(ops));
   op = ops;
@@ -164,7 +164,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1;
   op->data.recv_status_on_client.status = &status1;
   op->data.recv_status_on_client.status_details = &details1;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity1;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -219,9 +218,10 @@
   cq_verify_empty(cqv);
 
   /* and a new call: should go through to server2 when we start it */
-  grpc_call *call2 = grpc_channel_create_call(
-      chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo", "127.0.0.1",
-      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20), NULL);
+  grpc_call *call2 =
+      grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+                               grpc_slice_from_static_string("/foo"), &host,
+                               grpc_timeout_seconds_to_deadline(20), NULL);
   /* send initial metadata to probe connectivity */
   memset(ops, 0, sizeof(ops));
   op = ops;
@@ -240,7 +240,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2;
   op->data.recv_status_on_client.status = &status2;
   op->data.recv_status_on_client.status_details = &details2;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity2;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -306,11 +305,11 @@
   grpc_metadata_array_destroy(&trailing_metadata_recv1);
   grpc_metadata_array_destroy(&request_metadata1);
   grpc_call_details_destroy(&request_details1);
-  gpr_free(details1);
+  grpc_slice_unref(details1);
   grpc_metadata_array_destroy(&trailing_metadata_recv2);
   grpc_metadata_array_destroy(&request_metadata2);
   grpc_call_details_destroy(&request_details2);
-  gpr_free(details2);
+  grpc_slice_unref(details2);
 
   cq_verifier_destroy(cqv);
   grpc_completion_queue_destroy(cq);
diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c
index 5ce7ca0..2a90725 100644
--- a/test/core/end2end/invalid_call_argument_test.c
+++ b/test/core/end2end/invalid_call_argument_test.c
@@ -56,8 +56,7 @@
   grpc_metadata_array initial_metadata_recv;
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
-  char *details;
-  size_t details_capacity;
+  grpc_slice details;
   grpc_call *server_call;
   grpc_server *server;
   grpc_metadata_array server_initial_metadata_recv;
@@ -73,20 +72,20 @@
   g_state.is_client = is_client;
   grpc_metadata_array_init(&g_state.initial_metadata_recv);
   grpc_metadata_array_init(&g_state.trailing_metadata_recv);
-  g_state.deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2);
+  g_state.deadline = grpc_timeout_seconds_to_deadline(2);
   g_state.cq = grpc_completion_queue_create(NULL);
   g_state.cqv = cq_verifier_create(g_state.cq);
-  g_state.details = NULL;
-  g_state.details_capacity = 0;
+  g_state.details = grpc_empty_slice();
   memset(g_state.ops, 0, sizeof(g_state.ops));
 
   if (is_client) {
     /* create a call, channel to a non existant server */
     g_state.chan =
         grpc_insecure_channel_create("nonexistant:54321", NULL, NULL);
+    grpc_slice host = grpc_slice_from_static_string("nonexistant");
     g_state.call = grpc_channel_create_call(
-        g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, "/Foo",
-        "nonexistant", g_state.deadline, NULL);
+        g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq,
+        grpc_slice_from_static_string("/Foo"), &host, g_state.deadline, NULL);
   } else {
     g_state.server = grpc_server_create(NULL, NULL);
     grpc_server_register_completion_queue(g_state.server, g_state.cq, NULL);
@@ -97,9 +96,10 @@
     gpr_join_host_port(&server_hostport, "localhost", port);
     g_state.chan = grpc_insecure_channel_create(server_hostport, NULL, NULL);
     gpr_free(server_hostport);
+    grpc_slice host = grpc_slice_from_static_string("bar");
     g_state.call = grpc_channel_create_call(
-        g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, "/Foo", "bar",
-        g_state.deadline, NULL);
+        g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq,
+        grpc_slice_from_static_string("/Foo"), &host, g_state.deadline, NULL);
     grpc_metadata_array_init(&g_state.server_initial_metadata_recv);
     grpc_call_details_init(&g_state.call_details);
     op = g_state.ops;
@@ -126,7 +126,7 @@
   grpc_call_destroy(g_state.call);
   cq_verifier_destroy(g_state.cqv);
   grpc_channel_destroy(g_state.chan);
-  gpr_free(g_state.details);
+  grpc_slice_unref(g_state.details);
   grpc_metadata_array_destroy(&g_state.initial_metadata_recv);
   grpc_metadata_array_destroy(&g_state.trailing_metadata_recv);
 
@@ -134,7 +134,7 @@
     grpc_call_destroy(g_state.server_call);
     grpc_server_shutdown_and_notify(g_state.server, g_state.cq, tag(1000));
     GPR_ASSERT(grpc_completion_queue_pluck(g_state.cq, tag(1000),
-                                           GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
+                                           grpc_timeout_seconds_to_deadline(5),
                                            NULL)
                    .type == GRPC_OP_COMPLETE);
     grpc_server_destroy(g_state.server);
@@ -289,7 +289,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -400,8 +401,6 @@
       &g_state.trailing_metadata_recv;
   op->data.recv_status_on_client.status = &g_state.status;
   op->data.recv_status_on_client.status_details = &g_state.details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &g_state.details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -416,7 +415,6 @@
   op->data.recv_status_on_client.trailing_metadata = NULL;
   op->data.recv_status_on_client.status = NULL;
   op->data.recv_status_on_client.status_details = NULL;
-  op->data.recv_status_on_client.status_details_capacity = NULL;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -455,8 +453,6 @@
       &g_state.trailing_metadata_recv;
   op->data.recv_status_on_client.status = &g_state.status;
   op->data.recv_status_on_client.status_details = &g_state.details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &g_state.details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -476,7 +472,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 1;
   op->reserved = NULL;
   op++;
@@ -497,7 +494,8 @@
   op->data.send_status_from_server.trailing_metadata_count =
       (size_t)INT_MAX + 1;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -517,14 +515,15 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -579,9 +578,8 @@
   gpr_log(GPR_INFO, "test_invalid_initial_metadata_reserved_key");
 
   grpc_metadata metadata;
-  metadata.key = ":start_with_colon";
-  metadata.value = "value";
-  metadata.value_length = 6;
+  metadata.key = grpc_slice_from_static_string(":start_with_colon");
+  metadata.value = grpc_slice_from_static_string("value");
 
   grpc_op *op;
   prepare_test(1);
@@ -601,6 +599,7 @@
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   grpc_init();
+  test_invalid_initial_metadata_reserved_key();
   test_non_null_reserved_on_start_batch();
   test_non_null_reserved_on_op();
   test_send_initial_metadata_more_than_once();
@@ -620,7 +619,6 @@
   test_send_server_status_twice();
   test_recv_close_on_server_with_invalid_flags();
   test_recv_close_on_server_twice();
-  test_invalid_initial_metadata_reserved_key();
   grpc_shutdown();
 
   return 0;
diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c
index 03ff70a..26d26d8 100644
--- a/test/core/end2end/no_server_test.c
+++ b/test/core/end2end/no_server_test.c
@@ -45,15 +45,14 @@
 int main(int argc, char **argv) {
   grpc_channel *chan;
   grpc_call *call;
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2);
   grpc_completion_queue *cq;
   cq_verifier *cqv;
   grpc_op ops[6];
   grpc_op *op;
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   grpc_test_init(argc, argv);
   grpc_init();
@@ -65,8 +64,10 @@
 
   /* create a call, channel to a non existant server */
   chan = grpc_insecure_channel_create("nonexistant:54321", NULL, NULL);
+  grpc_slice host = grpc_slice_from_static_string("nonexistant");
   call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/Foo", "nonexistant", deadline, NULL);
+                                  grpc_slice_from_static_string("/Foo"), &host,
+                                  deadline, NULL);
 
   memset(ops, 0, sizeof(ops));
   op = ops;
@@ -79,7 +80,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -101,7 +101,7 @@
   grpc_channel_destroy(chan);
   cq_verifier_destroy(cqv);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
   grpc_shutdown();
diff --git a/test/core/end2end/tests/authority_not_supported.c b/test/core/end2end/tests/authority_not_supported.c
index b9a1d88..7db2fd6 100644
--- a/test/core/end2end/tests/authority_not_supported.c
+++ b/test/core/end2end/tests/authority_not_supported.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -103,9 +103,14 @@
   grpc_byte_buffer *request_payload =
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
-  grpc_metadata meta_c[2] = {
-      {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f =
       begin_test(config, "test_with_authority_header", NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -116,11 +121,12 @@
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
   c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "foo.test.google.fr", deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -157,7 +163,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -169,7 +174,7 @@
 
   GPR_ASSERT(status == GRPC_STATUS_CANCELLED);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
diff --git a/test/core/end2end/tests/bad_hostname.c b/test/core/end2end/tests/bad_hostname.c
index 054a1f4..f50a580 100644
--- a/test/core/end2end/tests/bad_hostname.c
+++ b/test/core/end2end/tests/bad_hostname.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_client(&f, client_args);
   config.init_server(&f, server_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -109,11 +109,12 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
+  grpc_slice host = grpc_slice_from_static_string("slartibartfast.local");
   c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "slartibartfast.local", deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -141,7 +142,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -153,7 +153,7 @@
 
   GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/binary_metadata.c b/test/core/end2end/tests/binary_metadata.c
index 2b76cc2..7fb60f4 100644
--- a/test/core/end2end/tests/binary_metadata.c
+++ b/test/core/end2end/tests/binary_metadata.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -110,25 +110,25 @@
       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
   grpc_metadata meta_c[2] = {
-      {"key1-bin",
-       "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc",
-       13,
+      {grpc_slice_from_static_string("key1-bin"),
+       grpc_slice_from_static_string(
+           "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc"),
        0,
        {{NULL, NULL, NULL, NULL}}},
-      {"key2-bin",
-       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d",
-       14,
+      {grpc_slice_from_static_string("key2-bin"),
+       grpc_slice_from_static_string(
+           "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"),
        0,
        {{NULL, NULL, NULL, NULL}}}};
   grpc_metadata meta_s[2] = {
-      {"key3-bin",
-       "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee",
-       15,
+      {grpc_slice_from_static_string("key3-bin"),
+       grpc_slice_from_static_string(
+           "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee"),
        0,
        {{NULL, NULL, NULL, NULL}}},
-      {"key4-bin",
-       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
-       16,
+      {grpc_slice_from_static_string("key4-bin"),
+       grpc_slice_from_static_string(
+           "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"),
        0,
        {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
@@ -144,13 +144,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -190,7 +190,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -238,7 +237,7 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details =
+  grpc_slice status_string = grpc_slice_from_static_string(
       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12"
       "\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24"
       "\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36"
@@ -253,7 +252,8 @@
       "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
       "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea"
       "\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc"
-      "\xfd\xfe\xff";
+      "\xfd\xfe\xff");
+  op->data.send_status_from_server.status_details = &status_string;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -267,24 +267,25 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(
       0 ==
-      strcmp(details,
-             "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
-             "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
-             "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
-             "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
-             "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
-             "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
-             "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
-             "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
-             "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
-             "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
-             "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
-             "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
-             "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
-             "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
-             "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
-             "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+      grpc_slice_str_cmp(
+          details,
+          "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
+          "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
+          "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
+          "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
+          "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
+          "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
+          "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
+          "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
+          "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
+          "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
+          "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
+          "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
+          "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
+          "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
+          "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
+          "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
@@ -303,7 +304,7 @@
       &initial_metadata_recv, "key4-bin",
       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c
index cb0c215..38cba50 100644
--- a/test/core/end2end/tests/call_creds.c
+++ b/test/core/end2end/tests/call_creds.c
@@ -59,7 +59,7 @@
                                             const char *test_name,
                                             int fail_server_auth_check) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(NULL, NULL);
   config.init_client(&f, NULL);
   if (fail_server_auth_check) {
@@ -76,7 +76,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -92,7 +92,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -156,8 +156,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   grpc_call_credentials *creds = NULL;
   grpc_auth_context *s_auth_context = NULL;
@@ -167,8 +166,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
   creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL);
@@ -225,7 +225,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -284,7 +283,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -296,8 +296,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
@@ -337,7 +337,7 @@
       break;
   }
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -391,8 +391,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
       grpc_slice_from_copied_string("hello world");
@@ -404,8 +403,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -425,7 +425,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -468,7 +467,7 @@
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
 
diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c
index b14d9da..1a92aa4 100644
--- a/test/core/end2end/tests/cancel_after_accept.c
+++ b/test/core/end2end/tests/cancel_after_accept.c
@@ -43,6 +43,7 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/service_config.h"
 
@@ -56,7 +57,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -64,7 +65,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -80,7 +81,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -118,8 +119,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *request_payload_recv = NULL;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
@@ -154,8 +154,9 @@
   cq_verifier *cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/service/method",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/service/method"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -170,7 +171,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -246,7 +246,7 @@
   grpc_byte_buffer_destroy(response_payload);
   grpc_byte_buffer_destroy(request_payload_recv);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
   grpc_call_destroy(s);
diff --git a/test/core/end2end/tests/cancel_after_client_done.c b/test/core/end2end/tests/cancel_after_client_done.c
index b713278..0afeecb 100644
--- a/test/core/end2end/tests/cancel_after_client_done.c
+++ b/test/core/end2end/tests/cancel_after_client_done.c
@@ -51,7 +51,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -59,7 +59,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -75,7 +75,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -113,8 +113,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *request_payload_recv = NULL;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
@@ -128,8 +127,9 @@
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -144,7 +144,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -224,7 +223,7 @@
   grpc_byte_buffer_destroy(response_payload);
   grpc_byte_buffer_destroy(request_payload_recv);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
   grpc_call_destroy(s);
diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c
index b68f324..8a96ef2 100644
--- a/test/core/end2end/tests/cancel_after_invoke.c
+++ b/test/core/end2end/tests/cancel_after_invoke.c
@@ -52,7 +52,8 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s/%s", test_name, config.name, mode.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name,
+          mode.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +61,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +77,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -113,8 +114,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
       grpc_slice_from_copied_string("hello world");
@@ -122,8 +122,9 @@
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -138,7 +139,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -183,7 +183,7 @@
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
 
diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c
index 9174fcb..586aa7e 100644
--- a/test/core/end2end/tests/cancel_before_invoke.c
+++ b/test/core/end2end/tests/cancel_before_invoke.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -111,8 +111,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
       grpc_slice_from_copied_string("hello world");
@@ -120,8 +119,9 @@
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -138,7 +138,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -181,7 +180,7 @@
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
 
diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c
index 5be850b..bc462dd 100644
--- a/test/core/end2end/tests/cancel_in_a_vacuum.c
+++ b/test/core/end2end/tests/cancel_in_a_vacuum.c
@@ -51,7 +51,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -59,7 +59,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -75,7 +75,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -106,8 +106,9 @@
   cq_verifier *v_client = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c
index 071c078..7d03fe5 100644
--- a/test/core/end2end/tests/cancel_with_status.c
+++ b/test/core/end2end/tests/cancel_with_status.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -108,14 +108,14 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -128,7 +128,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -156,9 +155,9 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c
index f3b0625..7dd8c11 100644
--- a/test/core/end2end/tests/compressed_payload.c
+++ b/test/core/end2end/tests/compressed_payload.c
@@ -48,6 +48,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/call_test_only.h"
+#include "src/core/lib/transport/static_metadata.h"
 #include "test/core/end2end/cq_verifier.h"
 
 static void *tag(intptr_t t) { return (void *)t; }
@@ -57,7 +58,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -65,7 +66,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -81,7 +82,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -125,8 +126,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   cq_verifier *cqv;
   char str[1024];
@@ -151,8 +151,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -191,7 +192,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -245,13 +245,13 @@
   gpr_asprintf(&expected_details, "Compression algorithm '%s' is disabled.",
                algo_name);
   /* and we expect a specific reason for it */
-  GPR_ASSERT(0 == strcmp(details, expected_details));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details));
   gpr_free(expected_details);
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -305,8 +305,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   cq_verifier *cqv;
   char request_str[1024];
@@ -331,8 +330,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -362,7 +362,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -489,7 +488,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -503,13 +503,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -569,17 +569,14 @@
   grpc_metadata gzip_compression_override;
   grpc_metadata identity_compression_override;
 
-  gzip_compression_override.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
-  gzip_compression_override.value = "gzip";
-  gzip_compression_override.value_length =
-      strlen(gzip_compression_override.value);
+  gzip_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
+  gzip_compression_override.value = grpc_slice_from_static_string("gzip");
   memset(&gzip_compression_override.internal_data, 0,
          sizeof(gzip_compression_override.internal_data));
 
-  identity_compression_override.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
-  identity_compression_override.value = "identity";
-  identity_compression_override.value_length =
-      strlen(identity_compression_override.value);
+  identity_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
+  identity_compression_override.value =
+      grpc_slice_from_static_string("identity");
   memset(&identity_compression_override.internal_data, 0,
          sizeof(identity_compression_override.internal_data));
 
diff --git a/test/core/end2end/tests/connectivity.c b/test/core/end2end/tests/connectivity.c
index 42475c7..979419a 100644
--- a/test/core/end2end/tests/connectivity.c
+++ b/test/core/end2end/tests/connectivity.c
@@ -89,7 +89,7 @@
   /* channels should start life in IDLE, and stay there */
   GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) ==
              GRPC_CHANNEL_IDLE);
-  gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100));
+  gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
   GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) ==
              GRPC_CHANNEL_IDLE);
 
@@ -106,7 +106,7 @@
              GRPC_CHANNEL_IDLE);
   /* start watching for a change */
   grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE,
-                                        GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
+                                        grpc_timeout_seconds_to_deadline(3),
                                         f.cq, tag(2));
 
   /* and now the watch should trigger */
@@ -118,7 +118,7 @@
 
   /* quickly followed by a transition to TRANSIENT_FAILURE */
   grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_CONNECTING,
-                                        GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
+                                        grpc_timeout_seconds_to_deadline(3),
                                         f.cq, tag(3));
   CQ_EXPECT_COMPLETION(cqv, tag(3), 1);
   cq_verify(cqv);
@@ -137,7 +137,7 @@
      READY is reached */
   while (state != GRPC_CHANNEL_READY) {
     grpc_channel_watch_connectivity_state(
-        f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(4));
+        f.client, state, grpc_timeout_seconds_to_deadline(3), f.cq, tag(4));
     CQ_EXPECT_COMPLETION(cqv, tag(4), 1);
     cq_verify(cqv);
     state = grpc_channel_check_connectivity_state(f.client, 0);
@@ -151,7 +151,7 @@
   gpr_log(GPR_DEBUG, "*** SHUTTING DOWN SERVER ***");
 
   grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_READY,
-                                        GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
+                                        grpc_timeout_seconds_to_deadline(3),
                                         f.cq, tag(5));
 
   grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
diff --git a/test/core/end2end/tests/default_host.c b/test/core/end2end/tests/default_host.c
index 21dd04f..bc1829b 100644
--- a/test/core/end2end/tests/default_host.c
+++ b/test/core/end2end/tests/default_host.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_client(&f, client_args);
   config.init_server(&f, server_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -110,13 +110,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   char *peer;
 
   c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", NULL, deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), NULL,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -149,7 +149,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -182,7 +181,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -199,12 +199,12 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
-  GPR_ASSERT(0 == strncmp(call_details.host, "localhost", 9));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+  GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9));
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c
index 4fa0675..05440a6 100644
--- a/test/core/end2end/tests/disappearing_server.c
+++ b/test/core/end2end/tests/disappearing_server.c
@@ -46,7 +46,7 @@
 static void *tag(intptr_t t) { return (void *)t; }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -93,13 +93,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -128,7 +128,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -156,7 +155,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -174,13 +174,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -194,7 +194,8 @@
   grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
 
-  gpr_log(GPR_INFO, "%s/%s", "disappearing_server_test", config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", "disappearing_server_test",
+          config.name);
 
   config.init_client(&f, NULL);
   config.init_server(&f, NULL);
diff --git a/test/core/end2end/tests/empty_batch.c b/test/core/end2end/tests/empty_batch.c
index dc8e52a..50bb6b8 100644
--- a/test/core/end2end/tests/empty_batch.c
+++ b/test/core/end2end/tests/empty_batch.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -106,8 +106,9 @@
   grpc_op *op = NULL;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c
index 1ecf1ef..d2d6e82 100644
--- a/test/core/end2end/tests/filter_call_init_fails.c
+++ b/test/core/end2end/tests/filter_call_init_fails.c
@@ -58,7 +58,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -66,7 +66,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -82,7 +82,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -125,12 +125,12 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -165,7 +165,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -181,9 +180,9 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
-  GPR_ASSERT(0 == strcmp(details, "access denied"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -206,7 +205,7 @@
 
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"),
                             GRPC_ERROR_INT_GRPC_STATUS,
                             GRPC_STATUS_PERMISSION_DENIED);
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index 0991431..25e6065 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -55,7 +55,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -63,7 +63,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -79,7 +79,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -121,12 +121,12 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -161,7 +161,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -177,9 +176,10 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
-  GPR_ASSERT(0 == strcmp(details, "Failure that's not preventable."));
+  GPR_ASSERT(0 ==
+             grpc_slice_str_cmp(details, "Failure that's not preventable."));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -208,18 +208,12 @@
                           grpc_error *error) {
   grpc_call_element *elem = arg;
   call_data *calld = elem->call_data;
-  if (error == GRPC_ERROR_NONE) {
-    // close the stream with an error.
-    grpc_slice message =
-        grpc_slice_from_copied_string("Failure that's not preventable.");
-    grpc_transport_stream_op *op = grpc_make_transport_stream_op(NULL);
-    grpc_transport_stream_op_add_close(exec_ctx, op,
-                                       GRPC_STATUS_PERMISSION_DENIED, &message);
-    grpc_call_next_op(exec_ctx, elem, op);
-  }
   grpc_closure_sched(
       exec_ctx, calld->recv_im_ready,
-      GRPC_ERROR_CREATE_REFERENCING("Forced call to close", &error, 1));
+      grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING(
+                             "Failure that's not preventable.", &error, 1),
+                         GRPC_ERROR_INT_GRPC_STATUS,
+                         GRPC_STATUS_PERMISSION_DENIED));
 }
 
 static void start_transport_stream_op(grpc_exec_ctx *exec_ctx,
@@ -236,7 +230,7 @@
 
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   return GRPC_ERROR_NONE;
 }
 
diff --git a/test/core/end2end/tests/filter_latency.c b/test/core/end2end/tests/filter_latency.c
index 5f412e1..d05e9e7 100644
--- a/test/core/end2end/tests/filter_latency.c
+++ b/test/core/end2end/tests/filter_latency.c
@@ -62,7 +62,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -70,7 +70,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -86,7 +86,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -128,8 +128,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   gpr_mu_lock(&g_mu);
@@ -138,8 +137,10 @@
   gpr_mu_unlock(&g_mu);
   const gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC);
 
-  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "foo.test.google.fr", deadline, NULL);
+  c = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr", config), deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -173,7 +174,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -198,7 +198,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_string = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_string;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -215,9 +216,9 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -259,7 +260,7 @@
 
 static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
                                   grpc_call_element *elem,
-                                  grpc_call_element_args *args) {
+                                  const grpc_call_element_args *args) {
   return GRPC_ERROR_NONE;
 }
 
diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c
index 172618e..a3ad260 100644
--- a/test/core/end2end/tests/graceful_server_shutdown.c
+++ b/test/core/end2end/tests/graceful_server_shutdown.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -107,13 +107,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -143,7 +143,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -171,7 +170,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -191,12 +191,12 @@
   grpc_call_destroy(s);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/high_initial_seqno.c b/test/core/end2end/tests/high_initial_seqno.c
index bb981f7..cca8532 100644
--- a/test/core/end2end/tests/high_initial_seqno.c
+++ b/test/core/end2end/tests/high_initial_seqno.c
@@ -54,7 +54,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -62,7 +62,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -78,7 +78,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -113,13 +113,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -148,7 +148,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -172,7 +171,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -189,13 +189,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -233,7 +233,7 @@
   f = begin_test(config, name, &client_args, NULL);
   for (i = 0; i < 10; i++) {
     simple_request_body(config, f);
-    gpr_log(GPR_INFO, "Passed simple request %d", i);
+    gpr_log(GPR_INFO, "Running test: Passed simple request %d", i);
   }
   end_test(&f);
   config.tear_down_data(&f);
diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c
index ccb8f71..7601722 100644
--- a/test/core/end2end/tests/hpack_size.c
+++ b/test/core/end2end/tests/hpack_size.c
@@ -194,7 +194,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -202,7 +202,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -218,7 +218,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -254,24 +254,24 @@
   grpc_status_code status;
   grpc_call_error error;
   grpc_metadata extra_metadata[3];
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   memset(extra_metadata, 0, sizeof(extra_metadata));
-  extra_metadata[0].key = "hobbit-first-name";
-  extra_metadata[0].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][0];
-  extra_metadata[0].value_length = strlen(extra_metadata[0].value);
-  extra_metadata[1].key = "hobbit-second-name";
-  extra_metadata[1].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][1];
-  extra_metadata[1].value_length = strlen(extra_metadata[1].value);
-  extra_metadata[2].key = "dragon";
-  extra_metadata[2].value = dragons[index % GPR_ARRAY_SIZE(dragons)];
-  extra_metadata[2].value_length = strlen(extra_metadata[2].value);
+  extra_metadata[0].key = grpc_slice_from_static_string("hobbit-first-name");
+  extra_metadata[0].value = grpc_slice_from_static_string(
+      hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]);
+  extra_metadata[1].key = grpc_slice_from_static_string("hobbit-second-name");
+  extra_metadata[1].value = grpc_slice_from_static_string(
+      hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]);
+  extra_metadata[2].key = grpc_slice_from_static_string("dragon");
+  extra_metadata[2].value =
+      grpc_slice_from_static_string(dragons[index % GPR_ARRAY_SIZE(dragons)]);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -301,7 +301,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -325,7 +324,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -342,13 +342,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/idempotent_request.c b/test/core/end2end/tests/idempotent_request.c
index 475303e..cef2e10 100644
--- a/test/core/end2end/tests/idempotent_request.c
+++ b/test/core/end2end/tests/idempotent_request.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -111,14 +111,14 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   char *peer;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -152,7 +152,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -185,7 +184,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -202,14 +202,14 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c
index 10459a3..d799bd8 100644
--- a/test/core/end2end/tests/invoke_large_request.c
+++ b/test/core/end2end/tests/invoke_large_request.c
@@ -51,7 +51,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -59,7 +59,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static void drain_cq(grpc_completion_queue *cq) {
@@ -73,7 +73,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -140,13 +140,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -185,7 +185,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -232,7 +231,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -244,13 +244,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c
new file mode 100644
index 0000000..4296be3
--- /dev/null
+++ b/test/core/end2end/tests/keepalive_timeout.c
@@ -0,0 +1,240 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/support/env.h"
+#include "test/core/end2end/cq_verifier.h"
+
+static void *tag(intptr_t t) { return (void *)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char *test_name,
+                                            grpc_channel_args *client_args,
+                                            grpc_channel_args *server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  config.init_server(&f, server_args);
+  config.init_client(&f, client_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_time(int n) {
+  return grpc_timeout_seconds_to_deadline(n);
+}
+
+static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
+
+static void drain_cq(grpc_completion_queue *cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture *f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+  GPR_ASSERT(
+      grpc_completion_queue_pluck(f->cq, tag(1000), five_seconds_time(), NULL)
+          .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = NULL;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture *f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = NULL;
+}
+
+static void end_test(grpc_end2end_test_fixture *f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+}
+
+/* Client sends a request, server replies with a payload, then waits for the
+   keepalive watchdog timeouts before returning status. */
+static void test_keepalive_timeout(grpc_end2end_test_config config) {
+  grpc_call *c;
+  grpc_call *s;
+  grpc_slice response_payload_slice =
+      grpc_slice_from_copied_string("hello world");
+  grpc_byte_buffer *response_payload =
+      grpc_raw_byte_buffer_create(&response_payload_slice, 1);
+  gpr_timespec deadline = five_seconds_time();
+
+  grpc_arg keepalive_args[2];
+  keepalive_args[0].type = GRPC_ARG_INTEGER;
+  keepalive_args[0].key = GRPC_ARG_HTTP2_KEEPALIVE_TIME;
+  keepalive_args[0].value.integer = 2;
+  keepalive_args[1].type = GRPC_ARG_INTEGER;
+  keepalive_args[1].key = GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT;
+  keepalive_args[1].value.integer = 0;
+
+  grpc_channel_args *client_args = NULL;
+  client_args = grpc_channel_args_copy_and_add(client_args, keepalive_args, 2);
+
+  grpc_end2end_test_fixture f =
+      begin_test(config, "keepalive_timeout", client_args, NULL);
+  cq_verifier *cqv = cq_verifier_create(f.cq);
+  grpc_op ops[6];
+  grpc_op *op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_byte_buffer *response_payload_recv = NULL;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  grpc_slice details;
+
+  c = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
+      NULL);
+  GPR_ASSERT(c);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op++;
+  op->op = GRPC_OP_RECV_MESSAGE;
+  op->data.recv_message.recv_message = &response_payload_recv;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
+                                 f.server, &s, &call_details,
+                                 &request_metadata_recv, f.cq, f.cq, tag(101)));
+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+  cq_verify(cqv);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op++;
+  op->op = GRPC_OP_SEND_MESSAGE;
+  op->data.send_message.send_message = response_payload;
+  op++;
+  error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
+  cq_verify(cqv);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(3), 1);
+  cq_verify(cqv);
+
+  char *details_str = grpc_slice_to_c_string(details);
+  char *method_str = grpc_slice_to_c_string(call_details.method);
+  GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "keepalive watchdog timeout"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
+                                config);
+
+  gpr_free(details_str);
+  gpr_free(method_str);
+
+  grpc_slice_unref(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  grpc_call_destroy(c);
+  grpc_call_destroy(s);
+
+  cq_verifier_destroy(cqv);
+
+  grpc_byte_buffer_destroy(response_payload);
+  grpc_byte_buffer_destroy(response_payload_recv);
+
+  if (client_args != NULL) {
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_channel_args_destroy(&exec_ctx, client_args);
+    grpc_exec_ctx_finish(&exec_ctx);
+  }
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+void keepalive_timeout(grpc_end2end_test_config config) {
+  test_keepalive_timeout(config);
+}
+
+void keepalive_timeout_pre_init(void) {}
diff --git a/test/core/end2end/tests/large_metadata.c b/test/core/end2end/tests/large_metadata.c
index 2a7f49c..ac4c0e7 100644
--- a/test/core/end2end/tests/large_metadata.c
+++ b/test/core/end2end/tests/large_metadata.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -122,21 +122,19 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
-  meta.key = "key";
-  meta.value = gpr_malloc(large_size + 1);
-  memset((char *)meta.value, 'a', large_size);
-  ((char *)meta.value)[large_size] = 0;
-  meta.value_length = large_size;
+  meta.key = grpc_slice_from_static_string("key");
+  meta.value = grpc_slice_malloc(large_size);
+  memset(GRPC_SLICE_START_PTR(meta.value), 'a', large_size);
 
   grpc_metadata_array_init(&initial_metadata_recv);
   grpc_metadata_array_init(&trailing_metadata_recv);
@@ -170,7 +168,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -216,7 +213,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -228,15 +226,17 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
-  GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value));
+  GPR_ASSERT(contains_metadata_slices(&request_metadata_recv,
+                                      grpc_slice_from_static_string("key"),
+                                      meta.value));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -250,7 +250,7 @@
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(request_payload_recv);
 
-  gpr_free((char *)meta.value);
+  grpc_slice_unref(meta.value);
 
   end_test(&f);
   config.tear_down_data(&f);
diff --git a/test/core/end2end/tests/load_reporting_hook.c b/test/core/end2end/tests/load_reporting_hook.c
index c8de069..d1ee26f 100644
--- a/test/core/end2end/tests/load_reporting_hook.c
+++ b/test/core/end2end/tests/load_reporting_hook.c
@@ -31,23 +31,24 @@
  *
  */
 
-#include "test/core/end2end/end2end_tests.h"
-
 #include <string.h>
 
 #include <grpc/byte_buffer.h>
+#include <grpc/load_reporting.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
-#include "test/core/end2end/cq_verifier.h"
 
 #include "src/core/ext/load_reporting/load_reporting.h"
 #include "src/core/ext/load_reporting/load_reporting_filter.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/transport/static_metadata.h"
 
+#include "test/core/end2end/cq_verifier.h"
+#include "test/core/end2end/end2end_tests.h"
+
 enum { TIMEOUT = 200000 };
 
 static void *tag(intptr_t t) { return (void *)t; }
@@ -74,7 +75,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
 
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
@@ -84,7 +85,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -100,7 +101,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -124,7 +125,8 @@
 static void request_response_with_payload(
     grpc_end2end_test_config config, grpc_end2end_test_fixture f,
     const char *method_name, const char *request_msg, const char *response_msg,
-    grpc_metadata *initial_lr_metadata, grpc_metadata *trailing_lr_metadata) {
+    grpc_metadata *initial_lr_metadata,
+    grpc_load_reporting_cost_context *cost_ctx) {
   grpc_slice request_payload_slice = grpc_slice_from_static_string(request_msg);
   grpc_slice response_payload_slice =
       grpc_slice_from_static_string(response_msg);
@@ -146,13 +148,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, method_name,
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string(method_name),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -193,7 +195,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -238,11 +239,11 @@
   op->reserved = NULL;
   op++;
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
-  GPR_ASSERT(trailing_lr_metadata != NULL);
-  op->data.send_status_from_server.trailing_metadata_count = 1;
-  op->data.send_status_from_server.trailing_metadata = trailing_lr_metadata;
+  GPR_ASSERT(cost_ctx != NULL);
+  grpc_call_set_load_reporting_cost_context(s, cost_ctx);
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -255,7 +256,7 @@
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -293,23 +294,21 @@
   const char *response_msg = "... and the response from the server";
 
   grpc_metadata initial_lr_metadata;
-  grpc_metadata trailing_lr_metadata;
 
-  initial_lr_metadata.key = GRPC_LB_TOKEN_MD_KEY;
-  initial_lr_metadata.value = "client-token";
-  initial_lr_metadata.value_length = strlen(initial_lr_metadata.value);
+  initial_lr_metadata.key = GRPC_MDSTR_LB_TOKEN;
+  initial_lr_metadata.value = grpc_slice_from_static_string("client-token");
   memset(&initial_lr_metadata.internal_data, 0,
          sizeof(initial_lr_metadata.internal_data));
 
-  trailing_lr_metadata.key = GRPC_LB_COST_MD_KEY;
-  trailing_lr_metadata.value = "server-token";
-  trailing_lr_metadata.value_length = strlen(trailing_lr_metadata.value);
-  memset(&trailing_lr_metadata.internal_data, 0,
-         sizeof(trailing_lr_metadata.internal_data));
+  grpc_load_reporting_cost_context *cost_ctx = gpr_malloc(sizeof(*cost_ctx));
+  memset(cost_ctx, 0, sizeof(*cost_ctx));
+  cost_ctx->values_count = 1;
+  cost_ctx->values =
+      gpr_malloc(sizeof(*cost_ctx->values) * cost_ctx->values_count);
+  cost_ctx->values[0] = grpc_slice_from_static_string("cost-token");
 
   request_response_with_payload(config, f, method_name, request_msg,
-                                response_msg, &initial_lr_metadata,
-                                &trailing_lr_metadata);
+                                response_msg, &initial_lr_metadata, cost_ctx);
   end_test(&f);
   {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c
index 4582178..e81a628 100644
--- a/test/core/end2end/tests/max_concurrent_streams.c
+++ b/test/core/end2end/tests/max_concurrent_streams.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -109,13 +109,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -144,7 +144,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -168,7 +167,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -185,13 +185,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -223,11 +223,9 @@
   grpc_metadata_array trailing_metadata_recv2;
   grpc_status_code status1;
   grpc_call_error error;
-  char *details1 = NULL;
-  size_t details_capacity1 = 0;
+  grpc_slice details1;
   grpc_status_code status2;
-  char *details2 = NULL;
-  size_t details_capacity2 = 0;
+  grpc_slice details2;
   grpc_op ops[6];
   grpc_op *op;
   int was_cancelled;
@@ -261,13 +259,15 @@
      the first completes */
   deadline = n_seconds_time(1000);
   c1 = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/alpha",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/alpha"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c1);
   c2 = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/beta",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/beta"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c2);
 
@@ -295,7 +295,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1;
   op->data.recv_status_on_client.status = &status1;
   op->data.recv_status_on_client.status_details = &details1;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity1;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -328,7 +327,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2;
   op->data.recv_status_on_client.status = &status2;
   op->data.recv_status_on_client.status_details = &details2;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity2;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -345,7 +343,7 @@
   got_server_start = 0;
   live_call = -1;
   while (!got_client_start || !got_server_start) {
-    ev = grpc_completion_queue_next(f.cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3),
+    ev = grpc_completion_queue_next(f.cq, grpc_timeout_seconds_to_deadline(3),
                                     NULL);
     GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
     GPR_ASSERT(ev.success);
@@ -380,7 +378,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -394,6 +393,8 @@
   CQ_EXPECT_COMPLETION(cqv, tag(live_call + 1), 1);
   cq_verify(cqv);
 
+  grpc_call_details_destroy(&call_details);
+
   GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
                                  f.server, &s2, &call_details,
                                  &request_metadata_recv, f.cq, f.cq, tag(201)));
@@ -415,7 +416,7 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -433,8 +434,394 @@
   grpc_call_destroy(c2);
   grpc_call_destroy(s2);
 
-  gpr_free(details1);
-  gpr_free(details2);
+  grpc_slice_unref(details1);
+  grpc_slice_unref(details2);
+  grpc_metadata_array_destroy(&initial_metadata_recv1);
+  grpc_metadata_array_destroy(&trailing_metadata_recv1);
+  grpc_metadata_array_destroy(&initial_metadata_recv2);
+  grpc_metadata_array_destroy(&trailing_metadata_recv2);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+static void test_max_concurrent_streams_with_timeout_on_first(
+    grpc_end2end_test_config config) {
+  grpc_end2end_test_fixture f;
+  grpc_arg server_arg;
+  grpc_channel_args server_args;
+  grpc_call *c1;
+  grpc_call *c2;
+  grpc_call *s1;
+  grpc_call *s2;
+  cq_verifier *cqv;
+  grpc_call_details call_details;
+  grpc_metadata_array request_metadata_recv;
+  grpc_metadata_array initial_metadata_recv1;
+  grpc_metadata_array trailing_metadata_recv1;
+  grpc_metadata_array initial_metadata_recv2;
+  grpc_metadata_array trailing_metadata_recv2;
+  grpc_status_code status1;
+  grpc_call_error error;
+  grpc_slice details1 = grpc_empty_slice();
+  grpc_status_code status2;
+  grpc_slice details2 = grpc_empty_slice();
+  grpc_op ops[6];
+  grpc_op *op;
+  int was_cancelled;
+
+  server_arg.key = GRPC_ARG_MAX_CONCURRENT_STREAMS;
+  server_arg.type = GRPC_ARG_INTEGER;
+  server_arg.value.integer = 1;
+
+  server_args.num_args = 1;
+  server_args.args = &server_arg;
+
+  f = begin_test(config, "test_max_concurrent_streams_with_timeout_on_first",
+                 NULL, &server_args);
+  cqv = cq_verifier_create(f.cq);
+
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_metadata_array_init(&initial_metadata_recv1);
+  grpc_metadata_array_init(&trailing_metadata_recv1);
+  grpc_metadata_array_init(&initial_metadata_recv2);
+  grpc_metadata_array_init(&trailing_metadata_recv2);
+  grpc_call_details_init(&call_details);
+
+  /* perform a ping-pong to ensure that settings have had a chance to round
+     trip */
+  simple_request_body(config, f);
+  /* perform another one to make sure that the one stream case still works */
+  simple_request_body(config, f);
+
+  /* start two requests - ensuring that the second is not accepted until
+     the first completes */
+  c1 = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/alpha"),
+      get_host_override_slice("foo.test.google.fr:1234", config),
+      n_seconds_time(3), NULL);
+  GPR_ASSERT(c1);
+  c2 = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/beta"),
+      get_host_override_slice("foo.test.google.fr:1234", config),
+      n_seconds_time(1000), NULL);
+  GPR_ASSERT(c2);
+
+  GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
+                                 f.server, &s1, &call_details,
+                                 &request_metadata_recv, f.cq, f.cq, tag(101)));
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(301), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1;
+  op->data.recv_status_on_client.status = &status1;
+  op->data.recv_status_on_client.status_details = &details1;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata =
+      &initial_metadata_recv1;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(302), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+  CQ_EXPECT_COMPLETION(cqv, tag(301), 1);
+  cq_verify(cqv);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(401), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2;
+  op->data.recv_status_on_client.status = &status2;
+  op->data.recv_status_on_client.status_details = &details2;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata =
+      &initial_metadata_recv2;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(402), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  grpc_call_details_destroy(&call_details);
+  grpc_call_details_init(&call_details);
+  GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
+                                 f.server, &s2, &call_details,
+                                 &request_metadata_recv, f.cq, f.cq, tag(201)));
+
+  CQ_EXPECT_COMPLETION(cqv, tag(302), 1);
+  /* first request is finished, we should be able to start the second */
+  CQ_EXPECT_COMPLETION(cqv, tag(401), 1);
+  CQ_EXPECT_COMPLETION(cqv, tag(201), 1);
+  cq_verify(cqv);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(s2, ops, (size_t)(op - ops), tag(202), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(402), 1);
+  CQ_EXPECT_COMPLETION(cqv, tag(202), 1);
+  cq_verify(cqv);
+
+  cq_verifier_destroy(cqv);
+
+  grpc_call_destroy(c1);
+  grpc_call_destroy(s1);
+  grpc_call_destroy(c2);
+  grpc_call_destroy(s2);
+
+  grpc_slice_unref(details1);
+  grpc_slice_unref(details2);
+  grpc_metadata_array_destroy(&initial_metadata_recv1);
+  grpc_metadata_array_destroy(&trailing_metadata_recv1);
+  grpc_metadata_array_destroy(&initial_metadata_recv2);
+  grpc_metadata_array_destroy(&trailing_metadata_recv2);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+static void test_max_concurrent_streams_with_timeout_on_second(
+    grpc_end2end_test_config config) {
+  grpc_end2end_test_fixture f;
+  grpc_arg server_arg;
+  grpc_channel_args server_args;
+  grpc_call *c1;
+  grpc_call *c2;
+  grpc_call *s1;
+  cq_verifier *cqv;
+  grpc_call_details call_details;
+  grpc_metadata_array request_metadata_recv;
+  grpc_metadata_array initial_metadata_recv1;
+  grpc_metadata_array trailing_metadata_recv1;
+  grpc_metadata_array initial_metadata_recv2;
+  grpc_metadata_array trailing_metadata_recv2;
+  grpc_status_code status1;
+  grpc_call_error error;
+  grpc_slice details1 = grpc_empty_slice();
+  grpc_status_code status2;
+  grpc_slice details2 = grpc_empty_slice();
+  grpc_op ops[6];
+  grpc_op *op;
+  int was_cancelled;
+
+  server_arg.key = GRPC_ARG_MAX_CONCURRENT_STREAMS;
+  server_arg.type = GRPC_ARG_INTEGER;
+  server_arg.value.integer = 1;
+
+  server_args.num_args = 1;
+  server_args.args = &server_arg;
+
+  f = begin_test(config, "test_max_concurrent_streams_with_timeout_on_second",
+                 NULL, &server_args);
+  cqv = cq_verifier_create(f.cq);
+
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_metadata_array_init(&initial_metadata_recv1);
+  grpc_metadata_array_init(&trailing_metadata_recv1);
+  grpc_metadata_array_init(&initial_metadata_recv2);
+  grpc_metadata_array_init(&trailing_metadata_recv2);
+  grpc_call_details_init(&call_details);
+
+  /* perform a ping-pong to ensure that settings have had a chance to round
+     trip */
+  simple_request_body(config, f);
+  /* perform another one to make sure that the one stream case still works */
+  simple_request_body(config, f);
+
+  /* start two requests - ensuring that the second is not accepted until
+     the first completes , and the second request will timeout in the
+     concurrent_list */
+  c1 = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/alpha"),
+      get_host_override_slice("foo.test.google.fr:1234", config),
+      n_seconds_time(1000), NULL);
+  GPR_ASSERT(c1);
+  c2 = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/beta"),
+      get_host_override_slice("foo.test.google.fr:1234", config),
+      n_seconds_time(3), NULL);
+  GPR_ASSERT(c2);
+
+  GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
+                                 f.server, &s1, &call_details,
+                                 &request_metadata_recv, f.cq, f.cq, tag(101)));
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(301), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1;
+  op->data.recv_status_on_client.status = &status1;
+  op->data.recv_status_on_client.status_details = &details1;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata =
+      &initial_metadata_recv1;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c1, ops, (size_t)(op - ops), tag(302), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+  CQ_EXPECT_COMPLETION(cqv, tag(301), 1);
+  cq_verify(cqv);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(401), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2;
+  op->data.recv_status_on_client.status = &status2;
+  op->data.recv_status_on_client.status_details = &details2;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata =
+      &initial_metadata_recv2;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c2, ops, (size_t)(op - ops), tag(402), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  /* the second request is time out*/
+  CQ_EXPECT_COMPLETION(cqv, tag(401), 0);
+  CQ_EXPECT_COMPLETION(cqv, tag(402), 1);
+  cq_verify(cqv);
+
+  /* second request is finished because of time out, so destroy the second call
+   */
+  grpc_call_destroy(c2);
+
+  /* now reply the first call */
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(s1, ops, (size_t)(op - ops), tag(102), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(302), 1);
+  CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
+  cq_verify(cqv);
+
+  cq_verifier_destroy(cqv);
+
+  grpc_call_destroy(c1);
+  grpc_call_destroy(s1);
+
+  grpc_slice_unref(details1);
+  grpc_slice_unref(details2);
   grpc_metadata_array_destroy(&initial_metadata_recv1);
   grpc_metadata_array_destroy(&trailing_metadata_recv1);
   grpc_metadata_array_destroy(&initial_metadata_recv2);
@@ -447,6 +834,8 @@
 }
 
 void max_concurrent_streams(grpc_end2end_test_config config) {
+  test_max_concurrent_streams_with_timeout_on_first(config);
+  test_max_concurrent_streams_with_timeout_on_second(config);
   test_max_concurrent_streams(config);
 }
 
diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c
index 57d4f1c..b15d30f 100644
--- a/test/core/end2end/tests/max_message_length.c
+++ b/test/core/end2end/tests/max_message_length.c
@@ -43,6 +43,7 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/service_config.h"
 
@@ -55,7 +56,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   // We intentionally do not pass the client and server args to
   // create_fixture(), since we don't want the limit enforced on the
   // proxy, only on the backend server.
@@ -66,7 +67,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -82,7 +83,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -108,9 +109,12 @@
 // recv limit on server.
 static void test_max_message_length_on_request(grpc_end2end_test_config config,
                                                bool send_limit,
-                                               bool use_service_config) {
-  gpr_log(GPR_INFO, "testing request with send_limit=%d use_service_config=%d",
-          send_limit, use_service_config);
+                                               bool use_service_config,
+                                               bool use_string_json_value) {
+  gpr_log(GPR_INFO,
+          "testing request with send_limit=%d use_service_config=%d "
+          "use_string_json_value=%d",
+          send_limit, use_service_config, use_string_json_value);
 
   grpc_end2end_test_fixture f;
   grpc_call *c = NULL;
@@ -129,8 +133,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   grpc_channel_args *client_args = NULL;
@@ -142,14 +145,23 @@
     arg.type = GRPC_ARG_STRING;
     arg.key = GRPC_ARG_SERVICE_CONFIG;
     arg.value.string =
-        "{\n"
-        "  \"methodConfig\": [ {\n"
-        "    \"name\": [\n"
-        "      { \"service\": \"service\", \"method\": \"method\" }\n"
-        "    ],\n"
-        "    \"maxRequestMessageBytes\": \"5\"\n"
-        "  } ]\n"
-        "}";
+        use_string_json_value
+            ? "{\n"
+              "  \"methodConfig\": [ {\n"
+              "    \"name\": [\n"
+              "      { \"service\": \"service\", \"method\": \"method\" }\n"
+              "    ],\n"
+              "    \"maxRequestMessageBytes\": \"5\"\n"
+              "  } ]\n"
+              "}"
+            : "{\n"
+              "  \"methodConfig\": [ {\n"
+              "    \"name\": [\n"
+              "      { \"service\": \"service\", \"method\": \"method\" }\n"
+              "    ],\n"
+              "    \"maxRequestMessageBytes\": 5\n"
+              "  } ]\n"
+              "}";
     client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
   } else {
     // Set limit via channel args.
@@ -178,8 +190,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/service/method",
-      get_host_override_string("foo.test.google.fr:1234", config),
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/service/method"),
+      get_host_override_slice("foo.test.google.fr:1234", config),
       gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(c);
 
@@ -213,7 +226,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -252,19 +264,20 @@
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.method, "/service/method"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
 done:
   GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
-  GPR_ASSERT(strcmp(details,
-                    send_limit
-                        ? "Sent message larger than max (11 vs. 5)"
-                        : "Received message larger than max (11 vs. 5)") == 0);
+  GPR_ASSERT(
+      grpc_slice_str_cmp(
+          details, send_limit
+                       ? "Sent message larger than max (11 vs. 5)"
+                       : "Received message larger than max (11 vs. 5)") == 0);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -286,9 +299,12 @@
 // recv limit on client.
 static void test_max_message_length_on_response(grpc_end2end_test_config config,
                                                 bool send_limit,
-                                                bool use_service_config) {
-  gpr_log(GPR_INFO, "testing response with send_limit=%d use_service_config=%d",
-          send_limit, use_service_config);
+                                                bool use_service_config,
+                                                bool use_string_json_value) {
+  gpr_log(GPR_INFO,
+          "testing response with send_limit=%d use_service_config=%d "
+          "use_string_json_value=%d",
+          send_limit, use_service_config, use_string_json_value);
 
   grpc_end2end_test_fixture f;
   grpc_call *c = NULL;
@@ -307,8 +323,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   grpc_channel_args *client_args = NULL;
@@ -320,14 +335,23 @@
     arg.type = GRPC_ARG_STRING;
     arg.key = GRPC_ARG_SERVICE_CONFIG;
     arg.value.string =
-        "{\n"
-        "  \"methodConfig\": [ {\n"
-        "    \"name\": [\n"
-        "      { \"service\": \"service\", \"method\": \"method\" }\n"
-        "    ],\n"
-        "    \"maxResponseMessageBytes\": \"5\"\n"
-        "  } ]\n"
-        "}";
+        use_string_json_value
+            ? "{\n"
+              "  \"methodConfig\": [ {\n"
+              "    \"name\": [\n"
+              "      { \"service\": \"service\", \"method\": \"method\" }\n"
+              "    ],\n"
+              "    \"maxResponseMessageBytes\": \"5\"\n"
+              "  } ]\n"
+              "}"
+            : "{\n"
+              "  \"methodConfig\": [ {\n"
+              "    \"name\": [\n"
+              "      { \"service\": \"service\", \"method\": \"method\" }\n"
+              "    ],\n"
+              "    \"maxResponseMessageBytes\": 5\n"
+              "  } ]\n"
+              "}";
     client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
   } else {
     // Set limit via channel args.
@@ -354,9 +378,11 @@
   }
   cqv = cq_verifier_create(f.cq);
 
-  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/service/method", "foo.test.google.fr:1234",
-                               gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  c = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/service/method"),
+      get_host_override_slice("foo.test.google.fr:1234", config),
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -389,7 +415,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -423,7 +448,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -434,16 +460,18 @@
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.method, "/service/method"));
-  GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
+  GPR_ASSERT(0 ==
+             grpc_slice_str_cmp(call_details.host, "foo.test.google.fr:1234"));
 
   GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
-  GPR_ASSERT(strcmp(details,
-                    send_limit
-                        ? "Sent message larger than max (11 vs. 5)"
-                        : "Received message larger than max (11 vs. 5)") == 0);
+  GPR_ASSERT(
+      grpc_slice_str_cmp(
+          details, send_limit
+                       ? "Sent message larger than max (11 vs. 5)"
+                       : "Received message larger than max (11 vs. 5)") == 0);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -462,17 +490,29 @@
 
 void max_message_length(grpc_end2end_test_config config) {
   test_max_message_length_on_request(config, false /* send_limit */,
-                                     false /* use_service_config */);
+                                     false /* use_service_config */,
+                                     false /* use_string_json_value */);
   test_max_message_length_on_request(config, true /* send_limit */,
-                                     false /* use_service_config */);
+                                     false /* use_service_config */,
+                                     false /* use_string_json_value */);
   test_max_message_length_on_response(config, false /* send_limit */,
-                                      false /* use_service_config */);
+                                      false /* use_service_config */,
+                                      false /* use_string_json_value */);
   test_max_message_length_on_response(config, true /* send_limit */,
-                                      false /* use_service_config */);
+                                      false /* use_service_config */,
+                                      false /* use_string_json_value */);
   test_max_message_length_on_request(config, true /* send_limit */,
-                                     true /* use_service_config */);
+                                     true /* use_service_config */,
+                                     false /* use_string_json_value */);
+  test_max_message_length_on_request(config, true /* send_limit */,
+                                     true /* use_service_config */,
+                                     true /* use_string_json_value */);
   test_max_message_length_on_response(config, false /* send_limit */,
-                                      true /* use_service_config */);
+                                      true /* use_service_config */,
+                                      false /* use_string_json_value */);
+  test_max_message_length_on_response(config, false /* send_limit */,
+                                      true /* use_service_config */,
+                                      true /* use_string_json_value */);
 }
 
 void max_message_length_pre_init(void) {}
diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c
index 61a9858..0b61efb 100644
--- a/test/core/end2end/tests/negative_deadline.c
+++ b/test/core/end2end/tests/negative_deadline.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -108,14 +108,14 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -128,7 +128,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -155,7 +154,7 @@
 
   GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
diff --git a/test/core/end2end/tests/network_status_change.c b/test/core/end2end/tests/network_status_change.c
index dc855b7..7540ce9 100644
--- a/test/core/end2end/tests/network_status_change.c
+++ b/test/core/end2end/tests/network_status_change.c
@@ -53,7 +53,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -61,7 +61,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(500); }
@@ -77,7 +77,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -119,13 +119,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -159,7 +159,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -201,7 +200,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -212,13 +212,16 @@
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
+  // TODO(makdharma) Update this when the shutdown_all_endpoints is implemented.
   // Expected behavior of a RPC when network is lost.
-  GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  // GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
+  GPR_ASSERT(status == GRPC_STATUS_OK);
+
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/no_logging.c b/test/core/end2end/tests/no_logging.c
index 497ed05..56e48a8 100644
--- a/test/core/end2end/tests/no_logging.c
+++ b/test/core/end2end/tests/no_logging.c
@@ -80,7 +80,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -88,7 +88,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -104,7 +104,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -139,14 +139,14 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   char *peer;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -179,7 +179,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -210,7 +209,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -227,14 +227,14 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/no_op.c b/test/core/end2end/tests/no_op.c
index 8b29c21..62fc728 100644
--- a/test/core/end2end/tests/no_op.c
+++ b/test/core/end2end/tests/no_op.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c
index e39b513..b04ee57 100644
--- a/test/core/end2end/tests/payload.c
+++ b/test/core/end2end/tests/payload.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -138,13 +138,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -183,7 +183,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -230,7 +229,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -242,8 +242,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
@@ -251,7 +251,7 @@
   GPR_ASSERT(
       byte_buffer_eq_slice(response_payload_recv, response_payload_slice));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/ping.c b/test/core/end2end/tests/ping.c
index 5e5169d..f5bfac2 100644
--- a/test/core/end2end/tests/ping.c
+++ b/test/core/end2end/tests/ping.c
@@ -37,6 +37,7 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
+#include <grpc/support/useful.h>
 
 #include "test/core/end2end/cq_verifier.h"
 
@@ -48,7 +49,15 @@
   grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
   int i;
 
-  config.init_client(&f, NULL);
+  grpc_arg a[] = {{.type = GRPC_ARG_INTEGER,
+                   .key = GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS,
+                   .value.integer = 0},
+                  {.type = GRPC_ARG_INTEGER,
+                   .key = GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA,
+                   .value.integer = 20}};
+  grpc_channel_args client_args = {.num_args = GPR_ARRAY_SIZE(a), .args = a};
+
+  config.init_client(&f, &client_args);
   config.init_server(&f, NULL);
 
   grpc_channel_ping(f.client, f.cq, tag(0), NULL);
@@ -61,7 +70,7 @@
      READY is reached */
   while (state != GRPC_CHANNEL_READY) {
     grpc_channel_watch_connectivity_state(
-        f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(99));
+        f.client, state, grpc_timeout_seconds_to_deadline(3), f.cq, tag(99));
     CQ_EXPECT_COMPLETION(cqv, tag(99), 1);
     cq_verify(cqv);
     state = grpc_channel_check_connectivity_state(f.client, 0);
diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c
index bd6b53f..848f760 100644
--- a/test/core/end2end/tests/ping_pong_streaming.c
+++ b/test/core/end2end/tests/ping_pong_streaming.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -112,8 +112,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   grpc_byte_buffer *request_payload;
   grpc_byte_buffer *request_payload_recv;
@@ -126,8 +125,9 @@
       grpc_slice_from_copied_string("hello you");
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -152,7 +152,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -248,7 +247,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -270,7 +270,7 @@
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   end_test(&f);
   config.tear_down_data(&f);
diff --git a/test/core/end2end/tests/registered_call.c b/test/core/end2end/tests/registered_call.c
index ea1b4cf..9c8ce89 100644
--- a/test/core/end2end/tests/registered_call.c
+++ b/test/core/end2end/tests/registered_call.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -111,8 +111,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_registered_call(
@@ -144,7 +143,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -168,7 +166,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -185,13 +184,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c
index bafe6f6..329359e 100644
--- a/test/core/end2end/tests/request_with_flags.c
+++ b/test/core/end2end/tests/request_with_flags.c
@@ -51,7 +51,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -59,7 +59,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -75,7 +75,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -117,13 +117,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_call_error expectation;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -157,7 +157,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = flags_for_op[op->op];
   op->reserved = NULL;
   op++;
@@ -168,9 +167,9 @@
   if (expectation == GRPC_CALL_OK) {
     CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
     cq_verify(cqv);
+    grpc_slice_unref(details);
   }
 
-  gpr_free(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c
index 58f7279..f71f92b 100644
--- a/test/core/end2end/tests/request_with_payload.c
+++ b/test/core/end2end/tests/request_with_payload.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -116,13 +116,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -156,7 +156,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -197,7 +196,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -209,14 +209,14 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c
index 96abc1c..4f9ed7a 100644
--- a/test/core/end2end/tests/resource_quota_server.c
+++ b/test/core/end2end/tests/resource_quota_server.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -149,8 +149,7 @@
   grpc_call_details *call_details =
       malloc(sizeof(grpc_call_details) * NUM_CALLS);
   grpc_status_code *status = malloc(sizeof(grpc_status_code) * NUM_CALLS);
-  char **details = malloc(sizeof(char *) * NUM_CALLS);
-  size_t *details_capacity = malloc(sizeof(size_t) * NUM_CALLS);
+  grpc_slice *details = malloc(sizeof(grpc_slice) * NUM_CALLS);
   grpc_byte_buffer **request_payload_recv =
       malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS);
   int *was_cancelled = malloc(sizeof(int) * NUM_CALLS);
@@ -161,6 +160,7 @@
   int pending_server_end_calls = 0;
   int cancelled_calls_on_client = 0;
   int cancelled_calls_on_server = 0;
+  int deadline_exceeded = 0;
 
   grpc_byte_buffer *request_payload =
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
@@ -173,8 +173,6 @@
     grpc_metadata_array_init(&trailing_metadata_recv[i]);
     grpc_metadata_array_init(&request_metadata_recv[i]);
     grpc_call_details_init(&call_details[i]);
-    details[i] = NULL;
-    details_capacity[i] = 0;
     request_payload_recv[i] = NULL;
     was_cancelled[i] = 0;
   }
@@ -190,8 +188,10 @@
 
   for (int i = 0; i < NUM_CALLS; i++) {
     client_calls[i] = grpc_channel_create_call(
-        f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-        "foo.test.google.fr", n_seconds_time(60), NULL);
+        f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+        grpc_slice_from_static_string("/foo"),
+        get_host_override_slice("foo.test.google.fr", config),
+        n_seconds_time(60), NULL);
 
     memset(ops, 0, sizeof(ops));
     op = ops;
@@ -220,8 +220,6 @@
         &trailing_metadata_recv[i];
     op->data.recv_status_on_client.status = &status[i];
     op->data.recv_status_on_client.status_details = &details[i];
-    op->data.recv_status_on_client.status_details_capacity =
-        &details_capacity[i];
     op->flags = 0;
     op->reserved = NULL;
     op++;
@@ -250,6 +248,9 @@
         case GRPC_STATUS_RESOURCE_EXHAUSTED:
           cancelled_calls_on_client++;
           break;
+        case GRPC_STATUS_DEADLINE_EXCEEDED:
+          deadline_exceeded++;
+          break;
         case GRPC_STATUS_OK:
           break;
         default:
@@ -261,7 +262,7 @@
       grpc_metadata_array_destroy(&initial_metadata_recv[call_id]);
       grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]);
       grpc_call_destroy(client_calls[call_id]);
-      gpr_free(details[call_id]);
+      grpc_slice_unref(details[call_id]);
 
       pending_client_calls--;
     } else if (ev_tag < SERVER_RECV_BASE_TAG) {
@@ -318,7 +319,8 @@
       op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
       op->data.send_status_from_server.trailing_metadata_count = 0;
       op->data.send_status_from_server.status = GRPC_STATUS_OK;
-      op->data.send_status_from_server.status_details = "xyz";
+      grpc_slice status_details = grpc_slice_from_static_string("xyz");
+      op->data.send_status_from_server.status_details = &status_details;
       op->flags = 0;
       op->reserved = NULL;
       op++;
@@ -345,24 +347,19 @@
     }
   }
 
-  gpr_log(
-      GPR_INFO,
-      "Done. %d total calls: %d cancelled at server, %d cancelled at client.",
-      NUM_CALLS, cancelled_calls_on_server, cancelled_calls_on_client);
-
-  /* The call may be cancelled after the server has sent its status but before
-   * the client has received it. This means that we should see strictly more
-   * failures on the client than on the server. */
-  GPR_ASSERT(cancelled_calls_on_client >= cancelled_calls_on_server);
-  /* However, we shouldn't see radically more... 0.9 is a guessed bound on what
-   * we'd want that ratio to be... to at least trigger some investigation should
-   * that ratio become much higher. */
-  GPR_ASSERT(cancelled_calls_on_server >= 0.9 * cancelled_calls_on_client);
+  gpr_log(GPR_INFO,
+          "Done. %d total calls: %d cancelled at server, %d cancelled at "
+          "client, %d timed out.",
+          NUM_CALLS, cancelled_calls_on_server, cancelled_calls_on_client,
+          deadline_exceeded);
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_slice_unref(request_payload_slice);
   grpc_resource_quota_unref(resource_quota);
 
+  end_test(&f);
+  config.tear_down_data(&f);
+
   free(client_calls);
   free(server_calls);
   free(initial_metadata_recv);
@@ -371,12 +368,8 @@
   free(call_details);
   free(status);
   free(details);
-  free(details_capacity);
   free(request_payload_recv);
   free(was_cancelled);
-
-  end_test(&f);
-  config.tear_down_data(&f);
 }
 
 void resource_quota_server_pre_init(void) {}
diff --git a/test/core/end2end/tests/server_finishes_request.c b/test/core/end2end/tests/server_finishes_request.c
index 6541815..b42d170 100644
--- a/test/core/end2end/tests/server_finishes_request.c
+++ b/test/core/end2end/tests/server_finishes_request.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -111,13 +111,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -142,7 +142,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -166,7 +165,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -183,13 +183,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c
index 608e97e..c019682 100644
--- a/test/core/end2end/tests/shutdown_finishes_calls.c
+++ b/test/core/end2end/tests/shutdown_finishes_calls.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -100,13 +100,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -136,7 +136,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -172,12 +171,12 @@
   grpc_server_destroy(f.server);
 
   GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/shutdown_finishes_tags.c b/test/core/end2end/tests/shutdown_finishes_tags.c
index 1d110a7..5540d2a 100644
--- a/test/core/end2end/tests/shutdown_finishes_tags.c
+++ b/test/core/end2end/tests/shutdown_finishes_tags.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
diff --git a/test/core/end2end/tests/simple_cacheable_request.c b/test/core/end2end/tests/simple_cacheable_request.c
index 269a40d..4eef02e 100644
--- a/test/core/end2end/tests/simple_cacheable_request.c
+++ b/test/core/end2end/tests/simple_cacheable_request.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -111,12 +111,22 @@
   grpc_byte_buffer *response_payload =
       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
-  grpc_metadata meta_c[2] = {
-      {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
-  grpc_metadata meta_s[2] = {
-      {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+                              grpc_slice_from_static_string("val3"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key4"),
+                              grpc_slice_from_static_string("val4"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
       config, "test_cacheable_request_response_with_metadata_and_payload", NULL,
       NULL);
@@ -131,13 +141,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -177,7 +187,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -225,7 +234,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -237,8 +247,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) {
@@ -254,7 +264,7 @@
   GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3"));
   GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c
index be9f9bf..e3b6aee 100644
--- a/test/core/end2end/tests/simple_delayed_request.c
+++ b/test/core/end2end/tests/simple_delayed_request.c
@@ -46,7 +46,7 @@
 static void *tag(intptr_t t) { return (void *)t; }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -62,7 +62,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -100,15 +100,16 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   config.init_client(f, client_args);
+  config.init_server(f, server_args);
 
   c = grpc_channel_create_call(
-      f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -137,15 +138,12 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
   error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
   GPR_ASSERT(GRPC_CALL_OK == error);
 
-  config.init_server(f, server_args);
-
   error =
       grpc_server_request_call(f->server, &s, &call_details,
                                &request_metadata_recv, f->cq, f->cq, tag(101));
@@ -163,7 +161,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -180,13 +179,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -208,7 +207,8 @@
   client_args.args = arg_array;
   client_args.num_args = 1;
 
-  gpr_log(GPR_INFO, "%s/%s", "test_simple_delayed_request_short", config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", "test_simple_delayed_request_short",
+          config.name);
   f = config.create_fixture(NULL, NULL);
 
   simple_delayed_request_body(config, &f, &client_args, NULL, 100000);
@@ -226,7 +226,8 @@
   client_args.args = arg_array;
   client_args.num_args = 1;
 
-  gpr_log(GPR_INFO, "%s/%s", "test_simple_delayed_request_long", config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", "test_simple_delayed_request_long",
+          config.name);
   f = config.create_fixture(NULL, NULL);
   /* This timeout should be longer than a single retry */
   simple_delayed_request_body(config, &f, &client_args, NULL, 1500000);
diff --git a/test/core/end2end/tests/simple_metadata.c b/test/core/end2end/tests/simple_metadata.c
index c9e571e..7ab5563 100644
--- a/test/core/end2end/tests/simple_metadata.c
+++ b/test/core/end2end/tests/simple_metadata.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -109,12 +109,22 @@
   grpc_byte_buffer *response_payload =
       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
-  grpc_metadata meta_c[2] = {
-      {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
-  grpc_metadata meta_s[2] = {
-      {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+                              grpc_slice_from_static_string("val3"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key4"),
+                              grpc_slice_from_static_string("val4"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
       config, "test_request_response_with_metadata_and_payload", NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -128,13 +138,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -174,7 +184,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -222,7 +231,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -234,8 +244,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
@@ -246,7 +256,7 @@
   GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3"));
   GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c
index 787ad40..af5d749 100644
--- a/test/core/end2end/tests/simple_request.c
+++ b/test/core/end2end/tests/simple_request.c
@@ -52,7 +52,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -111,14 +111,14 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   char *peer;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -152,7 +152,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -185,7 +184,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -202,14 +202,14 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -236,7 +236,7 @@
       begin_test(config, "test_invoke_10_simple_requests", NULL, NULL);
   for (i = 0; i < 10; i++) {
     simple_request_body(config, f);
-    gpr_log(GPR_INFO, "Passed simple request %d", i);
+    gpr_log(GPR_INFO, "Running test: Passed simple request %d", i);
   }
   end_test(&f);
   config.tear_down_data(&f);
diff --git a/test/core/end2end/tests/streaming_error_response.c b/test/core/end2end/tests/streaming_error_response.c
index 6fc6d75..4205590 100644
--- a/test/core/end2end/tests/streaming_error_response.c
+++ b/test/core/end2end/tests/streaming_error_response.c
@@ -51,8 +51,8 @@
                                             grpc_channel_args *server_args,
                                             bool request_status_early) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s/request_status_early=%s", test_name, config.name,
-          request_status_early ? "true" : "false");
+  gpr_log(GPR_INFO, "Running test: %s/%s/request_status_early=%s", test_name,
+          config.name, request_status_early ? "true" : "false");
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -60,7 +60,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -76,7 +76,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -121,13 +121,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -154,7 +154,6 @@
     op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
     op->data.recv_status_on_client.status = &status;
     op->data.recv_status_on_client.status_details = &details;
-    op->data.recv_status_on_client.status_details_capacity = &details_capacity;
     op++;
   }
   error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
@@ -202,7 +201,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_FAILED_PRECONDITION;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op++;
   error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL);
   GPR_ASSERT(GRPC_CALL_OK == error);
@@ -232,7 +232,6 @@
     op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
     op->data.recv_status_on_client.status = &status;
     op->data.recv_status_on_client.status_details = &details;
-    op->data.recv_status_on_client.status_details_capacity = &details_capacity;
     op++;
     error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL);
     GPR_ASSERT(GRPC_CALL_OK == error);
@@ -245,13 +244,13 @@
   }
 
   GPR_ASSERT(status == GRPC_STATUS_FAILED_PRECONDITION);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/trailing_metadata.c b/test/core/end2end/tests/trailing_metadata.c
index a44ed77..dbbda50 100644
--- a/test/core/end2end/tests/trailing_metadata.c
+++ b/test/core/end2end/tests/trailing_metadata.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -109,15 +109,30 @@
   grpc_byte_buffer *response_payload =
       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
-  grpc_metadata meta_c[2] = {
-      {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
-  grpc_metadata meta_s[2] = {
-      {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
-  grpc_metadata meta_t[2] = {
-      {"key5", "val5", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key6", "val6", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+                              grpc_slice_from_static_string("val3"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key4"),
+                              grpc_slice_from_static_string("val4"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_t[2] = {{grpc_slice_from_static_string("key5"),
+                              grpc_slice_from_static_string("val5"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key6"),
+                              grpc_slice_from_static_string("val6"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
       config, "test_request_response_with_metadata_and_payload", NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -131,13 +146,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -177,7 +192,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -226,7 +240,8 @@
   op->data.send_status_from_server.trailing_metadata_count = 2;
   op->data.send_status_from_server.trailing_metadata = meta_t;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -238,8 +253,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
@@ -251,7 +266,7 @@
   GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key5", "val5"));
   GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key6", "val6"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/write_buffering.c b/test/core/end2end/tests/write_buffering.c
index ee95338..abf90ca 100644
--- a/test/core/end2end/tests/write_buffering.c
+++ b/test/core/end2end/tests/write_buffering.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -120,13 +120,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details = grpc_empty_slice();
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -228,7 +228,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -244,7 +243,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -256,15 +256,15 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/write_buffering_at_end.c b/test/core/end2end/tests/write_buffering_at_end.c
index 9b203ea..8c02b42 100644
--- a/test/core/end2end/tests/write_buffering_at_end.c
+++ b/test/core/end2end/tests/write_buffering_at_end.c
@@ -50,7 +50,7 @@
                                             grpc_channel_args *client_args,
                                             grpc_channel_args *server_args) {
   grpc_end2end_test_fixture f;
-  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
   f = config.create_fixture(client_args, server_args);
   config.init_server(&f, server_args);
   config.init_client(&f, client_args);
@@ -58,7 +58,7 @@
 }
 
 static gpr_timespec n_seconds_time(int n) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+  return grpc_timeout_seconds_to_deadline(n);
 }
 
 static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
@@ -74,7 +74,7 @@
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 f->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
@@ -117,13 +117,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details = grpc_empty_slice();
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -219,7 +219,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -235,7 +234,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -247,15 +247,15 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world"));
   GPR_ASSERT(request_payload_recv2 == NULL);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/fling/BUILD b/test/core/fling/BUILD
new file mode 100644
index 0000000..0b0ebcb
--- /dev/null
+++ b/test/core/fling/BUILD
@@ -0,0 +1,62 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
+
+cc_binary(
+    name = "client",
+    srcs = ["client.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
+    testonly = 1,
+    copts = ['-std=c99']
+)
+
+cc_binary(
+    name = "server",
+    srcs = ["server.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
+    testonly = 1,
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "fling",
+    srcs = ["fling_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
+    data = [":client", ":server"]
+)
+
+cc_test(
+    name = "fling_stream",
+    srcs = ["fling_stream_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
+    data = [":client", ":server"]
+)
diff --git a/test/core/fling/client.c b/test/core/fling/client.c
index e1a4630..85bab6d 100644
--- a/test/core/fling/client.c
+++ b/test/core/fling/client.c
@@ -57,8 +57,7 @@
 static grpc_metadata_array trailing_metadata_recv;
 static grpc_byte_buffer *response_payload_recv = NULL;
 static grpc_status_code status;
-static char *details = NULL;
-static size_t details_capacity = 0;
+static grpc_slice details;
 static grpc_op *op;
 
 static void init_ping_pong_request(void) {
@@ -86,15 +85,16 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op++;
 }
 
 static void step_ping_pong_request(void) {
   GPR_TIMER_BEGIN("ping_pong", 1);
-  call = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/Reflector/reflectUnary", "localhost",
-                                  gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  grpc_slice host = grpc_slice_from_static_string("localhost");
+  call = grpc_channel_create_call(
+      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/Reflector/reflectUnary"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call, ops,
                                                    (size_t)(op - ops),
                                                    (void *)1, NULL));
@@ -109,9 +109,11 @@
   grpc_metadata_array_init(&initial_metadata_recv);
 
   grpc_call_error error;
-  call = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/Reflector/reflectStream", "localhost",
-                                  gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  grpc_slice host = grpc_slice_from_static_string("localhost");
+  call = grpc_channel_create_call(
+      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/Reflector/reflectStream"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   stream_init_ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
   stream_init_ops[0].data.send_initial_metadata.count = 0;
   stream_init_ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
@@ -212,9 +214,9 @@
 
   sc.init();
 
-  gpr_timespec end_warmup = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(warmup_seconds);
+  gpr_timespec end_warmup = grpc_timeout_seconds_to_deadline(warmup_seconds);
   gpr_timespec end_profiling =
-      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(warmup_seconds + benchmark_seconds);
+      grpc_timeout_seconds_to_deadline(warmup_seconds + benchmark_seconds);
 
   while (gpr_time_cmp(gpr_now(end_warmup.clock_type), end_warmup) < 0) {
     sc.do_one_step();
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index 79e5e35..7ea54b1 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -118,7 +118,7 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
   op->data.send_status_from_server.trailing_metadata_count = 0;
-  op->data.send_status_from_server.status_details = "";
+  op->data.send_status_from_server.status_details = NULL;
   op++;
   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
   op->data.recv_close_on_server.cancelled = &was_cancelled;
@@ -168,7 +168,7 @@
   status_op[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   status_op[0].data.send_status_from_server.status = GRPC_STATUS_OK;
   status_op[0].data.send_status_from_server.trailing_metadata_count = 0;
-  status_op[0].data.send_status_from_server.status_details = "";
+  status_op[0].data.send_status_from_server.status_details = NULL;
   status_op[1].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
   status_op[1].data.recv_close_on_server.cancelled = &was_cancelled;
 
@@ -244,7 +244,7 @@
       gpr_log(GPR_INFO, "Shutting down due to SIGINT");
       grpc_server_shutdown_and_notify(server, cq, tag(1000));
       GPR_ASSERT(grpc_completion_queue_pluck(
-                     cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                     cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                      .type == GRPC_OP_COMPLETE);
       grpc_completion_queue_shutdown(cq);
       shutdown_started = 1;
@@ -259,8 +259,8 @@
         switch ((intptr_t)s) {
           case FLING_SERVER_NEW_REQUEST:
             if (call != NULL) {
-              if (0 ==
-                  strcmp(call_details.method, "/Reflector/reflectStream")) {
+              if (0 == grpc_slice_str_cmp(call_details.method,
+                                          "/Reflector/reflectStream")) {
                 /* Received streaming call. Send metadata here. */
                 start_read_op(FLING_SERVER_READ_FOR_STREAMING);
                 send_initial_metadata();
diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD
new file mode 100644
index 0000000..864e0db
--- /dev/null
+++ b/test/core/handshake/BUILD
@@ -0,0 +1,62 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+cc_test(
+    name = "client_ssl",
+    srcs = ["client_ssl.c"],
+    copts = ["-std=c99"],
+    data = [
+        "//src/core/lib/tsi/test_creds:ca.pem",
+        "//src/core/lib/tsi/test_creds:server1.key",
+        "//src/core/lib/tsi/test_creds:server1.pem",
+    ],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "server_ssl",
+    srcs = ["server_ssl.c"],
+    copts = ["-std=c99"],
+    data = [
+        "//src/core/lib/tsi/test_creds:ca.pem",
+        "//src/core/lib/tsi/test_creds:server1.key",
+        "//src/core/lib/tsi/test_creds:server1.pem",
+    ],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/handshake/client_ssl.c b/test/core/handshake/client_ssl.c
index 1d853af..5cfe60d 100644
--- a/test/core/handshake/client_ssl.c
+++ b/test/core/handshake/client_ssl.c
@@ -64,13 +64,17 @@
   char *alpn_preferred;
 } server_args;
 
-// From https://wiki.openssl.org/index.php/Simple_TLS_Server.
-static int create_socket(int port) {
+// Based on https://wiki.openssl.org/index.php/Simple_TLS_Server.
+// Pick an arbitrary unused port and return it in *out_port. Return
+// an fd>=0 on success.
+static int create_socket(int *out_port) {
   int s;
   struct sockaddr_in addr;
+  socklen_t addr_len;
+  *out_port = -1;
 
   addr.sin_family = AF_INET;
-  addr.sin_port = htons((uint16_t)port);
+  addr.sin_port = 0;
   addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
   s = socket(AF_INET, SOCK_STREAM, 0);
@@ -81,7 +85,7 @@
 
   if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
     perror("Unable to bind");
-    gpr_log(GPR_ERROR, "Unable to bind to %d", port);
+    gpr_log(GPR_ERROR, "%s", "Unable to bind to any port");
     close(s);
     return -1;
   }
@@ -92,6 +96,16 @@
     return -1;
   }
 
+  addr_len = sizeof(addr);
+  if (getsockname(s, (struct sockaddr *)&addr, &addr_len) != 0 ||
+      addr_len > sizeof(addr)) {
+    perror("getsockname");
+    gpr_log(GPR_ERROR, "%s", "Unable to get socket local address");
+    close(s);
+    return -1;
+  }
+
+  *out_port = ntohs(addr.sin_port);
   return s;
 }
 
@@ -220,13 +234,12 @@
   int server_socket = -1;
   int socket_retries = 30;
   while (server_socket == -1 && socket_retries-- > 0) {
-    port = grpc_pick_unused_port_or_die();
-    server_socket = create_socket(port);
+    server_socket = create_socket(&port);
     if (server_socket == -1) {
       sleep(1);
     }
   }
-  GPR_ASSERT(server_socket > 0);
+  GPR_ASSERT(server_socket > 0 && port > 0);
 
   // Launch the TLS server thread.
   gpr_thd_options thdopt = gpr_thd_options_default();
@@ -279,8 +292,8 @@
   grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
   while (state != GRPC_CHANNEL_READY && retries-- > 0) {
     grpc_channel_watch_connectivity_state(
-        channel, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), cq, NULL);
-    gpr_timespec cq_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
+        channel, state, grpc_timeout_seconds_to_deadline(3), cq, NULL);
+    gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5);
     grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL);
     GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
     state =
diff --git a/test/core/handshake/server_ssl.c b/test/core/handshake/server_ssl.c
index f39b004..0bd5a03 100644
--- a/test/core/handshake/server_ssl.c
+++ b/test/core/handshake/server_ssl.c
@@ -113,7 +113,7 @@
   // sleeping between polls.
   int retries = 10;
   while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) {
-    const gpr_timespec cq_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
+    const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1);
     grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL);
     GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT);
   }
@@ -122,7 +122,7 @@
   grpc_server_shutdown_and_notify(server, cq, NULL);
   grpc_completion_queue_shutdown(cq);
 
-  const gpr_timespec cq_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
+  const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5);
   grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL);
   GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
 
diff --git a/test/core/http/BUILD b/test/core/http/BUILD
index 037ede3..abfa759 100644
--- a/test/core/http/BUILD
+++ b/test/core/http/BUILD
@@ -47,3 +47,58 @@
   copts = ["-std=c99"],
 )
 
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
+
+cc_test(
+    name = "httpcli_test",
+    srcs = ["httpcli_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
+    copts = ['-std=c99'],
+    data = ['test_server.py']
+)
+
+cc_test(
+    name = "httpscli_test",
+    srcs = ["httpscli_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
+    copts = ['-std=c99'],
+    data = ['test_server.py']
+)
+
+cc_test(
+    name = "parser_test",
+    srcs = ["parser_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/http/httpcli_test.c b/test/core/http/httpcli_test.c
index 4cdbb5d..f690dba 100644
--- a/test/core/http/httpcli_test.c
+++ b/test/core/http/httpcli_test.c
@@ -51,7 +51,7 @@
 static grpc_polling_entity g_pops;
 
 static gpr_timespec n_seconds_time(int seconds) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
+  return grpc_timeout_seconds_to_deadline(seconds);
 }
 
 static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
@@ -202,14 +202,14 @@
   grpc_test_init(argc, argv);
   grpc_init();
   grpc_httpcli_context_init(&g_context);
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &g_mu);
   g_pops = grpc_polling_entity_create_from_pollset(pollset);
 
   test_get(port);
   test_post(port);
 
-  grpc_httpcli_context_destroy(&g_context);
+  grpc_httpcli_context_destroy(&exec_ctx, &g_context);
   grpc_closure_init(&destroyed, destroy_pops, &g_pops,
                     grpc_schedule_on_exec_ctx);
   grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
diff --git a/test/core/http/httpscli_test.c b/test/core/http/httpscli_test.c
index 72017cf..5494110 100644
--- a/test/core/http/httpscli_test.c
+++ b/test/core/http/httpscli_test.c
@@ -51,7 +51,7 @@
 static grpc_polling_entity g_pops;
 
 static gpr_timespec n_seconds_time(int seconds) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
+  return grpc_timeout_seconds_to_deadline(seconds);
 }
 
 static void on_finish(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
@@ -205,14 +205,14 @@
   grpc_test_init(argc, argv);
   grpc_init();
   grpc_httpcli_context_init(&g_context);
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &g_mu);
   g_pops = grpc_polling_entity_create_from_pollset(pollset);
 
   test_get(port);
   test_post(port);
 
-  grpc_httpcli_context_destroy(&g_context);
+  grpc_httpcli_context_destroy(&exec_ctx, &g_context);
   grpc_closure_init(&destroyed, destroy_pops, &g_pops,
                     grpc_schedule_on_exec_ctx);
   grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&g_pops),
diff --git a/test/core/internal_api_canaries/iomgr.c b/test/core/internal_api_canaries/iomgr.c
deleted file mode 100644
index 3225b9d..0000000
--- a/test/core/internal_api_canaries/iomgr.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "src/core/lib/iomgr/iomgr.h"
-#include "src/core/lib/iomgr/closure.h"
-#include "src/core/lib/iomgr/endpoint.h"
-#include "src/core/lib/iomgr/exec_ctx.h"
-#include "src/core/lib/iomgr/executor.h"
-
-/*******************************************************************************
- * NOTE: If this test fails to compile, then the api changes are likely to cause
- *       merge failures downstream. Please pay special attention to reviewing
- *       these changes, and solicit help as appropriate when merging downstream.
- *
- * This test is NOT expected to be run directly.
- ******************************************************************************/
-
-static void test_code(void) {
-  /* iomgr.h */
-  grpc_iomgr_init();
-  grpc_iomgr_shutdown(NULL);
-
-  /* closure.h */
-  grpc_closure closure;
-  closure.cb = NULL;
-  closure.cb_arg = NULL;
-  closure.next_data.scratch = 0;
-
-  grpc_closure_list closure_list = GRPC_CLOSURE_LIST_INIT;
-  closure_list.head = NULL;
-  closure_list.tail = NULL;
-
-  grpc_closure_init(&closure, NULL, NULL, grpc_schedule_on_exec_ctx);
-
-  grpc_closure_create(NULL, NULL, grpc_schedule_on_exec_ctx);
-
-  grpc_closure_list_move(NULL, NULL);
-  grpc_closure_list_append(NULL, NULL, GRPC_ERROR_CREATE("Foo"));
-  grpc_closure_list_empty(closure_list);
-
-  /* exec_ctx.h */
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_exec_ctx_flush(&exec_ctx);
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_closure_sched(&exec_ctx, &closure, GRPC_ERROR_CREATE("Foo"));
-  grpc_closure_list_sched(&exec_ctx, &closure_list);
-
-  /* endpoint.h */
-  grpc_endpoint endpoint;
-  grpc_endpoint_vtable vtable = {grpc_endpoint_read,
-                                 grpc_endpoint_write,
-                                 grpc_endpoint_get_workqueue,
-                                 grpc_endpoint_add_to_pollset,
-                                 grpc_endpoint_add_to_pollset_set,
-                                 grpc_endpoint_shutdown,
-                                 grpc_endpoint_destroy,
-                                 grpc_endpoint_get_resource_user,
-                                 grpc_endpoint_get_peer,
-                                 grpc_endpoint_get_fd};
-  endpoint.vtable = &vtable;
-
-  grpc_endpoint_read(&exec_ctx, &endpoint, NULL, NULL);
-  grpc_endpoint_get_peer(&endpoint);
-  grpc_endpoint_write(&exec_ctx, &endpoint, NULL, NULL);
-  grpc_endpoint_shutdown(&exec_ctx, &endpoint);
-  grpc_endpoint_destroy(&exec_ctx, &endpoint);
-  grpc_endpoint_add_to_pollset(&exec_ctx, &endpoint, NULL);
-  grpc_endpoint_add_to_pollset_set(&exec_ctx, &endpoint, NULL);
-
-  /* executor.h */
-  grpc_executor_init();
-  grpc_executor_shutdown(NULL);
-
-  /* pollset.h */
-  grpc_pollset_size();
-  grpc_pollset_init(NULL, NULL);
-  grpc_pollset_shutdown(NULL, NULL, NULL);
-  grpc_pollset_reset(NULL);
-  grpc_pollset_destroy(NULL);
-  GRPC_ERROR_UNREF(grpc_pollset_work(NULL, NULL, NULL,
-                                     gpr_now(GPR_CLOCK_REALTIME),
-                                     gpr_now(GPR_CLOCK_MONOTONIC)));
-  GRPC_ERROR_UNREF(grpc_pollset_kick(NULL, NULL));
-}
-
-int main(void) {
-  if (false) test_code();
-  return 0;
-}
diff --git a/test/core/internal_api_canaries/support.c b/test/core/internal_api_canaries/support.c
deleted file mode 100644
index e992d2a..0000000
--- a/test/core/internal_api_canaries/support.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*******************************************************************************
- * NOTE: If this test fails to compile, then the api changes are likely to cause
- *       merge failures downstream. Please pay special attention to reviewing
- *       these changes, and solicit help as appropriate when merging downstream.
- *
- * This test is NOT expected to be run directly.
- ******************************************************************************/
-
-#include "src/core/lib/iomgr/load_file.h"
-#include "src/core/lib/support/env.h"
-#include "src/core/lib/support/tmpfile.h"
-
-static void test_code(void) {
-  /* env.h */
-  gpr_set_env("abc", gpr_getenv("xyz"));
-  /* load_file.h */
-  grpc_load_file("abc", 1, NULL);
-  /* tmpfile.h */
-  fclose(gpr_tmpfile("foo", NULL));
-}
-
-int main(void) {
-  if (false) test_code();
-  return 0;
-}
diff --git a/test/core/internal_api_canaries/transport.c b/test/core/internal_api_canaries/transport.c
deleted file mode 100644
index 2989f59..0000000
--- a/test/core/internal_api_canaries/transport.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*******************************************************************************
- * NOTE: If this test fails to compile, then the api changes are likely to cause
- *       merge failures downstream. Please pay special attention to reviewing
- *       these changes, and solicit help as appropriate when merging downstream.
- *
- * This test is NOT expected to be run directly.
- ******************************************************************************/
-
-#include "src/core/lib/transport/transport.h"
-#include "src/core/lib/transport/transport_impl.h"
-
-static void test_code(void) {
-  /* transport_impl.h */
-  grpc_transport transport;
-  grpc_transport_vtable vtable = {12345,
-                                  grpc_transport_init_stream,
-                                  grpc_transport_set_pollset,
-                                  grpc_transport_perform_stream_op,
-                                  grpc_transport_perform_op,
-                                  grpc_transport_destroy_stream,
-                                  grpc_transport_destroy,
-                                  grpc_transport_get_peer};
-  transport.vtable = &vtable;
-
-  /* transport.h */
-  GRPC_STREAM_REF_INIT(NULL, 0, NULL, NULL, "xyz");
-  GPR_ASSERT(0 == grpc_transport_stream_size(NULL));
-  GPR_ASSERT(grpc_transport_init_stream(&transport, NULL, NULL, NULL, NULL));
-  grpc_transport_set_pollset(&transport, NULL, NULL, NULL);
-  grpc_transport_destroy_stream(&transport, NULL, NULL);
-  grpc_transport_stream_op_finish_with_failure(NULL, NULL);
-  grpc_transport_stream_op_add_cancellation(NULL, GRPC_STATUS_UNAVAILABLE);
-  grpc_transport_stream_op_add_close(NULL, GRPC_STATUS_UNAVAILABLE,
-                                     grpc_transport_op_string(NULL));
-  grpc_transport_perform_stream_op(&transport, NULL, NULL, NULL);
-  grpc_transport_perform_op(&transport, NULL, NULL);
-  grpc_transport_ping(&transport, NULL);
-  grpc_transport_goaway(&transport, GRPC_STATUS_UNAVAILABLE,
-                        grpc_slice_malloc(0));
-  grpc_transport_close(&transport);
-  grpc_transport_destroy(&transport, NULL);
-  GPR_ASSERT("xyz" == grpc_transport_get_peer(&transport, NULL));
-}
-
-int main(void) {
-  if (false) test_code();
-  return 0;
-}
diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD
new file mode 100644
index 0000000..0cf93e7
--- /dev/null
+++ b/test/core/iomgr/BUILD
@@ -0,0 +1,181 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
+
+cc_library(
+    name = "endpoint_tests",
+    srcs = ["endpoint_tests.c"],
+    hdrs = ["endpoint_tests.h"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    visibility = ["//test:__subpackages__"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "combiner_test",
+    srcs = ["combiner_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "endpoint_pair_test",
+    srcs = ["endpoint_pair_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", ":endpoint_tests"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "ev_epoll_linux_test",
+    srcs = ["ev_epoll_linux_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "fd_conservation_posix_test",
+    srcs = ["fd_conservation_posix_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "fd_posix_test",
+    srcs = ["fd_posix_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "load_file_test",
+    srcs = ["load_file_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "pollset_set_test",
+    srcs = ["pollset_set_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "resolve_address_posix_test",
+    srcs = ["resolve_address_posix_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "resolve_address_test",
+    srcs = ["resolve_address_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "resource_quota_test",
+    srcs = ["resource_quota_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "sockaddr_utils_test",
+    srcs = ["sockaddr_utils_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "socket_utils_test",
+    srcs = ["socket_utils_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "tcp_client_posix_test",
+    srcs = ["tcp_client_posix_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "tcp_posix_test",
+    srcs = ["tcp_posix_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", ":endpoint_tests"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "tcp_server_posix_test",
+    srcs = ["tcp_server_posix_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "time_averaged_stats_test",
+    srcs = ["time_averaged_stats_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "timer_heap_test",
+    srcs = ["timer_heap_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "timer_list_test",
+    srcs = ["timer_list_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "udp_server_test",
+    srcs = ["udp_server_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "wakeup_fd_cv_test",
+    srcs = ["wakeup_fd_cv_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c
index 9b6d6ff..bc4d2af 100644
--- a/test/core/iomgr/combiner_test.c
+++ b/test/core/iomgr/combiner_test.c
@@ -44,7 +44,7 @@
 static void test_no_op(void) {
   gpr_log(GPR_DEBUG, "test_no_op");
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_combiner_destroy(&exec_ctx, grpc_combiner_create(NULL));
+  GRPC_COMBINER_UNREF(&exec_ctx, grpc_combiner_create(NULL), "test_no_op");
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -65,7 +65,7 @@
                      GRPC_ERROR_NONE);
   grpc_exec_ctx_flush(&exec_ctx);
   GPR_ASSERT(done);
-  grpc_combiner_destroy(&exec_ctx, lock);
+  GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_one");
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -103,7 +103,7 @@
     }
     // sleep for a little bit, to test a combiner draining and another thread
     // picking it up
-    gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100));
+    gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
   }
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -125,7 +125,7 @@
     gpr_thd_join(thds[i]);
   }
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_combiner_destroy(&exec_ctx, lock);
+  GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_many");
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -153,7 +153,7 @@
                      GRPC_ERROR_NONE);
   grpc_exec_ctx_flush(&exec_ctx);
   GPR_ASSERT(got_in_finally);
-  grpc_combiner_destroy(&exec_ctx, lock);
+  GRPC_COMBINER_UNREF(&exec_ctx, lock, "test_execute_finally");
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c
index f02171f..4b98ef2 100644
--- a/test/core/iomgr/endpoint_pair_test.c
+++ b/test/core/iomgr/endpoint_pair_test.c
@@ -78,7 +78,7 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  g_pollset = gpr_malloc(grpc_pollset_size());
+  g_pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(g_pollset, &g_mu);
   grpc_endpoint_tests(configs[0], g_pollset, g_mu);
   grpc_closure_init(&destroyed, destroy_pollset, g_pollset,
diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c
index df5dd20..94067a8 100644
--- a/test/core/iomgr/endpoint_tests.c
+++ b/test/core/iomgr/endpoint_tests.c
@@ -187,7 +187,7 @@
                                 size_t num_bytes, size_t write_size,
                                 size_t slice_size, bool shutdown) {
   struct read_and_write_test_state state;
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(20);
   grpc_endpoint_test_fixture f =
       begin_test(config, "read_and_write_test", slice_size);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -233,9 +233,11 @@
 
   if (shutdown) {
     gpr_log(GPR_DEBUG, "shutdown read");
-    grpc_endpoint_shutdown(&exec_ctx, state.read_ep);
+    grpc_endpoint_shutdown(&exec_ctx, state.read_ep,
+                           GRPC_ERROR_CREATE("Test Shutdown"));
     gpr_log(GPR_DEBUG, "shutdown write");
-    grpc_endpoint_shutdown(&exec_ctx, state.write_ep);
+    grpc_endpoint_shutdown(&exec_ctx, state.write_ep,
+                           GRPC_ERROR_CREATE("Test Shutdown"));
   }
   grpc_exec_ctx_flush(&exec_ctx);
 
@@ -296,7 +298,8 @@
                      grpc_closure_create(inc_on_failure, &fail_count,
                                          grpc_schedule_on_exec_ctx));
   wait_for_fail_count(&exec_ctx, &fail_count, 0);
-  grpc_endpoint_shutdown(&exec_ctx, f.client_ep);
+  grpc_endpoint_shutdown(&exec_ctx, f.client_ep,
+                         GRPC_ERROR_CREATE("Test Shutdown"));
   wait_for_fail_count(&exec_ctx, &fail_count, 1);
   grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer,
                      grpc_closure_create(inc_on_failure, &fail_count,
@@ -307,7 +310,8 @@
                       grpc_closure_create(inc_on_failure, &fail_count,
                                           grpc_schedule_on_exec_ctx));
   wait_for_fail_count(&exec_ctx, &fail_count, 3);
-  grpc_endpoint_shutdown(&exec_ctx, f.client_ep);
+  grpc_endpoint_shutdown(&exec_ctx, f.client_ep,
+                         GRPC_ERROR_CREATE("Test Shutdown"));
   wait_for_fail_count(&exec_ctx, &fail_count, 3);
 
   grpc_slice_buffer_destroy_internal(&exec_ctx, &slice_buffer);
diff --git a/test/core/iomgr/ev_epoll_linux_test.c b/test/core/iomgr/ev_epoll_linux_test.c
index d95d552..4ec9599 100644
--- a/test/core/iomgr/ev_epoll_linux_test.c
+++ b/test/core/iomgr/ev_epoll_linux_test.c
@@ -89,7 +89,8 @@
   int i;
 
   for (i = 0; i < num_fds; i++) {
-    grpc_fd_shutdown(exec_ctx, tfds[i].fd);
+    grpc_fd_shutdown(exec_ctx, tfds[i].fd,
+                     GRPC_ERROR_CREATE("test_fd_cleanup"));
     grpc_exec_ctx_flush(exec_ctx);
 
     grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, "test_fd_cleanup");
@@ -103,7 +104,7 @@
 static void test_pollset_init(test_pollset *pollsets, int num_pollsets) {
   int i;
   for (i = 0; i < num_pollsets; i++) {
-    pollsets[i].pollset = gpr_malloc(grpc_pollset_size());
+    pollsets[i].pollset = gpr_zalloc(grpc_pollset_size());
     grpc_pollset_init(pollsets[i].pollset, &pollsets[i].mu);
   }
 }
@@ -315,6 +316,7 @@
             "strategy. and the current strategy is: '%s'",
             poll_strategy);
   }
+
   {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     grpc_iomgr_shutdown(&exec_ctx);
diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c
index a617bfc..c1a0ef5 100644
--- a/test/core/iomgr/fd_posix_test.c
+++ b/test/core/iomgr/fd_posix_test.c
@@ -132,7 +132,8 @@
   grpc_fd_orphan(exec_ctx, se->em_fd, NULL, NULL, "a");
   gpr_free(se);
   /* Start to shutdown listen fd. */
-  grpc_fd_shutdown(exec_ctx, sv->em_fd);
+  grpc_fd_shutdown(exec_ctx, sv->em_fd,
+                   GRPC_ERROR_CREATE("session_shutdown_cb"));
 }
 
 /* Called when data become readable in a session. */
@@ -542,7 +543,7 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_iomgr_init();
-  g_pollset = gpr_malloc(grpc_pollset_size());
+  g_pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(g_pollset, &g_mu);
   test_grpc_fd();
   test_grpc_fd_change();
diff --git a/test/core/iomgr/pollset_set_test.c b/test/core/iomgr/pollset_set_test.c
new file mode 100644
index 0000000..f27e9db
--- /dev/null
+++ b/test/core/iomgr/pollset_set_test.c
@@ -0,0 +1,468 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "src/core/lib/iomgr/port.h"
+
+/* This test only relevant on linux systems where epoll is available */
+#ifdef GRPC_LINUX_EPOLL
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "test/core/util/test_config.h"
+
+/*******************************************************************************
+ * test_pollset_set
+ */
+
+typedef struct test_pollset_set { grpc_pollset_set *pss; } test_pollset_set;
+
+void init_test_pollset_sets(test_pollset_set *pollset_sets, const int num_pss) {
+  for (int i = 0; i < num_pss; i++) {
+    pollset_sets[i].pss = grpc_pollset_set_create();
+  }
+}
+
+void cleanup_test_pollset_sets(grpc_exec_ctx *exec_ctx,
+                               test_pollset_set *pollset_sets,
+                               const int num_pss) {
+  for (int i = 0; i < num_pss; i++) {
+    grpc_pollset_set_destroy(exec_ctx, pollset_sets[i].pss);
+    pollset_sets[i].pss = NULL;
+  }
+}
+
+/*******************************************************************************
+ * test_pollset
+ */
+
+typedef struct test_pollset {
+  grpc_pollset *ps;
+  gpr_mu *mu;
+} test_pollset;
+
+static void init_test_pollsets(test_pollset *pollsets, const int num_pollsets) {
+  for (int i = 0; i < num_pollsets; i++) {
+    pollsets[i].ps = gpr_zalloc(grpc_pollset_size());
+    grpc_pollset_init(pollsets[i].ps, &pollsets[i].mu);
+  }
+}
+
+static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
+                            grpc_error *error) {
+  grpc_pollset_destroy(p);
+}
+
+static void cleanup_test_pollsets(grpc_exec_ctx *exec_ctx,
+                                  test_pollset *pollsets,
+                                  const int num_pollsets) {
+  grpc_closure destroyed;
+  for (int i = 0; i < num_pollsets; i++) {
+    grpc_closure_init(&destroyed, destroy_pollset, pollsets[i].ps,
+                      grpc_schedule_on_exec_ctx);
+    grpc_pollset_shutdown(exec_ctx, pollsets[i].ps, &destroyed);
+
+    grpc_exec_ctx_flush(exec_ctx);
+    gpr_free(pollsets[i].ps);
+    pollsets[i].ps = NULL;
+  }
+}
+
+/*******************************************************************************
+ * test_fd
+ */
+
+typedef struct test_fd {
+  grpc_fd *fd;
+  grpc_wakeup_fd wakeup_fd;
+
+  bool is_on_readable_called; /* Is on_readable closure is called ? */
+  grpc_closure on_readable;   /* Closure to call when this fd is readable */
+} test_fd;
+
+void on_readable(grpc_exec_ctx *exec_ctx, void *tfd, grpc_error *error) {
+  ((test_fd *)tfd)->is_on_readable_called = true;
+}
+
+static void reset_test_fd(grpc_exec_ctx *exec_ctx, test_fd *tfd) {
+  tfd->is_on_readable_called = false;
+
+  grpc_closure_init(&tfd->on_readable, on_readable, tfd,
+                    grpc_schedule_on_exec_ctx);
+  grpc_fd_notify_on_read(exec_ctx, tfd->fd, &tfd->on_readable);
+}
+
+static void init_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds,
+                          const int num_fds) {
+  for (int i = 0; i < num_fds; i++) {
+    GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_init(&tfds[i].wakeup_fd));
+    tfds[i].fd = grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&tfds[i].wakeup_fd),
+                                "test_fd");
+    reset_test_fd(exec_ctx, &tfds[i]);
+  }
+}
+
+static void cleanup_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds,
+                             const int num_fds) {
+  int release_fd;
+
+  for (int i = 0; i < num_fds; i++) {
+    grpc_fd_shutdown(exec_ctx, tfds[i].fd, GRPC_ERROR_CREATE("fd cleanup"));
+    grpc_exec_ctx_flush(exec_ctx);
+
+    /* grpc_fd_orphan frees the memory allocated for grpc_fd. Normally it also
+     * calls close() on the underlying fd. In our case, we are using
+     * grpc_wakeup_fd and we would like to destroy it ourselves (by calling
+     * grpc_wakeup_fd_destroy). To prevent grpc_fd from calling close() on the
+     * underlying fd, call it with a non-NULL 'release_fd' parameter */
+    grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, "test_fd_cleanup");
+    grpc_exec_ctx_flush(exec_ctx);
+
+    grpc_wakeup_fd_destroy(&tfds[i].wakeup_fd);
+  }
+}
+
+static void make_test_fds_readable(test_fd *tfds, const int num_fds) {
+  for (int i = 0; i < num_fds; i++) {
+    GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_wakeup(&tfds[i].wakeup_fd));
+  }
+}
+
+static void verify_readable_and_reset(grpc_exec_ctx *exec_ctx, test_fd *tfds,
+                                      const int num_fds) {
+  for (int i = 0; i < num_fds; i++) {
+    /* Verify that the on_readable callback was called */
+    GPR_ASSERT(tfds[i].is_on_readable_called);
+
+    /* Reset the tfd[i] structure */
+    GPR_ASSERT(GRPC_ERROR_NONE ==
+               grpc_wakeup_fd_consume_wakeup(&tfds[i].wakeup_fd));
+    reset_test_fd(exec_ctx, &tfds[i]);
+  }
+}
+
+/*******************************************************************************
+ * Main tests
+ */
+
+/* Test some typical scenarios in pollset_set */
+static void pollset_set_test_basic() {
+  /* We construct the following structure for this test:
+   *
+   *        +---> FD0 (Added before PSS1, PS1 and PS2 are added to PSS0)
+   *        |
+   *        +---> FD5 (Added after PSS1, PS1 and PS2 are added to PSS0)
+   *        |
+   *        |
+   *        |           +---> FD1 (Added before PSS1 is added to PSS0)
+   *        |           |
+   *        |           +---> FD6 (Added after PSS1 is added to PSS0)
+   *        |           |
+   *        +---> PSS1--+           +--> FD2 (Added before PS0 is added to PSS1)
+   *        |           |           |
+   *        |           +---> PS0---+
+   *        |                       |
+   * PSS0---+                       +--> FD7 (Added after PS0 is added to PSS1)
+   *        |
+   *        |
+   *        |           +---> FD3 (Added before PS1 is added to PSS0)
+   *        |           |
+   *        +---> PS1---+
+   *        |           |
+   *        |           +---> FD8 (Added after PS1 added to PSS0)
+   *        |
+   *        |
+   *        |           +---> FD4 (Added before PS2 is added to PSS0)
+   *        |           |
+   *        +---> PS2---+
+   *                    |
+   *                    +---> FD9 (Added after PS2 is added to PSS0)
+   */
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_pollset_worker *worker;
+  gpr_timespec deadline;
+
+  test_fd tfds[10];
+  test_pollset pollsets[3];
+  test_pollset_set pollset_sets[2];
+  const int num_fds = GPR_ARRAY_SIZE(tfds);
+  const int num_ps = GPR_ARRAY_SIZE(pollsets);
+  const int num_pss = GPR_ARRAY_SIZE(pollset_sets);
+
+  init_test_fds(&exec_ctx, tfds, num_fds);
+  init_test_pollsets(pollsets, num_ps);
+  init_test_pollset_sets(pollset_sets, num_pss);
+
+  /* Construct the pollset_set/pollset/fd tree (see diagram above) */
+
+  grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd);
+  grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd);
+
+  grpc_pollset_add_fd(&exec_ctx, pollsets[0].ps, tfds[2].fd);
+  grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[3].fd);
+  grpc_pollset_add_fd(&exec_ctx, pollsets[2].ps, tfds[4].fd);
+
+  grpc_pollset_set_add_pollset_set(&exec_ctx, pollset_sets[0].pss,
+                                   pollset_sets[1].pss);
+
+  grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[1].pss, pollsets[0].ps);
+  grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[1].ps);
+  grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[2].ps);
+
+  grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[5].fd);
+  grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[6].fd);
+
+  grpc_pollset_add_fd(&exec_ctx, pollsets[0].ps, tfds[7].fd);
+  grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[8].fd);
+  grpc_pollset_add_fd(&exec_ctx, pollsets[2].ps, tfds[9].fd);
+
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  /* Test that if any FD in the above structure is readable, it is observable by
+   * doing grpc_pollset_work on any pollset
+   *
+   *   For every pollset, do the following:
+   *     - (Ensure that all FDs are in reset state)
+   *     - Make all FDs readable
+   *     - Call grpc_pollset_work() on the pollset
+   *     - Flush the exec_ctx
+   *     - Verify that on_readable call back was called for all FDs (and
+   *       reset the FDs)
+   * */
+  for (int i = 0; i < num_ps; i++) {
+    make_test_fds_readable(tfds, num_fds);
+
+    gpr_mu_lock(pollsets[i].mu);
+    deadline = grpc_timeout_milliseconds_to_deadline(2);
+    GPR_ASSERT(GRPC_ERROR_NONE ==
+               grpc_pollset_work(&exec_ctx, pollsets[i].ps, &worker,
+                                 gpr_now(GPR_CLOCK_MONOTONIC), deadline));
+    gpr_mu_unlock(pollsets[i].mu);
+
+    grpc_exec_ctx_flush(&exec_ctx);
+
+    verify_readable_and_reset(&exec_ctx, tfds, num_fds);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+
+  /* Test tear down */
+  grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd);
+  grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[5].fd);
+  grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd);
+  grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[6].fd);
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[1].pss, pollsets[0].ps);
+  grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[1].ps);
+  grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[2].ps);
+
+  grpc_pollset_set_del_pollset_set(&exec_ctx, pollset_sets[0].pss,
+                                   pollset_sets[1].pss);
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  cleanup_test_fds(&exec_ctx, tfds, num_fds);
+  cleanup_test_pollsets(&exec_ctx, pollsets, num_ps);
+  cleanup_test_pollset_sets(&exec_ctx, pollset_sets, num_pss);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+/* Same FD added multiple times to the pollset_set tree */
+void pollset_set_test_dup_fds() {
+  /* We construct the following structure for this test:
+   *
+   *        +---> FD0
+   *        |
+   *        |
+   * PSS0---+
+   *        |           +---> FD0 (also under PSS0)
+   *        |           |
+   *        +---> PSS1--+           +--> FD1 (also under PSS1)
+   *                    |           |
+   *                    +---> PS ---+
+   *                    |           |
+   *                    |           +--> FD2
+   *                    +---> FD1
+   */
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_pollset_worker *worker;
+  gpr_timespec deadline;
+
+  test_fd tfds[3];
+  test_pollset pollset;
+  test_pollset_set pollset_sets[2];
+  const int num_fds = GPR_ARRAY_SIZE(tfds);
+  const int num_ps = 1;
+  const int num_pss = GPR_ARRAY_SIZE(pollset_sets);
+
+  init_test_fds(&exec_ctx, tfds, num_fds);
+  init_test_pollsets(&pollset, num_ps);
+  init_test_pollset_sets(pollset_sets, num_pss);
+
+  /* Construct the structure */
+  grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd);
+  grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[0].fd);
+  grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd);
+
+  grpc_pollset_add_fd(&exec_ctx, pollset.ps, tfds[1].fd);
+  grpc_pollset_add_fd(&exec_ctx, pollset.ps, tfds[2].fd);
+
+  grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[1].pss, pollset.ps);
+  grpc_pollset_set_add_pollset_set(&exec_ctx, pollset_sets[0].pss,
+                                   pollset_sets[1].pss);
+
+  /* Test. Make all FDs readable and make sure that can be observed by doing a
+   * grpc_pollset_work on the pollset 'PS' */
+  make_test_fds_readable(tfds, num_fds);
+
+  gpr_mu_lock(pollset.mu);
+  deadline = grpc_timeout_milliseconds_to_deadline(2);
+  GPR_ASSERT(GRPC_ERROR_NONE ==
+             grpc_pollset_work(&exec_ctx, pollset.ps, &worker,
+                               gpr_now(GPR_CLOCK_MONOTONIC), deadline));
+  gpr_mu_unlock(pollset.mu);
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  verify_readable_and_reset(&exec_ctx, tfds, num_fds);
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  /* Tear down */
+  grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd);
+  grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[0].fd);
+  grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd);
+
+  grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[1].pss, pollset.ps);
+  grpc_pollset_set_del_pollset_set(&exec_ctx, pollset_sets[0].pss,
+                                   pollset_sets[1].pss);
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  cleanup_test_fds(&exec_ctx, tfds, num_fds);
+  cleanup_test_pollsets(&exec_ctx, &pollset, num_ps);
+  cleanup_test_pollset_sets(&exec_ctx, pollset_sets, num_pss);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+/* Pollset_set with an empty pollset */
+void pollset_set_test_empty_pollset() {
+  /* We construct the following structure for this test:
+   *
+   *        +---> PS0 (EMPTY)
+   *        |
+   *        +---> FD0
+   *        |
+   * PSS0---+
+   *        |          +---> FD1
+   *        |          |
+   *        +---> PS1--+
+   *                   |
+   *                   +---> FD2
+   */
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_pollset_worker *worker;
+  gpr_timespec deadline;
+
+  test_fd tfds[3];
+  test_pollset pollsets[2];
+  test_pollset_set pollset_set;
+  const int num_fds = GPR_ARRAY_SIZE(tfds);
+  const int num_ps = GPR_ARRAY_SIZE(pollsets);
+  const int num_pss = 1;
+
+  init_test_fds(&exec_ctx, tfds, num_fds);
+  init_test_pollsets(pollsets, num_ps);
+  init_test_pollset_sets(&pollset_set, num_pss);
+
+  /* Construct the structure */
+  grpc_pollset_set_add_fd(&exec_ctx, pollset_set.pss, tfds[0].fd);
+  grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[1].fd);
+  grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[2].fd);
+
+  grpc_pollset_set_add_pollset(&exec_ctx, pollset_set.pss, pollsets[0].ps);
+  grpc_pollset_set_add_pollset(&exec_ctx, pollset_set.pss, pollsets[1].ps);
+
+  /* Test. Make all FDs readable and make sure that can be observed by doing
+   * grpc_pollset_work on the empty pollset 'PS0' */
+  make_test_fds_readable(tfds, num_fds);
+
+  gpr_mu_lock(pollsets[0].mu);
+  deadline = grpc_timeout_milliseconds_to_deadline(2);
+  GPR_ASSERT(GRPC_ERROR_NONE ==
+             grpc_pollset_work(&exec_ctx, pollsets[0].ps, &worker,
+                               gpr_now(GPR_CLOCK_MONOTONIC), deadline));
+  gpr_mu_unlock(pollsets[0].mu);
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  verify_readable_and_reset(&exec_ctx, tfds, num_fds);
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  /* Tear down */
+  grpc_pollset_set_del_fd(&exec_ctx, pollset_set.pss, tfds[0].fd);
+  grpc_pollset_set_del_pollset(&exec_ctx, pollset_set.pss, pollsets[0].ps);
+  grpc_pollset_set_del_pollset(&exec_ctx, pollset_set.pss, pollsets[1].ps);
+  grpc_exec_ctx_flush(&exec_ctx);
+
+  cleanup_test_fds(&exec_ctx, tfds, num_fds);
+  cleanup_test_pollsets(&exec_ctx, pollsets, num_ps);
+  cleanup_test_pollset_sets(&exec_ctx, &pollset_set, num_pss);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+int main(int argc, char **argv) {
+  const char *poll_strategy = grpc_get_poll_strategy_name();
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_test_init(argc, argv);
+  grpc_iomgr_init();
+
+  if (poll_strategy != NULL && strcmp(poll_strategy, "epoll") == 0) {
+    pollset_set_test_basic();
+    pollset_set_test_dup_fds();
+    pollset_set_test_empty_pollset();
+  } else {
+    gpr_log(GPR_INFO,
+            "Skipping the test. The test is only relevant for 'epoll' "
+            "strategy. and the current strategy is: '%s'",
+            poll_strategy);
+  }
+
+  grpc_iomgr_shutdown(&exec_ctx);
+  grpc_exec_ctx_finish(&exec_ctx);
+  return 0;
+}
+#else /* defined(GRPC_LINUX_EPOLL) */
+int main(int argc, char **argv) { return 0; }
+#endif /* !defined(GRPC_LINUX_EPOLL) */
diff --git a/test/core/iomgr/resolve_address_posix_test.c b/test/core/iomgr/resolve_address_posix_test.c
new file mode 100644
index 0000000..fa88aca
--- /dev/null
+++ b/test/core/iomgr/resolve_address_posix_test.c
@@ -0,0 +1,188 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/iomgr/resolve_address.h"
+
+#include <string.h>
+#include <sys/un.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/iomgr/iomgr.h"
+#include "test/core/util/test_config.h"
+
+static gpr_timespec test_deadline(void) {
+  return grpc_timeout_seconds_to_deadline(100);
+}
+
+typedef struct args_struct {
+  gpr_event ev;
+  grpc_resolved_addresses *addrs;
+  gpr_atm done_atm;
+  gpr_mu *mu;
+  grpc_pollset *pollset;
+  grpc_pollset_set *pollset_set;
+} args_struct;
+
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
+
+void args_init(grpc_exec_ctx *exec_ctx, args_struct *args) {
+  gpr_event_init(&args->ev);
+  args->pollset = gpr_zalloc(grpc_pollset_size());
+  grpc_pollset_init(args->pollset, &args->mu);
+  args->pollset_set = grpc_pollset_set_create();
+  grpc_pollset_set_add_pollset(exec_ctx, args->pollset_set, args->pollset);
+  args->addrs = NULL;
+}
+
+void args_finish(grpc_exec_ctx *exec_ctx, args_struct *args) {
+  GPR_ASSERT(gpr_event_wait(&args->ev, test_deadline()));
+  grpc_resolved_addresses_destroy(args->addrs);
+  grpc_pollset_set_del_pollset(exec_ctx, args->pollset_set, args->pollset);
+  grpc_pollset_set_destroy(exec_ctx, args->pollset_set);
+  grpc_closure do_nothing_cb;
+  grpc_closure_init(&do_nothing_cb, do_nothing, NULL,
+                    grpc_schedule_on_exec_ctx);
+  grpc_pollset_shutdown(exec_ctx, args->pollset, &do_nothing_cb);
+  // exec_ctx needs to be flushed before calling grpc_pollset_destroy()
+  grpc_exec_ctx_flush(exec_ctx);
+  grpc_pollset_destroy(args->pollset);
+  gpr_free(args->pollset);
+}
+
+static gpr_timespec n_sec_deadline(int seconds) {
+  return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                      gpr_time_from_seconds(seconds, GPR_TIMESPAN));
+}
+
+static void actually_poll(void *argsp) {
+  args_struct *args = argsp;
+  gpr_timespec deadline = n_sec_deadline(10);
+  while (true) {
+    bool done = gpr_atm_acq_load(&args->done_atm) != 0;
+    if (done) {
+      break;
+    }
+    gpr_timespec time_left =
+        gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME));
+    gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64 ".%09d", done,
+            time_left.tv_sec, time_left.tv_nsec);
+    GPR_ASSERT(gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) >= 0);
+    grpc_pollset_worker *worker = NULL;
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    gpr_mu_lock(args->mu);
+    GRPC_LOG_IF_ERROR(
+        "pollset_work",
+        grpc_pollset_work(&exec_ctx, args->pollset, &worker,
+                          gpr_now(GPR_CLOCK_REALTIME), n_sec_deadline(1)));
+    gpr_mu_unlock(args->mu);
+    grpc_exec_ctx_finish(&exec_ctx);
+  }
+  gpr_event_set(&args->ev, (void *)1);
+}
+
+static void poll_pollset_until_request_done(args_struct *args) {
+  gpr_atm_rel_store(&args->done_atm, 0);
+  gpr_thd_id id;
+  gpr_thd_new(&id, actually_poll, args, NULL);
+}
+
+static void must_succeed(grpc_exec_ctx *exec_ctx, void *argsp,
+                         grpc_error *err) {
+  args_struct *args = argsp;
+  GPR_ASSERT(err == GRPC_ERROR_NONE);
+  GPR_ASSERT(args->addrs != NULL);
+  GPR_ASSERT(args->addrs->naddrs > 0);
+  gpr_atm_rel_store(&args->done_atm, 1);
+}
+
+static void must_fail(grpc_exec_ctx *exec_ctx, void *argsp, grpc_error *err) {
+  args_struct *args = argsp;
+  GPR_ASSERT(err != GRPC_ERROR_NONE);
+  gpr_atm_rel_store(&args->done_atm, 1);
+}
+
+static void test_unix_socket(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  args_struct args;
+  args_init(&exec_ctx, &args);
+  poll_pollset_until_request_done(&args);
+  grpc_resolve_address(
+      &exec_ctx, "unix:/path/name", NULL, args.pollset_set,
+      grpc_closure_create(must_succeed, &args, grpc_schedule_on_exec_ctx),
+      &args.addrs);
+  args_finish(&exec_ctx, &args);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void test_unix_socket_path_name_too_long(void) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  args_struct args;
+  args_init(&exec_ctx, &args);
+  const char prefix[] = "unix:/path/name";
+  size_t path_name_length =
+      GPR_ARRAY_SIZE(((struct sockaddr_un *)0)->sun_path) + 6;
+  char *path_name = gpr_malloc(sizeof(char) * path_name_length);
+  memset(path_name, 'a', path_name_length);
+  memcpy(path_name, prefix, strlen(prefix) - 1);
+  path_name[path_name_length - 1] = '\0';
+
+  poll_pollset_until_request_done(&args);
+  grpc_resolve_address(
+      &exec_ctx, path_name, NULL, args.pollset_set,
+      grpc_closure_create(must_fail, &args, grpc_schedule_on_exec_ctx),
+      &args.addrs);
+  gpr_free(path_name);
+  args_finish(&exec_ctx, &args);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+  grpc_executor_init();
+  grpc_iomgr_init();
+  test_unix_socket();
+  test_unix_socket_path_name_too_long();
+  {
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_executor_shutdown(&exec_ctx);
+    grpc_iomgr_shutdown(&exec_ctx);
+    grpc_exec_ctx_finish(&exec_ctx);
+  }
+  return 0;
+}
diff --git a/test/core/iomgr/resolve_address_test.c b/test/core/iomgr/resolve_address_test.c
index 71e9fe5..ea79adc 100644
--- a/test/core/iomgr/resolve_address_test.c
+++ b/test/core/iomgr/resolve_address_test.c
@@ -41,7 +41,7 @@
 #include "test/core/util/test_config.h"
 
 static gpr_timespec test_deadline(void) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(100);
+  return grpc_timeout_seconds_to_deadline(100);
 }
 
 typedef struct args_struct {
@@ -57,7 +57,7 @@
 
 void args_init(grpc_exec_ctx *exec_ctx, args_struct *args) {
   gpr_event_init(&args->ev);
-  args->pollset = gpr_malloc(grpc_pollset_size());
+  args->pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(args->pollset, &args->mu);
   args->pollset_set = grpc_pollset_set_create();
   grpc_pollset_set_add_pollset(exec_ctx, args->pollset_set, args->pollset);
@@ -69,7 +69,7 @@
   GPR_ASSERT(gpr_event_wait(&args->ev, test_deadline()));
   grpc_resolved_addresses_destroy(args->addrs);
   grpc_pollset_set_del_pollset(exec_ctx, args->pollset_set, args->pollset);
-  grpc_pollset_set_destroy(args->pollset_set);
+  grpc_pollset_set_destroy(exec_ctx, args->pollset_set);
   grpc_closure do_nothing_cb;
   grpc_closure_init(&do_nothing_cb, do_nothing, NULL,
                     grpc_schedule_on_exec_ctx);
diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c
index e813cdb..b324b5a 100644
--- a/test/core/iomgr/tcp_client_posix_test.c
+++ b/test/core/iomgr/tcp_client_posix_test.c
@@ -62,7 +62,7 @@
 static grpc_endpoint *g_connecting = NULL;
 
 static gpr_timespec test_deadline(void) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
+  return grpc_timeout_seconds_to_deadline(10);
 }
 
 static void finish_connection() {
@@ -77,7 +77,8 @@
                          grpc_error *error) {
   GPR_ASSERT(g_connecting != NULL);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
-  grpc_endpoint_shutdown(exec_ctx, g_connecting);
+  grpc_endpoint_shutdown(exec_ctx, g_connecting,
+                         GRPC_ERROR_CREATE("must_succeed called"));
   grpc_endpoint_destroy(exec_ctx, g_connecting);
   g_connecting = NULL;
   finish_connection();
@@ -139,7 +140,7 @@
         "pollset_work",
         grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                           gpr_now(GPR_CLOCK_MONOTONIC),
-                          GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))));
+                          grpc_timeout_seconds_to_deadline(5))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_flush(&exec_ctx);
     gpr_mu_lock(g_mu);
@@ -204,14 +205,14 @@
   grpc_test_init(argc, argv);
   grpc_init();
   g_pollset_set = grpc_pollset_set_create();
-  g_pollset = gpr_malloc(grpc_pollset_size());
+  g_pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(g_pollset, &g_mu);
   grpc_pollset_set_add_pollset(&exec_ctx, g_pollset_set, g_pollset);
   grpc_exec_ctx_finish(&exec_ctx);
   test_succeeds();
   gpr_log(GPR_ERROR, "End of first test");
   test_fails();
-  grpc_pollset_set_destroy(g_pollset_set);
+  grpc_pollset_set_destroy(&exec_ctx, g_pollset_set);
   grpc_closure_init(&destroyed, destroy_pollset, g_pollset,
                     grpc_schedule_on_exec_ctx);
   grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c
index cabb64e..5a55be8 100644
--- a/test/core/iomgr/tcp_posix_test.c
+++ b/test/core/iomgr/tcp_posix_test.c
@@ -175,7 +175,7 @@
   grpc_endpoint *ep;
   struct read_socket_state state;
   size_t written_bytes;
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(20);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
   gpr_log(GPR_INFO, "Read test of size %" PRIuPTR ", slice size %" PRIuPTR,
@@ -226,7 +226,7 @@
   grpc_endpoint *ep;
   struct read_socket_state state;
   ssize_t written_bytes;
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(20);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
   gpr_log(GPR_INFO, "Start large read test, slice size %" PRIuPTR, slice_size);
@@ -330,7 +330,7 @@
         "pollset_work",
         grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                           gpr_now(GPR_CLOCK_MONOTONIC),
-                          GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10))));
+                          grpc_timeout_milliseconds_to_deadline(10))));
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     do {
@@ -363,7 +363,7 @@
   uint8_t current_data = 0;
   grpc_slice_buffer outgoing;
   grpc_closure write_done_closure;
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(20);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
   gpr_log(GPR_INFO,
@@ -428,7 +428,7 @@
   struct read_socket_state state;
   size_t written_bytes;
   int fd;
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(20);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_closure fd_released_cb;
   int fd_released_done = 0;
@@ -561,7 +561,7 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  g_pollset = gpr_malloc(grpc_pollset_size());
+  g_pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(g_pollset, &g_mu);
   grpc_endpoint_tests(configs[0], g_pollset, g_mu);
   run_tests();
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index 020f005..efadddc 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -39,9 +39,12 @@
 #include "src/core/lib/iomgr/tcp_server.h"
 
 #include <errno.h>
+#include <ifaddrs.h>
 #include <netinet/in.h>
+#include <stdio.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include <grpc/grpc.h>
@@ -50,6 +53,7 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 
+#include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
@@ -62,7 +66,7 @@
 static grpc_pollset *g_pollset;
 static int g_nconnects = 0;
 
-typedef struct on_connect_result {
+typedef struct {
   /* Owns a ref to server. */
   grpc_tcp_server *server;
   unsigned port_index;
@@ -70,15 +74,41 @@
   int server_fd;
 } on_connect_result;
 
-typedef struct server_weak_ref {
+typedef struct {
   grpc_tcp_server *server;
 
   /* arg is this server_weak_ref. */
   grpc_closure server_shutdown;
 } server_weak_ref;
 
+#define MAX_URI 1024
+typedef struct {
+  grpc_resolved_address addr;
+  char str[MAX_URI];
+} test_addr;
+
+#define MAX_ADDRS 100
+typedef struct {
+  size_t naddrs;
+  test_addr addrs[MAX_ADDRS];
+} test_addrs;
+
 static on_connect_result g_result = {NULL, 0, 0, -1};
 
+static char family_name_buf[1024];
+static const char *sock_family_name(int family) {
+  if (family == AF_INET) {
+    return "AF_INET";
+  } else if (family == AF_INET6) {
+    return "AF_INET6";
+  } else if (family == AF_UNSPEC) {
+    return "AF_UNSPEC";
+  } else {
+    sprintf(family_name_buf, "%d", family);
+    return family_name_buf;
+  }
+}
+
 static void on_connect_result_init(on_connect_result *result) {
   result->server = NULL;
   result->port_index = 0;
@@ -118,10 +148,22 @@
   weak_ref->server = server;
 }
 
+static void test_addr_init_str(test_addr *addr) {
+  char *str = NULL;
+  if (grpc_sockaddr_to_string(&str, &addr->addr, 0) != -1) {
+    size_t str_len;
+    memcpy(addr->str, str, (str_len = strnlen(str, sizeof(addr->str) - 1)));
+    addr->str[str_len] = '\0';
+    gpr_free(str);
+  } else {
+    addr->str[0] = '\0';
+  }
+}
+
 static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
                        grpc_pollset *pollset,
                        grpc_tcp_server_acceptor *acceptor) {
-  grpc_endpoint_shutdown(exec_ctx, tcp);
+  grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
   grpc_endpoint_destroy(exec_ctx, tcp);
 
   on_connect_result temp_result;
@@ -168,7 +210,7 @@
   memset(&resolved_addr, 0, sizeof(resolved_addr));
   resolved_addr.len = sizeof(struct sockaddr_in);
   addr->sin_family = AF_INET;
-  int port;
+  int port = -1;
   GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) ==
                  GRPC_ERROR_NONE &&
              port > 0);
@@ -185,7 +227,7 @@
   GPR_ASSERT(GRPC_ERROR_NONE ==
              grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s));
   LOG_TEST("test_no_op_with_port_and_start");
-  int port;
+  int port = -1;
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
   resolved_addr.len = sizeof(struct sockaddr_in);
@@ -200,74 +242,115 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote,
-                        socklen_t remote_len, on_connect_result *result) {
-  gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
-  int clifd = socket(remote->sa_family, SOCK_STREAM, 0);
+static grpc_error *tcp_connect(grpc_exec_ctx *exec_ctx, const test_addr *remote,
+                               on_connect_result *result) {
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10);
+  int clifd;
   int nconnects_before;
+  const struct sockaddr *remote_addr =
+      (const struct sockaddr *)remote->addr.addr;
 
+  gpr_log(GPR_INFO, "Connecting to %s", remote->str);
   gpr_mu_lock(g_mu);
   nconnects_before = g_nconnects;
   on_connect_result_init(&g_result);
-  GPR_ASSERT(clifd >= 0);
-  gpr_log(GPR_DEBUG, "start connect");
-  GPR_ASSERT(connect(clifd, remote, remote_len) == 0);
+  clifd = socket(remote_addr->sa_family, SOCK_STREAM, 0);
+  if (clifd < 0) {
+    gpr_mu_unlock(g_mu);
+    return GRPC_OS_ERROR(errno, "Failed to create socket");
+  }
+  gpr_log(GPR_DEBUG, "start connect to %s", remote->str);
+  if (connect(clifd, remote_addr, (socklen_t)remote->addr.len) != 0) {
+    gpr_mu_unlock(g_mu);
+    close(clifd);
+    return GRPC_OS_ERROR(errno, "connect");
+  }
   gpr_log(GPR_DEBUG, "wait");
   while (g_nconnects == nconnects_before &&
          gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0) {
     grpc_pollset_worker *worker = NULL;
-    GPR_ASSERT(GRPC_LOG_IF_ERROR(
-        "pollset_work",
-        grpc_pollset_work(exec_ctx, g_pollset, &worker,
-                          gpr_now(GPR_CLOCK_MONOTONIC), deadline)));
+    grpc_error *err;
+    if ((err = grpc_pollset_work(exec_ctx, g_pollset, &worker,
+                                 gpr_now(GPR_CLOCK_MONOTONIC), deadline)) !=
+        GRPC_ERROR_NONE) {
+      gpr_mu_unlock(g_mu);
+      close(clifd);
+      return err;
+    }
     gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(exec_ctx);
     gpr_mu_lock(g_mu);
   }
   gpr_log(GPR_DEBUG, "wait done");
-  GPR_ASSERT(g_nconnects == nconnects_before + 1);
+  if (g_nconnects != nconnects_before + 1) {
+    gpr_mu_unlock(g_mu);
+    close(clifd);
+    return GRPC_ERROR_CREATE("Didn't connect");
+  }
   close(clifd);
   *result = g_result;
 
   gpr_mu_unlock(g_mu);
+  gpr_log(GPR_INFO, "Result (%d, %d) fd %d", result->port_index,
+          result->fd_index, result->server_fd);
+  grpc_tcp_server_unref(exec_ctx, result->server);
+  return GRPC_ERROR_NONE;
 }
 
-/* Tests a tcp server with multiple ports. TODO(daniel-j-born): Multiple fds for
-   the same port should be tested. */
-static void test_connect(unsigned n) {
+/* Tests a tcp server on "::" listeners with multiple ports. If channel_args is
+   non-NULL, pass them to the server. If dst_addrs is non-NULL, use valid addrs
+   as destination addrs (port is not set). If dst_addrs is NULL, use listener
+   addrs as destination addrs. If test_dst_addrs is true, test connectivity with
+   each destination address, set grpc_resolved_address::len=0 for failures, but
+   don't fail the overall unitest. */
+static void test_connect(size_t num_connects,
+                         const grpc_channel_args *channel_args,
+                         test_addrs *dst_addrs, bool test_dst_addrs) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_resolved_address resolved_addr;
   grpc_resolved_address resolved_addr1;
-  struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr;
-  struct sockaddr_storage *addr1 =
+  struct sockaddr_storage *const addr =
+      (struct sockaddr_storage *)resolved_addr.addr;
+  struct sockaddr_storage *const addr1 =
       (struct sockaddr_storage *)resolved_addr1.addr;
   unsigned svr_fd_count;
+  int port;
   int svr_port;
   unsigned svr1_fd_count;
   int svr1_port;
   grpc_tcp_server *s;
+  const unsigned num_ports = 2;
   GPR_ASSERT(GRPC_ERROR_NONE ==
-             grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s));
-  unsigned i;
+             grpc_tcp_server_create(&exec_ctx, NULL, channel_args, &s));
+  unsigned port_num;
   server_weak_ref weak_ref;
   server_weak_ref_init(&weak_ref);
+  server_weak_ref_set(&weak_ref, s);
   LOG_TEST("test_connect");
-  gpr_log(GPR_INFO, "clients=%d", n);
+  gpr_log(GPR_INFO,
+          "clients=%lu, num chan args=%lu, remote IP=%s, test_dst_addrs=%d",
+          (unsigned long)num_connects,
+          (unsigned long)(channel_args != NULL ? channel_args->num_args : 0),
+          dst_addrs != NULL ? "<specific>" : "::", test_dst_addrs);
   memset(&resolved_addr, 0, sizeof(resolved_addr));
   memset(&resolved_addr1, 0, sizeof(resolved_addr1));
   resolved_addr.len = sizeof(struct sockaddr_storage);
   resolved_addr1.len = sizeof(struct sockaddr_storage);
   addr->ss_family = addr1->ss_family = AF_INET;
-  GPR_ASSERT(GRPC_ERROR_NONE ==
-             grpc_tcp_server_add_port(s, &resolved_addr, &svr_port));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "grpc_tcp_server_add_port",
+      grpc_tcp_server_add_port(s, &resolved_addr, &svr_port)));
+  gpr_log(GPR_INFO, "Allocated port %d", svr_port);
   GPR_ASSERT(svr_port > 0);
   /* Cannot use wildcard (port==0), because add_port() will try to reuse the
      same port as a previous add_port(). */
   svr1_port = grpc_pick_unused_port_or_die();
+  GPR_ASSERT(svr1_port > 0);
+  gpr_log(GPR_INFO, "Picked unused port %d", svr1_port);
   grpc_sockaddr_set_port(&resolved_addr1, svr1_port);
-  GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1, &svr_port) ==
+  GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1, &port) ==
                  GRPC_ERROR_NONE &&
-             svr_port == svr1_port);
+             port == svr1_port);
 
   /* Bad port_index. */
   GPR_ASSERT(grpc_tcp_server_port_fd_count(s, 2) == 0);
@@ -283,58 +366,70 @@
   svr1_fd_count = grpc_tcp_server_port_fd_count(s, 1);
   GPR_ASSERT(svr1_fd_count >= 1);
 
-  for (i = 0; i < svr_fd_count; ++i) {
-    int fd = grpc_tcp_server_port_fd(s, 0, i);
-    GPR_ASSERT(fd >= 0);
-    if (i == 0) {
-      GPR_ASSERT(getsockname(fd, (struct sockaddr *)addr,
-                             (socklen_t *)&resolved_addr.len) == 0);
-      GPR_ASSERT(resolved_addr.len <= sizeof(*addr));
-    }
-  }
-  for (i = 0; i < svr1_fd_count; ++i) {
-    int fd = grpc_tcp_server_port_fd(s, 1, i);
-    GPR_ASSERT(fd >= 0);
-    if (i == 0) {
-      GPR_ASSERT(getsockname(fd, (struct sockaddr *)addr1,
-                             (socklen_t *)&resolved_addr1.len) == 0);
-      GPR_ASSERT(resolved_addr1.len <= sizeof(*addr1));
-    }
-  }
-
   grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL);
 
-  for (i = 0; i < n; i++) {
-    on_connect_result result;
-    int svr_fd;
-    on_connect_result_init(&result);
-    tcp_connect(&exec_ctx, (struct sockaddr *)addr,
-                (socklen_t)resolved_addr.len, &result);
-    GPR_ASSERT(result.server_fd >= 0);
-    svr_fd = result.server_fd;
-    GPR_ASSERT(grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) ==
-               result.server_fd);
-    GPR_ASSERT(result.port_index == 0);
-    GPR_ASSERT(result.fd_index < svr_fd_count);
-    GPR_ASSERT(result.server == s);
-    if (weak_ref.server == NULL) {
-      server_weak_ref_set(&weak_ref, result.server);
+  if (dst_addrs != NULL) {
+    int ports[] = {svr_port, svr1_port};
+    for (port_num = 0; port_num < num_ports; ++port_num) {
+      size_t dst_idx;
+      size_t num_tested = 0;
+      for (dst_idx = 0; dst_idx < dst_addrs->naddrs; ++dst_idx) {
+        test_addr dst = dst_addrs->addrs[dst_idx];
+        on_connect_result result;
+        grpc_error *err;
+        if (dst.addr.len == 0) {
+          gpr_log(GPR_DEBUG, "Skipping test of non-functional local IP %s",
+                  dst.str);
+          continue;
+        }
+        GPR_ASSERT(grpc_sockaddr_set_port(&dst.addr, ports[port_num]));
+        test_addr_init_str(&dst);
+        ++num_tested;
+        on_connect_result_init(&result);
+        if ((err = tcp_connect(&exec_ctx, &dst, &result)) == GRPC_ERROR_NONE &&
+            result.server_fd >= 0 && result.server == s) {
+          continue;
+        }
+        gpr_log(GPR_ERROR, "Failed to connect to %s: %s", dst.str,
+                grpc_error_string(err));
+        GPR_ASSERT(test_dst_addrs);
+        dst_addrs->addrs[dst_idx].addr.len = 0;
+        GRPC_ERROR_UNREF(err);
+      }
+      GPR_ASSERT(num_tested > 0);
     }
-    grpc_tcp_server_unref(&exec_ctx, result.server);
-
-    on_connect_result_init(&result);
-    tcp_connect(&exec_ctx, (struct sockaddr *)addr1,
-                (socklen_t)resolved_addr1.len, &result);
-    GPR_ASSERT(result.server_fd >= 0);
-    GPR_ASSERT(result.server_fd != svr_fd);
-    GPR_ASSERT(grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) ==
-               result.server_fd);
-    GPR_ASSERT(result.port_index == 1);
-    GPR_ASSERT(result.fd_index < svr_fd_count);
-    GPR_ASSERT(result.server == s);
-    grpc_tcp_server_unref(&exec_ctx, result.server);
+  } else {
+    for (port_num = 0; port_num < num_ports; ++port_num) {
+      const unsigned num_fds = grpc_tcp_server_port_fd_count(s, port_num);
+      unsigned fd_num;
+      for (fd_num = 0; fd_num < num_fds; ++fd_num) {
+        int fd = grpc_tcp_server_port_fd(s, port_num, fd_num);
+        size_t connect_num;
+        test_addr dst;
+        GPR_ASSERT(fd >= 0);
+        dst.addr.len = sizeof(dst.addr.addr);
+        GPR_ASSERT(getsockname(fd, (struct sockaddr *)dst.addr.addr,
+                               (socklen_t *)&dst.addr.len) == 0);
+        GPR_ASSERT(dst.addr.len <= sizeof(dst.addr.addr));
+        test_addr_init_str(&dst);
+        gpr_log(GPR_INFO, "(%d, %d) fd %d family %s listening on %s", port_num,
+                fd_num, fd, sock_family_name(addr->ss_family), dst.str);
+        for (connect_num = 0; connect_num < num_connects; ++connect_num) {
+          on_connect_result result;
+          on_connect_result_init(&result);
+          GPR_ASSERT(GRPC_LOG_IF_ERROR("tcp_connect",
+                                       tcp_connect(&exec_ctx, &dst, &result)));
+          GPR_ASSERT(result.server_fd == fd);
+          GPR_ASSERT(result.port_index == port_num);
+          GPR_ASSERT(result.fd_index == fd_num);
+          GPR_ASSERT(result.server == s);
+          GPR_ASSERT(
+              grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) ==
+              result.server_fd);
+        }
+      }
+    }
   }
-
   /* Weak ref to server valid until final unref. */
   GPR_ASSERT(weak_ref.server != NULL);
   GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 0) >= 0);
@@ -354,17 +449,60 @@
 int main(int argc, char **argv) {
   grpc_closure destroyed;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_arg chan_args[] = {
+      {GRPC_ARG_INTEGER, GRPC_ARG_EXPAND_WILDCARD_ADDRS, {.integer = 1}}};
+  const grpc_channel_args channel_args = {1, chan_args};
+  struct ifaddrs *ifa = NULL;
+  struct ifaddrs *ifa_it;
+  test_addrs dst_addrs;
   grpc_test_init(argc, argv);
   grpc_init();
-  g_pollset = gpr_malloc(grpc_pollset_size());
+  g_pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(g_pollset, &g_mu);
 
   test_no_op();
   test_no_op_with_start();
   test_no_op_with_port();
   test_no_op_with_port_and_start();
-  test_connect(1);
-  test_connect(10);
+
+  if (getifaddrs(&ifa) != 0 || ifa == NULL) {
+    gpr_log(GPR_ERROR, "getifaddrs: %s", strerror(errno));
+    return EXIT_FAILURE;
+  }
+  dst_addrs.naddrs = 0;
+  for (ifa_it = ifa; ifa_it != NULL && dst_addrs.naddrs < MAX_ADDRS;
+       ifa_it = ifa_it->ifa_next) {
+    if (ifa_it->ifa_addr == NULL) {
+      continue;
+    } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
+      dst_addrs.addrs[dst_addrs.naddrs].addr.len = sizeof(struct sockaddr_in);
+    } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
+      dst_addrs.addrs[dst_addrs.naddrs].addr.len = sizeof(struct sockaddr_in6);
+    } else {
+      continue;
+    }
+    memcpy(dst_addrs.addrs[dst_addrs.naddrs].addr.addr, ifa_it->ifa_addr,
+           dst_addrs.addrs[dst_addrs.naddrs].addr.len);
+    GPR_ASSERT(
+        grpc_sockaddr_set_port(&dst_addrs.addrs[dst_addrs.naddrs].addr, 0));
+    test_addr_init_str(&dst_addrs.addrs[dst_addrs.naddrs]);
+    ++dst_addrs.naddrs;
+  }
+  freeifaddrs(ifa);
+  ifa = NULL;
+
+  /* Connect to same addresses as listeners. */
+  test_connect(1, NULL, NULL, false);
+  test_connect(10, NULL, NULL, false);
+
+  /* Set dst_addrs.addrs[i].len=0 for dst_addrs that are unreachable with a "::"
+     listener. */
+  test_connect(1, NULL, &dst_addrs, true);
+
+  /* Test connect(2) with dst_addrs. */
+  test_connect(1, &channel_args, &dst_addrs, false);
+  /* Test connect(2) with dst_addrs. */
+  test_connect(10, &channel_args, &dst_addrs, false);
 
   grpc_closure_init(&destroyed, destroy_pollset, g_pollset,
                     grpc_schedule_on_exec_ctx);
@@ -372,7 +510,7 @@
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
   gpr_free(g_pollset);
-  return 0;
+  return EXIT_SUCCESS;
 }
 
 #else /* GRPC_POSIX_SOCKET */
diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c
index e121040..d57a37b 100644
--- a/test/core/iomgr/udp_server_test.c
+++ b/test/core/iomgr/udp_server_test.c
@@ -58,6 +58,7 @@
 static grpc_pollset *g_pollset;
 static gpr_mu *g_mu;
 static int g_number_of_reads = 0;
+static int g_number_of_writes = 0;
 static int g_number_of_bytes_read = 0;
 static int g_number_of_orphan_calls = 0;
 
@@ -78,7 +79,16 @@
   gpr_mu_unlock(g_mu);
 }
 
-static void on_fd_orphaned(grpc_fd *emfd) {
+static void on_write(grpc_exec_ctx *exec_ctx, grpc_fd *emfd) {
+  gpr_mu_lock(g_mu);
+  g_number_of_writes++;
+
+  GPR_ASSERT(
+      GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, NULL)));
+  gpr_mu_unlock(g_mu);
+}
+
+static void on_fd_orphaned(grpc_exec_ctx *exec_ctx, grpc_fd *emfd) {
   gpr_log(GPR_INFO, "gRPC FD about to be orphaned: %d",
           grpc_fd_wrapped_fd(emfd));
   g_number_of_orphan_calls++;
@@ -111,8 +121,8 @@
   memset(&resolved_addr, 0, sizeof(resolved_addr));
   resolved_addr.len = sizeof(struct sockaddr_in);
   addr->sin_family = AF_INET;
-  GPR_ASSERT(
-      grpc_udp_server_add_port(s, &resolved_addr, on_read, on_fd_orphaned));
+  GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write,
+                                      on_fd_orphaned));
 
   grpc_udp_server_destroy(&exec_ctx, s, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -132,8 +142,8 @@
   memset(&resolved_addr, 0, sizeof(resolved_addr));
   resolved_addr.len = sizeof(struct sockaddr_in);
   addr->sin_family = AF_INET;
-  GPR_ASSERT(
-      grpc_udp_server_add_port(s, &resolved_addr, on_read, on_fd_orphaned));
+  GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write,
+                                      on_fd_orphaned));
 
   grpc_udp_server_start(&exec_ctx, s, NULL, 0, NULL);
 
@@ -164,8 +174,8 @@
   memset(&resolved_addr, 0, sizeof(resolved_addr));
   resolved_addr.len = sizeof(struct sockaddr_storage);
   addr->ss_family = AF_INET;
-  GPR_ASSERT(
-      grpc_udp_server_add_port(s, &resolved_addr, on_read, on_fd_orphaned));
+  GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, on_read, on_write,
+                                      on_fd_orphaned));
 
   svrfd = grpc_udp_server_get_fd(s, 0);
   GPR_ASSERT(svrfd >= 0);
@@ -179,7 +189,7 @@
   gpr_mu_lock(g_mu);
 
   for (i = 0; i < number_of_clients; i++) {
-    deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
+    deadline = grpc_timeout_seconds_to_deadline(10);
 
     number_of_reads_before = g_number_of_reads;
     /* Create a socket, send a packet to the UDP server. */
@@ -212,6 +222,9 @@
   /* The server had a single FD, which is orphaned once in *
    * deactivated_all_ports, and once in grpc_udp_server_destroy. */
   GPR_ASSERT(g_number_of_orphan_calls == 2);
+
+  /* The write callback should have fired a few times. */
+  GPR_ASSERT(g_number_of_writes > 0);
 }
 
 static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
@@ -224,7 +237,7 @@
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  g_pollset = gpr_malloc(grpc_pollset_size());
+  g_pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(g_pollset, &g_mu);
 
   test_no_op();
diff --git a/test/core/json/BUILD b/test/core/json/BUILD
index 05d4c6e..f5a877e 100644
--- a/test/core/json/BUILD
+++ b/test/core/json/BUILD
@@ -1,4 +1,4 @@
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -39,3 +39,32 @@
   copts = ["-std=c99"],
 )
 
+cc_binary(
+    name = "json_rewrite",
+    srcs = ["json_rewrite.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    testonly = 1,
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "json_rewrite_test",
+    srcs = ["json_rewrite_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99'],
+    data = ["rewrite_test_input.json", "rewrite_test_output_condensed.json", "rewrite_test_output_indented.json", ":json_stream_error_test"]
+)
+
+cc_test(
+    name = "json_stream_error_test",
+    srcs = ["json_stream_error_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "json_test",
+    srcs = ["json_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c
index 827a395..09f0e2d 100644
--- a/test/core/memory_usage/client.c
+++ b/test/core/memory_usage/client.c
@@ -58,8 +58,7 @@
   grpc_call *call;
   grpc_metadata_array initial_metadata_recv;
   grpc_status_code status;
-  char *details;
-  size_t details_capacity;
+  grpc_slice details;
   grpc_metadata_array trailing_metadata_recv;
 } fling_call;
 
@@ -86,9 +85,11 @@
       &calls[call_idx].initial_metadata_recv;
   op++;
 
+  grpc_slice hostname = grpc_slice_from_static_string("localhost");
   calls[call_idx].call = grpc_channel_create_call(
-      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/Reflector/reflectUnary",
-      "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/Reflector/reflectUnary"), &hostname,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call,
                                                    metadata_ops,
@@ -108,8 +109,6 @@
       &calls[call_idx].trailing_metadata_recv;
   op->data.recv_status_on_client.status = &calls[call_idx].status;
   op->data.recv_status_on_client.status_details = &calls[call_idx].details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &calls[call_idx].details_capacity;
   op++;
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call,
@@ -119,13 +118,13 @@
   grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv);
   grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv);
-  gpr_free(calls[call_idx].details);
+  grpc_slice_unref(calls[call_idx].details);
   grpc_call_destroy(calls[call_idx].call);
   calls[call_idx].call = NULL;
 }
 
-static struct grpc_memory_counters send_snapshot_request(
-    int call_idx, const char *call_type) {
+static struct grpc_memory_counters send_snapshot_request(int call_idx,
+                                                         grpc_slice call_type) {
   grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv);
   grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv);
 
@@ -151,12 +150,11 @@
       &calls[call_idx].trailing_metadata_recv;
   op->data.recv_status_on_client.status = &calls[call_idx].status;
   op->data.recv_status_on_client.status_details = &calls[call_idx].details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &calls[call_idx].details_capacity;
   op++;
 
+  grpc_slice hostname = grpc_slice_from_static_string("localhost");
   calls[call_idx].call = grpc_channel_create_call(
-      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, call_type, "localhost",
+      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, call_type, &hostname,
       gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(
                                  calls[call_idx].call, snapshot_ops,
@@ -186,9 +184,8 @@
   grpc_slice_unref(response);
   grpc_byte_buffer_reader_destroy(&reader);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(calls[call_idx].details);
-  calls[call_idx].details = NULL;
-  calls[call_idx].details_capacity = 0;
+  grpc_slice_unref(calls[call_idx].details);
+  calls[call_idx].details = grpc_empty_slice();
   grpc_call_destroy(calls[call_idx].call);
   calls[call_idx].call = NULL;
 
@@ -221,9 +218,8 @@
   gpr_cmdline_parse(cl, argc, argv);
   gpr_cmdline_destroy(cl);
 
-  for (int k = 0; k < (int)(sizeof(calls) / sizeof(fling_call)); k++) {
-    calls[k].details = NULL;
-    calls[k].details_capacity = 0;
+  for (size_t k = 0; k < GPR_ARRAY_SIZE(calls); k++) {
+    calls[k].details = grpc_empty_slice();
   }
 
   cq = grpc_completion_queue_create(NULL);
@@ -234,10 +230,10 @@
 
   int call_idx = 0;
 
-  struct grpc_memory_counters before_server_create =
-      send_snapshot_request(0, "Reflector/GetBeforeSvrCreation");
-  struct grpc_memory_counters after_server_create =
-      send_snapshot_request(0, "Reflector/GetAfterSvrCreation");
+  struct grpc_memory_counters before_server_create = send_snapshot_request(
+      0, grpc_slice_from_static_string("Reflector/GetBeforeSvrCreation"));
+  struct grpc_memory_counters after_server_create = send_snapshot_request(
+      0, grpc_slice_from_static_string("Reflector/GetAfterSvrCreation"));
 
   // warmup period
   for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) {
@@ -245,7 +241,8 @@
   }
 
   struct grpc_memory_counters server_benchmark_calls_start =
-      send_snapshot_request(0, "Reflector/SimpleSnapshot");
+      send_snapshot_request(
+          0, grpc_slice_from_static_string("Reflector/SimpleSnapshot"));
 
   struct grpc_memory_counters client_benchmark_calls_start =
       grpc_memory_counters_snapshot();
@@ -258,8 +255,8 @@
   struct grpc_memory_counters client_calls_inflight =
       grpc_memory_counters_snapshot();
 
-  struct grpc_memory_counters server_calls_inflight =
-      send_snapshot_request(0, "Reflector/DestroyCalls");
+  struct grpc_memory_counters server_calls_inflight = send_snapshot_request(
+      0, grpc_slice_from_static_string("Reflector/DestroyCalls"));
 
   do {
     event = grpc_completion_queue_next(
@@ -274,8 +271,8 @@
     finish_ping_pong_request(call_idx + 1);
   }
 
-  struct grpc_memory_counters server_calls_end =
-      send_snapshot_request(0, "Reflector/SimpleSnapshot");
+  struct grpc_memory_counters server_calls_end = send_snapshot_request(
+      0, grpc_slice_from_static_string("Reflector/SimpleSnapshot"));
 
   struct grpc_memory_counters client_channel_end =
       grpc_memory_counters_snapshot();
diff --git a/test/core/memory_usage/server.c b/test/core/memory_usage/server.c
index cd7f2aa..ab059c2 100644
--- a/test/core/memory_usage/server.c
+++ b/test/core/memory_usage/server.c
@@ -110,7 +110,8 @@
   status_op.op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   status_op.data.send_status_from_server.status = GRPC_STATUS_OK;
   status_op.data.send_status_from_server.trailing_metadata_count = 0;
-  status_op.data.send_status_from_server.status_details = "";
+  grpc_slice details = grpc_slice_from_static_string("");
+  status_op.data.send_status_from_server.status_details = &details;
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call,
                                                    &status_op, 1, tag, NULL));
@@ -140,7 +141,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
   op->data.send_status_from_server.trailing_metadata_count = 0;
-  op->data.send_status_from_server.status_details = "";
+  grpc_slice details = grpc_slice_from_static_string("");
+  op->data.send_status_from_server.status_details = &details;
   op++;
   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
   op->data.recv_close_on_server.cancelled = &was_cancelled;
@@ -230,7 +232,7 @@
       gpr_log(GPR_INFO, "Shutting down due to SIGINT");
       grpc_server_shutdown_and_notify(server, cq, tag(1000));
       GPR_ASSERT(grpc_completion_queue_pluck(
-                     cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                     cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                      .type == GRPC_OP_COMPLETE);
       grpc_completion_queue_shutdown(cq);
       shutdown_started = 1;
@@ -245,25 +247,27 @@
         switch (s->state) {
           case FLING_SERVER_NEW_REQUEST:
             request_call_unary(++next_call_idx);
-            if (0 ==
-                strcmp(s->call_details.method, "/Reflector/reflectUnary")) {
+            if (0 == grpc_slice_str_cmp(s->call_details.method,
+                                        "/Reflector/reflectUnary")) {
               s->state = FLING_SERVER_SEND_INIT_METADATA;
               send_initial_metadata_unary(s);
-            } else if (0 == strcmp(s->call_details.method,
-                                   "Reflector/GetBeforeSvrCreation")) {
+            } else if (0 ==
+                       grpc_slice_str_cmp(s->call_details.method,
+                                          "Reflector/GetBeforeSvrCreation")) {
               s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT;
               send_snapshot(s, &before_server_create);
-            } else if (0 == strcmp(s->call_details.method,
-                                   "Reflector/GetAfterSvrCreation")) {
+            } else if (0 ==
+                       grpc_slice_str_cmp(s->call_details.method,
+                                          "Reflector/GetAfterSvrCreation")) {
               s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT;
               send_snapshot(s, &after_server_create);
-            } else if (0 == strcmp(s->call_details.method,
-                                   "Reflector/SimpleSnapshot")) {
+            } else if (0 == grpc_slice_str_cmp(s->call_details.method,
+                                               "Reflector/SimpleSnapshot")) {
               s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT;
               current_snapshot = grpc_memory_counters_snapshot();
               send_snapshot(s, &current_snapshot);
-            } else if (0 == strcmp(s->call_details.method,
-                                   "Reflector/DestroyCalls")) {
+            } else if (0 == grpc_slice_str_cmp(s->call_details.method,
+                                               "Reflector/DestroyCalls")) {
               s->state = FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL;
               current_snapshot = grpc_memory_counters_snapshot();
               send_snapshot(s, &current_snapshot);
diff --git a/test/core/network_benchmarks/BUILD b/test/core/network_benchmarks/BUILD
new file mode 100644
index 0000000..a5209de
--- /dev/null
+++ b/test/core/network_benchmarks/BUILD
@@ -0,0 +1,37 @@
+# Copyright 2016, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+cc_binary(
+    name = "low_level_ping_pong",
+    srcs = ["low_level_ping_pong.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
new file mode 100644
index 0000000..e750c39
--- /dev/null
+++ b/test/core/security/BUILD
@@ -0,0 +1,104 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
+
+grpc_fuzzer(
+  name = "ssl_server_fuzzer",
+  srcs = ["ssl_server_fuzzer.c"],
+  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
+  corpus = "corpus",
+  copts = ["-std=c99"],
+)
+
+cc_library(
+    name = "oauth2_utils",
+    srcs = ["oauth2_utils.c"],
+    hdrs = ["oauth2_utils.h"],
+    deps = ["//:grpc"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "auth_context_test",
+    srcs = ["auth_context_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "b64_test",
+    srcs = ["b64_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "credentials_test",
+    srcs = ["credentials_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "secure_endpoint_test",
+    srcs = ["secure_endpoint_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/iomgr:endpoint_tests"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "security_connector_test",
+    srcs = ["security_connector_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_binary(
+    name = "create_jwt",
+    srcs = ["create_jwt.c"],
+    deps = ["//:grpc", "//:gpr"],
+    copts = ['-std=c99']
+)
+
+cc_binary(
+    name = "fetch_oauth2",
+    srcs = ["fetch_oauth2.c"],
+    deps = ["//:grpc", "//:gpr", ":oauth2_utils"],
+    copts = ['-std=c99']
+)
+
+cc_binary(
+    name = "verify_jwt",
+    srcs = ["verify_jwt.c"],
+    deps = ["//:grpc", "//:gpr"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 0a79292..c0933c6 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -196,8 +196,8 @@
   grpc_slice value = grpc_slice_from_copied_string(value_str);
   grpc_credentials_md_store_add(store, key, value);
   GPR_ASSERT(store->num_entries == 1);
-  GPR_ASSERT(grpc_slice_cmp(key, store->entries[0].key) == 0);
-  GPR_ASSERT(grpc_slice_cmp(value, store->entries[0].value) == 0);
+  GPR_ASSERT(grpc_slice_eq(key, store->entries[0].key));
+  GPR_ASSERT(grpc_slice_eq(value, store->entries[0].value));
   grpc_slice_unref(key);
   grpc_slice_unref(value);
   grpc_credentials_md_store_unref(&exec_ctx, store);
@@ -1065,9 +1065,8 @@
   *s = PLUGIN_GET_METADATA_CALLED_STATE;
   for (i = 0; i < GPR_ARRAY_SIZE(plugin_md); i++) {
     memset(&md[i], 0, sizeof(grpc_metadata));
-    md[i].key = plugin_md[i].key;
-    md[i].value = plugin_md[i].value;
-    md[i].value_length = strlen(plugin_md[i].value);
+    md[i].key = grpc_slice_from_copied_string(plugin_md[i].key);
+    md[i].value = grpc_slice_from_copied_string(plugin_md[i].value);
   }
   cb(user_data, md, GPR_ARRAY_SIZE(md), GRPC_STATUS_OK, NULL);
 }
diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c
index a9bd976..0a73f67 100644
--- a/test/core/security/jwt_verifier_test.c
+++ b/test/core/security/jwt_verifier_test.c
@@ -386,9 +386,9 @@
   GPR_ASSERT(jwt != NULL);
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_success, (void *)expected_user_data);
+  grpc_jwt_verifier_destroy(&exec_ctx, verifier);
   grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
-  grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
 }
 
@@ -420,9 +420,9 @@
   GPR_ASSERT(jwt != NULL);
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_success, (void *)expected_user_data);
+  grpc_jwt_verifier_destroy(&exec_ctx, verifier);
   grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
-  grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
 }
 
@@ -469,9 +469,9 @@
   GPR_ASSERT(jwt != NULL);
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_success, (void *)expected_user_data);
+  grpc_jwt_verifier_destroy(&exec_ctx, verifier);
   grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
-  grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
 }
 
@@ -511,9 +511,9 @@
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_key_retrieval_error,
                            (void *)expected_user_data);
+  grpc_jwt_verifier_destroy(&exec_ctx, verifier);
   grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
-  grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
 }
 
@@ -534,9 +534,9 @@
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_key_retrieval_error,
                            (void *)expected_user_data);
+  grpc_jwt_verifier_destroy(&exec_ctx, verifier);
   grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
-  grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
 }
 
@@ -588,9 +588,9 @@
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, jwt, expected_audience,
                            on_verification_bad_signature,
                            (void *)expected_user_data);
-  grpc_exec_ctx_finish(&exec_ctx);
   gpr_free(jwt);
-  grpc_jwt_verifier_destroy(verifier);
+  grpc_jwt_verifier_destroy(&exec_ctx, verifier);
+  grpc_exec_ctx_finish(&exec_ctx);
   grpc_httpcli_set_override(NULL, NULL);
 }
 
@@ -619,8 +619,8 @@
   grpc_jwt_verifier_verify(&exec_ctx, verifier, NULL, "bad jwt",
                            expected_audience, on_verification_bad_format,
                            (void *)expected_user_data);
+  grpc_jwt_verifier_destroy(&exec_ctx, verifier);
   grpc_exec_ctx_finish(&exec_ctx);
-  grpc_jwt_verifier_destroy(verifier);
   grpc_httpcli_set_override(NULL, NULL);
 }
 
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index ff77af9..f0550db 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -87,7 +87,7 @@
   grpc_closure do_nothing_closure;
   grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL};
 
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &request.mu);
   request.pops = grpc_polling_entity_create_from_pollset(pollset);
   request.is_done = 0;
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index 2b74690..b6421f1 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -63,7 +63,7 @@
   } else {
     char *token;
     GPR_ASSERT(num_md == 1);
-    token = grpc_dump_slice(md_elems[0].value, GPR_DUMP_ASCII);
+    token = grpc_slice_to_c_string(md_elems[0].value);
     printf("\nGot token: %s\n\n", token);
     gpr_free(token);
   }
@@ -98,7 +98,7 @@
     goto end;
   }
 
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &sync.mu);
   sync.pops = grpc_polling_entity_create_from_pollset(pollset);
   sync.is_done = 0;
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index e1d6ff9..d2b76ba 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -164,10 +164,12 @@
   grpc_exec_ctx_finish(&exec_ctx);
   GPR_ASSERT(n == 1);
   GPR_ASSERT(incoming.count == 1);
-  GPR_ASSERT(0 == grpc_slice_cmp(s, incoming.slices[0]));
+  GPR_ASSERT(grpc_slice_eq(s, incoming.slices[0]));
 
-  grpc_endpoint_shutdown(&exec_ctx, f.client_ep);
-  grpc_endpoint_shutdown(&exec_ctx, f.server_ep);
+  grpc_endpoint_shutdown(&exec_ctx, f.client_ep,
+                         GRPC_ERROR_CREATE("test_leftover end"));
+  grpc_endpoint_shutdown(&exec_ctx, f.server_ep,
+                         GRPC_ERROR_CREATE("test_leftover end"));
   grpc_endpoint_destroy(&exec_ctx, f.client_ep);
   grpc_endpoint_destroy(&exec_ctx, f.server_ep);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -188,7 +190,7 @@
   grpc_test_init(argc, argv);
 
   grpc_init();
-  g_pollset = gpr_malloc(grpc_pollset_size());
+  g_pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(g_pollset, &g_mu);
   grpc_endpoint_tests(configs[0], g_pollset, g_mu);
   test_leftover(configs[1], 1);
diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c
index 8872cbe..4219b13 100644
--- a/test/core/security/security_connector_test.c
+++ b/test/core/security/security_connector_test.c
@@ -370,7 +370,7 @@
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
   grpc_set_ssl_roots_override_callback(override_roots_success);
   grpc_slice roots = grpc_get_default_ssl_roots_for_testing();
-  char *roots_contents = grpc_dump_slice(roots, GPR_DUMP_ASCII);
+  char *roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
   gpr_free(roots_contents);
@@ -379,7 +379,7 @@
      instead. */
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path);
   roots = grpc_get_default_ssl_roots_for_testing();
-  roots_contents = grpc_dump_slice(roots, GPR_DUMP_ASCII);
+  roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0);
   gpr_free(roots_contents);
@@ -388,7 +388,7 @@
      the api. */
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
   roots = grpc_get_default_ssl_roots_for_testing();
-  roots_contents = grpc_dump_slice(roots, GPR_DUMP_ASCII);
+  roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
   gpr_free(roots_contents);
diff --git a/test/core/security/ssl_server_fuzzer.c b/test/core/security/ssl_server_fuzzer.c
index 55e8f5e..f789278 100644
--- a/test/core/security/ssl_server_fuzzer.c
+++ b/test/core/security/ssl_server_fuzzer.c
@@ -121,7 +121,8 @@
   // server will wait for more data. Explicitly fail the server by shutting down
   // the endpoint.
   if (!state.done_callback_called) {
-    grpc_endpoint_shutdown(&exec_ctx, mock_endpoint);
+    grpc_endpoint_shutdown(&exec_ctx, mock_endpoint,
+                           GRPC_ERROR_CREATE("Explicit close"));
     grpc_exec_ctx_flush(&exec_ctx);
   }
 
diff --git a/test/core/security/verify_jwt.c b/test/core/security/verify_jwt.c
index bbd4a67..f8a7d64 100644
--- a/test/core/security/verify_jwt.c
+++ b/test/core/security/verify_jwt.c
@@ -106,7 +106,7 @@
 
   grpc_init();
 
-  sync.pollset = gpr_malloc(grpc_pollset_size());
+  sync.pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(sync.pollset, &sync.mu);
   sync.is_done = 0;
 
@@ -123,14 +123,15 @@
                               gpr_inf_future(GPR_CLOCK_MONOTONIC))))
       sync.is_done = true;
     gpr_mu_unlock(sync.mu);
-    grpc_exec_ctx_finish(&exec_ctx);
+    grpc_exec_ctx_flush(&exec_ctx);
     gpr_mu_lock(sync.mu);
   }
   gpr_mu_unlock(sync.mu);
 
   gpr_free(sync.pollset);
 
-  grpc_jwt_verifier_destroy(verifier);
+  grpc_jwt_verifier_destroy(&exec_ctx, verifier);
+  grpc_exec_ctx_finish(&exec_ctx);
   gpr_cmdline_destroy(cl);
   grpc_shutdown();
   return !sync.success;
diff --git a/test/core/slice/BUILD b/test/core/slice/BUILD
new file mode 100644
index 0000000..67a4706
--- /dev/null
+++ b/test/core/slice/BUILD
@@ -0,0 +1,54 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
+
+grpc_fuzzer(
+  name = "percent_decode_fuzzer",
+  srcs = ["percent_decode_fuzzer.c"],
+  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
+  corpus = "response_corpus",
+  copts = ["-std=c99"],
+)
+
+cc_test(
+    name = "percent_encoding_test",
+    srcs = ["percent_encoding_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "slice_buffer_test",
+    srcs = ["slice_string_helpers_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/slice/percent_encode_fuzzer.c b/test/core/slice/percent_encode_fuzzer.c
index 9698e79..0d440c5 100644
--- a/test/core/slice/percent_encode_fuzzer.c
+++ b/test/core/slice/percent_encode_fuzzer.c
@@ -55,8 +55,8 @@
   grpc_slice permissive_decoded_output =
       grpc_permissive_percent_decode_slice(output);
   // and decoded output must always match the input
-  GPR_ASSERT(grpc_slice_cmp(input, decoded_output) == 0);
-  GPR_ASSERT(grpc_slice_cmp(input, permissive_decoded_output) == 0);
+  GPR_ASSERT(grpc_slice_eq(input, decoded_output));
+  GPR_ASSERT(grpc_slice_eq(input, permissive_decoded_output));
   grpc_slice_unref(input);
   grpc_slice_unref(output);
   grpc_slice_unref(decoded_output);
diff --git a/test/core/slice/percent_encoding_test.c b/test/core/slice/percent_encoding_test.c
index d71c99f..222e695 100644
--- a/test/core/slice/percent_encoding_test.c
+++ b/test/core/slice/percent_encoding_test.c
@@ -81,9 +81,9 @@
   gpr_free(encoded2raw_msg);
   gpr_free(encoded2raw_permissive_msg);
 
-  GPR_ASSERT(0 == grpc_slice_cmp(raw_slice, encoded2raw_slice));
-  GPR_ASSERT(0 == grpc_slice_cmp(raw_slice, encoded2raw_permissive_slice));
-  GPR_ASSERT(0 == grpc_slice_cmp(encoded_slice, raw2encoded_slice));
+  GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_slice));
+  GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_permissive_slice));
+  GPR_ASSERT(grpc_slice_eq(encoded_slice, raw2encoded_slice));
 
   grpc_slice_unref(encoded2raw_slice);
   grpc_slice_unref(encoded2raw_permissive_slice);
@@ -123,8 +123,8 @@
           encoded2raw_permissive_msg);
   gpr_free(encoded2raw_permissive_msg);
 
-  GPR_ASSERT(0 == grpc_slice_cmp(permissive_unencoded_slice,
-                                 encoded2raw_permissive_slice));
+  GPR_ASSERT(
+      grpc_slice_eq(permissive_unencoded_slice, encoded2raw_permissive_slice));
 
   grpc_slice_unref(permissive_unencoded_slice);
   grpc_slice_unref(encoded2raw_permissive_slice);
diff --git a/test/core/slice/slice_test.c b/test/core/slice/slice_test.c
index ca44bec..f68a953 100644
--- a/test/core/slice/slice_test.c
+++ b/test/core/slice/slice_test.c
@@ -35,8 +35,12 @@
 
 #include <string.h>
 
+#include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/static_metadata.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x);
@@ -61,8 +65,10 @@
     GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == length);
     /* If the slice has a refcount, it must be destroyable. */
     if (slice.refcount) {
-      GPR_ASSERT(slice.refcount->ref != NULL);
-      GPR_ASSERT(slice.refcount->unref != NULL);
+      GPR_ASSERT(slice.refcount->vtable != NULL);
+      GPR_ASSERT(slice.refcount->vtable->ref != NULL);
+      GPR_ASSERT(slice.refcount->vtable->unref != NULL);
+      GPR_ASSERT(slice.refcount->vtable->hash != NULL);
     }
     /* We must be able to write to every byte of the data */
     for (i = 0; i < length; i++) {
@@ -249,6 +255,55 @@
   grpc_slice_unref(slice);
 }
 
+static void test_slice_interning(void) {
+  LOG_TEST_NAME("test_slice_interning");
+
+  grpc_init();
+  grpc_slice src1 = grpc_slice_from_copied_string("hello123456789123456789");
+  grpc_slice src2 = grpc_slice_from_copied_string("hello123456789123456789");
+  GPR_ASSERT(GRPC_SLICE_START_PTR(src1) != GRPC_SLICE_START_PTR(src2));
+  grpc_slice interned1 = grpc_slice_intern(src1);
+  grpc_slice interned2 = grpc_slice_intern(src2);
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) ==
+             GRPC_SLICE_START_PTR(interned2));
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) != GRPC_SLICE_START_PTR(src1));
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned2) != GRPC_SLICE_START_PTR(src2));
+  grpc_slice_unref(src1);
+  grpc_slice_unref(src2);
+  grpc_slice_unref(interned1);
+  grpc_slice_unref(interned2);
+  grpc_shutdown();
+}
+
+static void test_static_slice_interning(void) {
+  LOG_TEST_NAME("test_static_slice_interning");
+
+  // grpc_init/grpc_shutdown deliberately omitted: they should not be necessary
+  // to intern a static slice
+
+  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
+    GPR_ASSERT(grpc_slice_is_equivalent(
+        grpc_static_slice_table[i],
+        grpc_slice_intern(grpc_static_slice_table[i])));
+  }
+}
+
+static void test_static_slice_copy_interning(void) {
+  LOG_TEST_NAME("test_static_slice_copy_interning");
+
+  grpc_init();
+
+  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
+    grpc_slice copy = grpc_slice_dup(grpc_static_slice_table[i]);
+    GPR_ASSERT(grpc_static_slice_table[i].refcount != copy.refcount);
+    GPR_ASSERT(grpc_static_slice_table[i].refcount ==
+               grpc_slice_intern(copy).refcount);
+    grpc_slice_unref(copy);
+  }
+
+  grpc_shutdown();
+}
+
 int main(int argc, char **argv) {
   unsigned length;
   grpc_test_init(argc, argv);
@@ -262,5 +317,8 @@
     test_slice_split_tail_works(length);
   }
   test_slice_from_copied_string_works();
+  test_slice_interning();
+  test_static_slice_interning();
+  test_static_slice_copy_interning();
   return 0;
 }
diff --git a/test/core/statistics/census_log_tests.c b/test/core/statistics/census_log_tests.c
index 8646a2f..0f96f01 100644
--- a/test/core/statistics/census_log_tests.c
+++ b/test/core/statistics/census_log_tests.c
@@ -199,7 +199,7 @@
          This should never happen for circular logs. */
       printf("   Writer stalled due to out-of-space: %d out of %d written\n",
              records_written, args->num_records);
-      gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10));
+      gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10));
     }
   }
   /* Done. Decrement count and signal. */
diff --git a/test/core/support/BUILD b/test/core/support/BUILD
index dfe952e..08cee14 100644
--- a/test/core/support/BUILD
+++ b/test/core/support/BUILD
@@ -119,6 +119,13 @@
 )
 
 cc_test(
+    name = "spinlock_test",
+    srcs = ["spinlock_test.c"],
+    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
     name = "sync_test",
     srcs = ["sync_test.c"],
     deps = ["//:gpr", "//test/core/util:gpr_test_util"],
diff --git a/test/core/support/alloc_test.c b/test/core/support/alloc_test.c
index 451c580..72e99de 100644
--- a/test/core/support/alloc_test.c
+++ b/test/core/support/alloc_test.c
@@ -47,7 +47,7 @@
   const gpr_allocation_functions default_fns = gpr_get_allocation_functions();
   intptr_t addr_to_free = 0;
   char *i;
-  gpr_allocation_functions fns = {fake_malloc, fake_realloc, fake_free};
+  gpr_allocation_functions fns = {fake_malloc, NULL, fake_realloc, fake_free};
 
   gpr_set_allocation_functions(fns);
   GPR_ASSERT((void *)(size_t)0xdeadbeef == gpr_malloc(0xdeadbeef));
diff --git a/test/core/support/cpu_test.c b/test/core/support/cpu_test.c
index a5c5244..ca0fe0c 100644
--- a/test/core/support/cpu_test.c
+++ b/test/core/support/cpu_test.c
@@ -81,9 +81,9 @@
   uint32_t cpu;
   unsigned r = 12345678;
   unsigned i, j;
-  for (i = 0; i < 1000 / GRPC_TEST_SLOWDOWN_FACTOR; i++) {
+  for (i = 0; i < 1000 / grpc_test_slowdown_factor(); i++) {
     /* run for a bit - just calculate something random. */
-    for (j = 0; j < 1000000 / GRPC_TEST_SLOWDOWN_FACTOR; j++) {
+    for (j = 0; j < 1000000 / grpc_test_slowdown_factor(); j++) {
       r = (r * 17) & ((r - i) | (r * i));
     }
     cpu = gpr_cpu_current_cpu();
diff --git a/test/core/support/spinlock_test.c b/test/core/support/spinlock_test.c
new file mode 100644
index 0000000..c70e76c
--- /dev/null
+++ b/test/core/support/spinlock_test.c
@@ -0,0 +1,161 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Test of gpr synchronization support. */
+
+#include "src/core/lib/support/spinlock.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "test/core/util/test_config.h"
+
+/* ------------------------------------------------- */
+/* Tests for gpr_spinlock. */
+struct test {
+  int thread_count; /* number of threads */
+  gpr_thd_id *threads;
+
+  int64_t iterations; /* number of iterations per thread */
+  int64_t counter;
+  int incr_step; /* how much to increment/decrement refcount each time */
+
+  gpr_spinlock mu; /* protects iterations, counter */
+};
+
+/* Return pointer to a new struct test. */
+static struct test *test_new(int threads, int64_t iterations, int incr_step) {
+  struct test *m = gpr_malloc(sizeof(*m));
+  m->thread_count = threads;
+  m->threads = gpr_malloc(sizeof(*m->threads) * (size_t)threads);
+  m->iterations = iterations;
+  m->counter = 0;
+  m->thread_count = 0;
+  m->incr_step = incr_step;
+  m->mu = GPR_SPINLOCK_INITIALIZER;
+  return m;
+}
+
+/* Return pointer to a new struct test. */
+static void test_destroy(struct test *m) {
+  gpr_free(m->threads);
+  gpr_free(m);
+}
+
+/* Create m->threads threads, each running (*body)(m) */
+static void test_create_threads(struct test *m, void (*body)(void *arg)) {
+  int i;
+  for (i = 0; i != m->thread_count; i++) {
+    gpr_thd_options opt = gpr_thd_options_default();
+    gpr_thd_options_set_joinable(&opt);
+    GPR_ASSERT(gpr_thd_new(&m->threads[i], body, m, &opt));
+  }
+}
+
+/* Wait until all threads report done. */
+static void test_wait(struct test *m) {
+  int i;
+  for (i = 0; i != m->thread_count; i++) {
+    gpr_thd_join(m->threads[i]);
+  }
+}
+
+/* Test several threads running (*body)(struct test *m) for increasing settings
+   of m->iterations, until about timeout_s to 2*timeout_s seconds have elapsed.
+   If extra!=NULL, run (*extra)(m) in an additional thread.
+   incr_step controls by how much m->refcount should be incremented/decremented
+   (if at all) each time in the tests.
+   */
+static void test(const char *name, void (*body)(void *m), int timeout_s,
+                 int incr_step) {
+  int64_t iterations = 1024;
+  struct test *m;
+  gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
+  gpr_timespec time_taken;
+  gpr_timespec deadline = gpr_time_add(
+      start, gpr_time_from_micros((int64_t)timeout_s * 1000000, GPR_TIMESPAN));
+  fprintf(stderr, "%s:", name);
+  while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) {
+    iterations <<= 1;
+    fprintf(stderr, " %ld", (long)iterations);
+    m = test_new(10, iterations, incr_step);
+    test_create_threads(m, body);
+    test_wait(m);
+    if (m->counter != m->thread_count * m->iterations * m->incr_step) {
+      fprintf(stderr, "counter %ld  threads %d  iterations %ld\n",
+              (long)m->counter, m->thread_count, (long)m->iterations);
+      GPR_ASSERT(0);
+    }
+    test_destroy(m);
+  }
+  time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start);
+  fprintf(stderr, " done %lld.%09d s\n", (long long)time_taken.tv_sec,
+          (int)time_taken.tv_nsec);
+}
+
+/* Increment m->counter on each iteration; then mark thread as done.  */
+static void inc(void *v /*=m*/) {
+  struct test *m = v;
+  int64_t i;
+  for (i = 0; i != m->iterations; i++) {
+    gpr_spinlock_lock(&m->mu);
+    m->counter++;
+    gpr_spinlock_unlock(&m->mu);
+  }
+}
+
+/* Increment m->counter under lock acquired with trylock, m->iterations times;
+   then mark thread as done.  */
+static void inctry(void *v /*=m*/) {
+  struct test *m = v;
+  int64_t i;
+  for (i = 0; i != m->iterations;) {
+    if (gpr_spinlock_trylock(&m->mu)) {
+      m->counter++;
+      gpr_spinlock_unlock(&m->mu);
+      i++;
+    }
+  }
+}
+
+/* ------------------------------------------------- */
+
+int main(int argc, char *argv[]) {
+  grpc_test_init(argc, argv);
+  test("spinlock", &inc, 1, 1);
+  test("spinlock try", &inctry, 1, 1);
+  return 0;
+}
diff --git a/test/core/surface/BUILD b/test/core/surface/BUILD
new file mode 100644
index 0000000..c158413
--- /dev/null
+++ b/test/core/surface/BUILD
@@ -0,0 +1,186 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+cc_test(
+    name = "alarm_test",
+    srcs = ["alarm_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "grpc_byte_buffer_reader_test",
+    srcs = ["byte_buffer_reader_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "channel_create_test",
+    srcs = ["channel_create_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "grpc_completion_queue_test",
+    srcs = ["completion_queue_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "concurrent_connectivity_test",
+    srcs = ["concurrent_connectivity_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "init_test",
+    srcs = ["init_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "grpc_invalid_channel_args_test",
+    srcs = ["invalid_channel_args_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "lame_client_test",
+    srcs = ["lame_client_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:cq_verifier",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "public_headers_must_be_c89",
+    srcs = ["public_headers_must_be_c89.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "secure_channel_create_test",
+    srcs = ["secure_channel_create_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "sequential_connectivity_test",
+    srcs = ["sequential_connectivity_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "server_chttp2_test",
+    srcs = ["server_chttp2_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+cc_test(
+    name = "server_test",
+    srcs = ["server_test.c"],
+    copts = ["-std=c99"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/surface/alarm_test.c b/test/core/surface/alarm_test.c
index 054c328..4afe357 100644
--- a/test/core/surface/alarm_test.c
+++ b/test/core/surface/alarm_test.c
@@ -64,9 +64,9 @@
     grpc_event ev;
     void *tag = create_test_tag();
     grpc_alarm *alarm =
-        grpc_alarm_create(cc, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), tag);
+        grpc_alarm_create(cc, grpc_timeout_seconds_to_deadline(1), tag);
 
-    ev = grpc_completion_queue_next(cc, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2),
+    ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(2),
                                     NULL);
     GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
     GPR_ASSERT(ev.tag == tag);
@@ -78,10 +78,10 @@
     grpc_event ev;
     void *tag = create_test_tag();
     grpc_alarm *alarm =
-        grpc_alarm_create(cc, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2), tag);
+        grpc_alarm_create(cc, grpc_timeout_seconds_to_deadline(2), tag);
 
     grpc_alarm_cancel(alarm);
-    ev = grpc_completion_queue_next(cc, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1),
+    ev = grpc_completion_queue_next(cc, grpc_timeout_seconds_to_deadline(1),
                                     NULL);
     GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
     GPR_ASSERT(ev.tag == tag);
diff --git a/test/core/surface/completion_queue_threading_test.c b/test/core/surface/completion_queue_threading_test.c
index c41ee41..2d55ead 100644
--- a/test/core/surface/completion_queue_threading_test.c
+++ b/test/core/surface/completion_queue_threading_test.c
@@ -98,7 +98,7 @@
   }
 
   /* wait until all other threads are plucking */
-  gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(1000));
+  gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1000));
 
   ev = grpc_completion_queue_pluck(cc, create_test_tag(),
                                    gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
@@ -132,7 +132,7 @@
 } test_thread_options;
 
 gpr_timespec ten_seconds_time(void) {
-  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
+  return grpc_timeout_seconds_to_deadline(10);
 }
 
 static void free_completion(grpc_exec_ctx *exec_ctx, void *arg,
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index 8ebe8d0..ff92738 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -70,11 +70,13 @@
     grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL);
 
     for (int j = 0; j < NUM_INNER_LOOPS; ++j) {
-      gpr_timespec later_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(DELAY_MILLIS);
+      gpr_timespec later_time =
+          grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS);
       grpc_connectivity_state state =
           grpc_channel_check_connectivity_state(chan, 1);
       grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL);
-      gpr_timespec poll_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(POLL_MILLIS);
+      gpr_timespec poll_time =
+          grpc_timeout_milliseconds_to_deadline(POLL_MILLIS);
       GPR_ASSERT(grpc_completion_queue_next(cq, poll_time, NULL).type ==
                  GRPC_OP_COMPLETE);
     }
@@ -107,7 +109,7 @@
                        grpc_tcp_server_acceptor *acceptor) {
   gpr_free(acceptor);
   struct server_thread_args *args = (struct server_thread_args *)vargs;
-  grpc_endpoint_shutdown(exec_ctx, tcp);
+  grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
   grpc_endpoint_destroy(exec_ctx, tcp);
   GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL));
 }
@@ -213,7 +215,7 @@
 
   /* Third round, bogus tcp server */
   gpr_log(GPR_DEBUG, "Wave 3");
-  args.pollset = gpr_malloc(grpc_pollset_size());
+  args.pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(args.pollset, &args.mu);
   gpr_event_init(&args.ready);
   gpr_thd_new(&server, bad_server_thread, &args, &options);
diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c
index b78361a..9deb50b 100644
--- a/test/core/surface/lame_client_test.c
+++ b/test/core/surface/lame_client_test.c
@@ -90,8 +90,7 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   char *peer;
 
   grpc_test_init(argc, argv);
@@ -111,9 +110,10 @@
 
   cq = grpc_completion_queue_create(NULL);
 
+  grpc_slice host = grpc_slice_from_static_string("anywhere");
   call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/Foo", "anywhere",
-                                  GRPC_TIMEOUT_SECONDS_TO_DEADLINE(100), NULL);
+                                  grpc_slice_from_static_string("/Foo"), &host,
+                                  grpc_timeout_seconds_to_deadline(100), NULL);
   GPR_ASSERT(call);
   cqv = cq_verifier_create(cq);
 
@@ -142,7 +142,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -164,7 +163,7 @@
 
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_shutdown();
 
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index e0a2c94..330da46 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -52,6 +52,7 @@
 #include <grpc/impl/codegen/status.h>
 #include <grpc/impl/codegen/sync.h>
 #include <grpc/impl/codegen/sync_generic.h>
+#include <grpc/load_reporting.h>
 #include <grpc/slice.h>
 #include <grpc/slice_buffer.h>
 #include <grpc/status.h>
diff --git a/test/core/surface/secure_channel_create_test.c b/test/core/surface/secure_channel_create_test.c
index ab4067d..567f8ae 100644
--- a/test/core/surface/secure_channel_create_test.c
+++ b/test/core/surface/secure_channel_create_test.c
@@ -43,45 +43,44 @@
 #include "test/core/util/test_config.h"
 
 void test_unknown_scheme_target(void) {
-  grpc_channel *chan;
-  grpc_channel_credentials *creds;
   grpc_resolver_registry_shutdown();
   grpc_resolver_registry_init();
-
-  creds = grpc_fake_transport_security_credentials_create();
-  chan = grpc_secure_channel_create(creds, "blah://blah", NULL, NULL);
-  GPR_ASSERT(chan == NULL);
+  grpc_channel_credentials *creds =
+      grpc_fake_transport_security_credentials_create();
+  grpc_channel *chan =
+      grpc_secure_channel_create(creds, "blah://blah", NULL, NULL);
+  grpc_channel_element *elem =
+      grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0);
+  GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client"));
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test");
   grpc_channel_credentials_unref(&exec_ctx, creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 void test_security_connector_already_in_arg(void) {
-  grpc_channel *chan;
-  grpc_channel_element *elem;
-  grpc_channel_args args;
   grpc_arg arg;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
   arg.type = GRPC_ARG_POINTER;
   arg.value.pointer.p = NULL;
-  arg.key = GRPC_SECURITY_CONNECTOR_ARG;
+  arg.key = GRPC_ARG_SECURITY_CONNECTOR;
+  grpc_channel_args args;
   args.num_args = 1;
   args.args = &arg;
-  chan = grpc_secure_channel_create(NULL, NULL, &args, NULL);
-  elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0);
+  grpc_channel *chan = grpc_secure_channel_create(NULL, NULL, &args, NULL);
+  grpc_channel_element *elem =
+      grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0);
   GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client"));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test");
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 void test_null_creds(void) {
-  grpc_channel *chan;
-  grpc_channel_element *elem;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  chan = grpc_secure_channel_create(NULL, NULL, NULL, NULL);
-  elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0);
+  grpc_channel *chan = grpc_secure_channel_create(NULL, NULL, NULL, NULL);
+  grpc_channel_element *elem =
+      grpc_channel_stack_element(grpc_channel_get_channel_stack(chan), 0);
   GPR_ASSERT(0 == strcmp(elem->filter->name, "lame-client"));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, chan, "test");
   grpc_exec_ctx_finish(&exec_ctx);
 }
diff --git a/test/core/surface/sequential_connectivity_test.c b/test/core/surface/sequential_connectivity_test.c
index 3292718..5f66f90 100644
--- a/test/core/surface/sequential_connectivity_test.c
+++ b/test/core/surface/sequential_connectivity_test.c
@@ -91,7 +91,7 @@
   for (size_t i = 0; i < NUM_CONNECTIONS; i++) {
     channels[i] = fixture->create_channel(addr);
 
-    gpr_timespec connect_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(30);
+    gpr_timespec connect_deadline = grpc_timeout_seconds_to_deadline(30);
     grpc_connectivity_state state;
     while ((state = grpc_channel_check_connectivity_state(channels[i], 1)) !=
            GRPC_CHANNEL_READY) {
diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD
new file mode 100644
index 0000000..865b0c2
--- /dev/null
+++ b/test/core/transport/BUILD
@@ -0,0 +1,72 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+cc_test(
+    name = "bdp_estimator_test",
+    srcs = ["bdp_estimator_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "connectivity_state_test",
+    srcs = ["connectivity_state_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "metadata_test",
+    srcs = ["metadata_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "pid_controller_test",
+    srcs = ["pid_controller_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "status_conversion_test",
+    srcs = ["status_conversion_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "timeout_encoding_test",
+    srcs = ["timeout_encoding_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/transport/bdp_estimator_test.c b/test/core/transport/bdp_estimator_test.c
new file mode 100644
index 0000000..f55a3ca
--- /dev/null
+++ b/test/core/transport/bdp_estimator_test.c
@@ -0,0 +1,153 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/transport/bdp_estimator.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+#include <limits.h>
+#include "src/core/lib/support/string.h"
+#include "test/core/util/test_config.h"
+
+static void test_noop(void) {
+  gpr_log(GPR_INFO, "test_noop");
+  grpc_bdp_estimator est;
+  grpc_bdp_estimator_init(&est, "test");
+}
+
+static void test_get_estimate_no_samples(void) {
+  gpr_log(GPR_INFO, "test_get_estimate_no_samples");
+  grpc_bdp_estimator est;
+  grpc_bdp_estimator_init(&est, "test");
+  int64_t estimate;
+  grpc_bdp_estimator_get_estimate(&est, &estimate);
+}
+
+static void add_samples(grpc_bdp_estimator *estimator, int64_t *samples,
+                        size_t n) {
+  GPR_ASSERT(grpc_bdp_estimator_add_incoming_bytes(estimator, 1234567) == true);
+  grpc_bdp_estimator_schedule_ping(estimator);
+  grpc_bdp_estimator_start_ping(estimator);
+  for (size_t i = 0; i < n; i++) {
+    GPR_ASSERT(grpc_bdp_estimator_add_incoming_bytes(estimator, samples[i]) ==
+               false);
+  }
+  grpc_bdp_estimator_complete_ping(estimator);
+}
+
+static void add_sample(grpc_bdp_estimator *estimator, int64_t sample) {
+  add_samples(estimator, &sample, 1);
+}
+
+static void test_get_estimate_1_sample(void) {
+  gpr_log(GPR_INFO, "test_get_estimate_1_sample");
+  grpc_bdp_estimator est;
+  grpc_bdp_estimator_init(&est, "test");
+  add_sample(&est, 100);
+  int64_t estimate;
+  grpc_bdp_estimator_get_estimate(&est, &estimate);
+}
+
+static void test_get_estimate_2_samples(void) {
+  gpr_log(GPR_INFO, "test_get_estimate_2_samples");
+  grpc_bdp_estimator est;
+  grpc_bdp_estimator_init(&est, "test");
+  add_sample(&est, 100);
+  add_sample(&est, 100);
+  int64_t estimate;
+  grpc_bdp_estimator_get_estimate(&est, &estimate);
+}
+
+static int64_t get_estimate(grpc_bdp_estimator *estimator) {
+  int64_t out;
+  GPR_ASSERT(grpc_bdp_estimator_get_estimate(estimator, &out));
+  return out;
+}
+
+static void test_get_estimate_3_samples(void) {
+  gpr_log(GPR_INFO, "test_get_estimate_3_samples");
+  grpc_bdp_estimator est;
+  grpc_bdp_estimator_init(&est, "test");
+  add_sample(&est, 100);
+  add_sample(&est, 100);
+  add_sample(&est, 100);
+  int64_t estimate;
+  grpc_bdp_estimator_get_estimate(&est, &estimate);
+}
+
+static int64_t next_pow_2(int64_t v) {
+  v--;
+  v |= v >> 1;
+  v |= v >> 2;
+  v |= v >> 4;
+  v |= v >> 8;
+  v |= v >> 16;
+  v |= v >> 32;
+  v++;
+  return v;
+}
+
+static void test_get_estimate_random_values(size_t n) {
+  gpr_log(GPR_INFO, "test_get_estimate_random_values(%" PRIdPTR ")", n);
+  grpc_bdp_estimator est;
+  grpc_bdp_estimator_init(&est, "test");
+  int min = INT_MAX;
+  int max = 65535;  // Windows rand() has limited range, make sure the ASSERT
+                    // passes
+  for (size_t i = 0; i < n; i++) {
+    int sample = rand();
+    if (sample < min) min = sample;
+    if (sample > max) max = sample;
+    add_sample(&est, sample);
+    if (i >= 3) {
+      gpr_log(GPR_DEBUG, "est:%" PRId64 " min:%d max:%d", get_estimate(&est),
+              min, max);
+      GPR_ASSERT(get_estimate(&est) <= 2 * next_pow_2(max));
+    }
+  }
+}
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+  test_noop();
+  test_get_estimate_no_samples();
+  test_get_estimate_1_sample();
+  test_get_estimate_2_samples();
+  test_get_estimate_3_samples();
+  for (size_t i = 3; i < 1000; i = i * 3 / 2) {
+    test_get_estimate_random_values(i);
+  }
+  return 0;
+}
diff --git a/test/core/transport/chttp2/BUILD b/test/core/transport/chttp2/BUILD
index 94b4830..b507e27 100644
--- a/test/core/transport/chttp2/BUILD
+++ b/test/core/transport/chttp2/BUILD
@@ -38,3 +38,58 @@
   corpus = "hpack_parser_corpus"
 )
 
+cc_test(
+    name = "alpn_test",
+    srcs = ["alpn_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "bin_decoder_test",
+    srcs = ["bin_decoder_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "bin_encoder_test",
+    srcs = ["bin_encoder_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "hpack_encoder_test",
+    srcs = ["hpack_encoder_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "hpack_parser_test",
+    srcs = ["hpack_parser_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "hpack_table_test",
+    srcs = ["hpack_table_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "stream_map_test",
+    srcs = ["stream_map_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
+
+cc_test(
+    name = "varint_test",
+    srcs = ["varint_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/transport/chttp2/bin_decoder_test.c b/test/core/transport/chttp2/bin_decoder_test.c
index 221112a..a8b0a75 100644
--- a/test/core/transport/chttp2/bin_decoder_test.c
+++ b/test/core/transport/chttp2/bin_decoder_test.c
@@ -46,7 +46,7 @@
 
 static void expect_slice_eq(grpc_exec_ctx *exec_ctx, grpc_slice expected,
                             grpc_slice slice, char *debug, int line) {
-  if (0 != grpc_slice_cmp(slice, expected)) {
+  if (!grpc_slice_eq(slice, expected)) {
     char *hs = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *he = grpc_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot:  %s\nwant: %s", line, debug, hs,
diff --git a/test/core/transport/chttp2/bin_encoder_test.c b/test/core/transport/chttp2/bin_encoder_test.c
index 53b55a3..bd10a1e 100644
--- a/test/core/transport/chttp2/bin_encoder_test.c
+++ b/test/core/transport/chttp2/bin_encoder_test.c
@@ -48,7 +48,7 @@
 
 static void expect_slice_eq(grpc_slice expected, grpc_slice slice, char *debug,
                             int line) {
-  if (0 != grpc_slice_cmp(slice, expected)) {
+  if (!grpc_slice_eq(slice, expected)) {
     char *hs = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *he = grpc_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot:  %s\nwant: %s", line, debug, hs,
@@ -84,8 +84,8 @@
   grpc_slice input = grpc_slice_from_copied_buffer(s, len);
   grpc_slice base64 = grpc_chttp2_base64_encode(input);
   grpc_slice expect = grpc_chttp2_huffman_compress(base64);
-  grpc_slice got = grpc_chttp2_base64_encode_and_huffman_compress_impl(input);
-  if (0 != grpc_slice_cmp(expect, got)) {
+  grpc_slice got = grpc_chttp2_base64_encode_and_huffman_compress(input);
+  if (!grpc_slice_eq(expect, got)) {
     char *t = grpc_dump_slice(input, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *e = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *g = grpc_dump_slice(got, GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -106,7 +106,7 @@
   expect_combined_equiv(x, sizeof(x) - 1, __LINE__)
 
 static void expect_binary_header(const char *hdr, int binary) {
-  if (grpc_is_binary_header(hdr, strlen(hdr)) != binary) {
+  if (grpc_is_binary_header(grpc_slice_from_static_string(hdr)) != binary) {
     gpr_log(GPR_ERROR, "FAILED: expected header '%s' to be %s", hdr,
             binary ? "binary" : "not binary");
     all_ok = 0;
diff --git a/test/core/transport/chttp2/hpack_encoder_test.c b/test/core/transport/chttp2/hpack_encoder_test.c
index 1fd2540..d572d79 100644
--- a/test/core/transport/chttp2/hpack_encoder_test.c
+++ b/test/core/transport/chttp2/hpack_encoder_test.c
@@ -81,7 +81,9 @@
       e[i - 1].next = &e[i];
       e[i].prev = &e[i - 1];
     }
-    e[i].md = grpc_mdelem_from_strings(exec_ctx, key, value);
+    e[i].md = grpc_mdelem_from_slices(
+        exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)),
+        grpc_slice_intern(grpc_slice_from_static_string(value)));
   }
   e[0].prev = NULL;
   e[nheaders - 1].next = NULL;
@@ -89,6 +91,7 @@
 
   b.list.head = &e[0];
   b.list.tail = &e[nheaders - 1];
+  b.list.count = nheaders;
 
   if (cap_to_delete == num_to_delete) {
     cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000);
@@ -106,7 +109,7 @@
   grpc_slice_buffer_destroy_internal(exec_ctx, &output);
   grpc_metadata_batch_destroy(exec_ctx, &b);
 
-  if (0 != grpc_slice_cmp(merged, expect)) {
+  if (!grpc_slice_eq(merged, expect)) {
     char *expect_str = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *got_str = grpc_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     gpr_log(GPR_ERROR, "mismatched output for %s", expected);
@@ -193,7 +196,9 @@
                                                      const char *key,
                                                      const char *value) {
   grpc_slice_buffer output;
-  grpc_mdelem *elem = grpc_mdelem_from_strings(exec_ctx, key, value);
+  grpc_mdelem elem = grpc_mdelem_from_slices(
+      exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)),
+      grpc_slice_intern(grpc_slice_from_static_string(value)));
   size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
   size_t initial_table_size = g_compressor.table_size;
   grpc_linked_mdelem *e = gpr_malloc(sizeof(*e));
@@ -204,6 +209,7 @@
   e[0].next = NULL;
   b.list.head = &e[0];
   b.list.tail = &e[0];
+  b.list.count = 1;
   grpc_slice_buffer_init(&output);
 
   grpc_transport_one_way_stats stats;
@@ -233,7 +239,7 @@
 
 int main(int argc, char **argv) {
   size_t i;
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   grpc_test_init(argc, argv);
   grpc_init();
   TEST(test_basic_headers);
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/051268ade45dbed0aab896d7d9f4d10ba89d3b09 b/test/core/transport/chttp2/hpack_parser_corpus/051268ade45dbed0aab896d7d9f4d10ba89d3b09
new file mode 100644
index 0000000..70967ff
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/051268ade45dbed0aab896d7d9f4d10ba89d3b09
@@ -0,0 +1 @@
+*¤¤¤ð¤-bin‹c[)(ð¤-bin-'bin	!!?¤Ûð!ð{(-binð	!\	!å7é;?Gí([(!!\ð*¤¤Ûð
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67 b/test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67
new file mode 100644
index 0000000..8f3d4a9
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35 b/test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35
new file mode 100644
index 0000000..d62e767
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada b/test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada
new file mode 100644
index 0000000..44984f3
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f b/test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f
new file mode 100644
index 0000000..ace84af
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44 b/test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44
new file mode 100644
index 0000000..600b6cd
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715 b/test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715
new file mode 100644
index 0000000..49ea908
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715
Binary files differ
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/fcc06696e641a7743bfd2f3b7ecd88e7b727e00a b/test/core/transport/chttp2/hpack_parser_corpus/fcc06696e641a7743bfd2f3b7ecd88e7b727e00a
new file mode 100644
index 0000000..f79c824
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/fcc06696e641a7743bfd2f3b7ecd88e7b727e00a
@@ -0,0 +1 @@
+;?'cð[(!	ð[N!\	!åGý!acceptý.:¤cA)(!)í!¼ª)ågÝI)(Ù;)Š
\ No newline at end of file
diff --git a/test/core/transport/chttp2/hpack_parser_fuzzer_test.c b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
index 4e00f49..e9ac16d 100644
--- a/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
+++ b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
@@ -39,25 +39,26 @@
 #include <grpc/support/log.h>
 
 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
+#include "src/core/lib/slice/slice_internal.h"
 
 bool squelch = true;
 bool leak_check = true;
 
-static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem *md) {
+static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem md) {
   GRPC_MDELEM_UNREF(exec_ctx, md);
 }
 static void dont_log(gpr_log_func_args *args) {}
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   if (squelch) gpr_set_log_function(dont_log);
   grpc_init();
   grpc_chttp2_hpack_parser parser;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_chttp2_hpack_parser_init(&exec_ctx, &parser);
   parser.on_header = onhdr;
-  GRPC_ERROR_UNREF(
-      grpc_chttp2_hpack_parser_parse(&exec_ctx, &parser, data, data + size));
+  GRPC_ERROR_UNREF(grpc_chttp2_hpack_parser_parse(
+      &exec_ctx, &parser, grpc_slice_from_static_buffer(data, size)));
   grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c
index 8f48849..01789c4 100644
--- a/test/core/transport/chttp2/hpack_parser_test.c
+++ b/test/core/transport/chttp2/hpack_parser_test.c
@@ -45,15 +45,15 @@
 
 typedef struct { va_list args; } test_checker;
 
-static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem *md) {
+static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem md) {
   const char *ekey, *evalue;
   test_checker *chk = ud;
   ekey = va_arg(chk->args, char *);
   GPR_ASSERT(ekey);
   evalue = va_arg(chk->args, char *);
   GPR_ASSERT(evalue);
-  GPR_ASSERT(grpc_slice_str_cmp(md->key->slice, ekey) == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(md->value->slice, evalue) == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(md), ekey) == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md), evalue) == 0);
   GRPC_MDELEM_UNREF(exec_ctx, md);
 }
 
@@ -76,9 +76,8 @@
 
   for (i = 0; i < nslices; i++) {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    GPR_ASSERT(grpc_chttp2_hpack_parser_parse(
-                   &exec_ctx, parser, GRPC_SLICE_START_PTR(slices[i]),
-                   GRPC_SLICE_END_PTR(slices[i])) == GRPC_ERROR_NONE);
+    GPR_ASSERT(grpc_chttp2_hpack_parser_parse(&exec_ctx, parser, slices[i]) ==
+               GRPC_ERROR_NONE);
     grpc_exec_ctx_finish(&exec_ctx);
   }
 
diff --git a/test/core/transport/chttp2/hpack_table_test.c b/test/core/transport/chttp2/hpack_table_test.c
index ef2ad66..d2f6d5d 100644
--- a/test/core/transport/chttp2/hpack_table_test.c
+++ b/test/core/transport/chttp2/hpack_table_test.c
@@ -46,16 +46,16 @@
 
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
 
-static void assert_str(const grpc_chttp2_hptbl *tbl, grpc_mdstr *mdstr,
+static void assert_str(const grpc_chttp2_hptbl *tbl, grpc_slice mdstr,
                        const char *str) {
-  GPR_ASSERT(grpc_slice_str_cmp(mdstr->slice, str) == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(mdstr, str) == 0);
 }
 
 static void assert_index(const grpc_chttp2_hptbl *tbl, uint32_t idx,
                          const char *key, const char *value) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(tbl, idx);
-  assert_str(tbl, md->key, key);
-  assert_str(tbl, md->value, value);
+  grpc_mdelem md = grpc_chttp2_hptbl_lookup(tbl, idx);
+  assert_str(tbl, GRPC_MDKEY(md), key);
+  assert_str(tbl, GRPC_MDVALUE(md), value);
 }
 
 static void test_static_lookup(void) {
@@ -143,10 +143,12 @@
   grpc_chttp2_hptbl_init(&exec_ctx, &tbl);
 
   for (i = 0; i < 100000; i++) {
-    grpc_mdelem *elem;
+    grpc_mdelem elem;
     gpr_asprintf(&key, "K:%d", i);
     gpr_asprintf(&value, "VALUE:%d", i);
-    elem = grpc_mdelem_from_strings(&exec_ctx, key, value);
+    elem =
+        grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key),
+                                grpc_slice_from_copied_string(value));
     GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
     GRPC_MDELEM_UNREF(&exec_ctx, elem);
     assert_index(&tbl, 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value);
@@ -169,7 +171,9 @@
                                                  const char *key,
                                                  const char *value) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_mdelem *md = grpc_mdelem_from_strings(&exec_ctx, key, value);
+  grpc_mdelem md =
+      grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key),
+                              grpc_slice_from_copied_string(value));
   grpc_chttp2_hptbl_find_result r = grpc_chttp2_hptbl_find(tbl, md);
   GRPC_MDELEM_UNREF(&exec_ctx, md);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -181,19 +185,24 @@
   grpc_chttp2_hptbl tbl;
   uint32_t i;
   char buffer[32];
-  grpc_mdelem *elem;
+  grpc_mdelem elem;
   grpc_chttp2_hptbl_find_result r;
 
   LOG_TEST("test_find");
 
   grpc_chttp2_hptbl_init(&exec_ctx, &tbl);
-  elem = grpc_mdelem_from_strings(&exec_ctx, "abc", "xyz");
+  elem =
+      grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("abc"),
+                              grpc_slice_from_static_string("xyz"));
   GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(&exec_ctx, elem);
-  elem = grpc_mdelem_from_strings(&exec_ctx, "abc", "123");
+  elem =
+      grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("abc"),
+                              grpc_slice_from_static_string("123"));
   GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(&exec_ctx, elem);
-  elem = grpc_mdelem_from_strings(&exec_ctx, "x", "1");
+  elem = grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("x"),
+                                 grpc_slice_from_static_string("1"));
   GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(&exec_ctx, elem);
 
@@ -244,7 +253,9 @@
   /* overflow the string buffer, check find still works */
   for (i = 0; i < 10000; i++) {
     int64_ttoa(i, buffer);
-    elem = grpc_mdelem_from_strings(&exec_ctx, "test", buffer);
+    elem = grpc_mdelem_from_slices(&exec_ctx,
+                                   grpc_slice_from_static_string("test"),
+                                   grpc_slice_from_copied_string(buffer));
     GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
     GRPC_MDELEM_UNREF(&exec_ctx, elem);
   }
diff --git a/test/core/transport/chttp2/status_conversion_test.c b/test/core/transport/chttp2/status_conversion_test.c
deleted file mode 100644
index f5a5cd1..0000000
--- a/test/core/transport/chttp2/status_conversion_test.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
-#include <grpc/support/log.h>
-#include "test/core/util/test_config.h"
-
-#define GRPC_STATUS_TO_HTTP2_ERROR(a, b) \
-  GPR_ASSERT(grpc_chttp2_grpc_status_to_http2_error(a) == (b))
-#define HTTP2_ERROR_TO_GRPC_STATUS(a, deadline, b) \
-  GPR_ASSERT(grpc_chttp2_http2_error_to_grpc_status(a, deadline) == (b))
-#define GRPC_STATUS_TO_HTTP2_STATUS(a, b) \
-  GPR_ASSERT(grpc_chttp2_grpc_status_to_http2_status(a) == (b))
-#define HTTP2_STATUS_TO_GRPC_STATUS(a, b) \
-  GPR_ASSERT(grpc_chttp2_http2_status_to_grpc_status(a) == (b))
-
-int main(int argc, char **argv) {
-  int i;
-
-  grpc_test_init(argc, argv);
-
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OK, GRPC_CHTTP2_NO_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_CANCELLED, GRPC_CHTTP2_CANCEL);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNKNOWN, GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INVALID_ARGUMENT,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DEADLINE_EXCEEDED, GRPC_CHTTP2_CANCEL);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_NOT_FOUND, GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ALREADY_EXISTS,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_PERMISSION_DENIED,
-                             GRPC_CHTTP2_INADEQUATE_SECURITY);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAUTHENTICATED,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_RESOURCE_EXHAUSTED,
-                             GRPC_CHTTP2_ENHANCE_YOUR_CALM);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_FAILED_PRECONDITION,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ABORTED, GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OUT_OF_RANGE,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNIMPLEMENTED,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INTERNAL, GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAVAILABLE,
-                             GRPC_CHTTP2_REFUSED_STREAM);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DATA_LOSS, GRPC_CHTTP2_INTERNAL_ERROR);
-
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OK, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_CANCELLED, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNKNOWN, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_INVALID_ARGUMENT, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DEADLINE_EXCEEDED, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_NOT_FOUND, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_ALREADY_EXISTS, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_PERMISSION_DENIED, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAUTHENTICATED, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_RESOURCE_EXHAUSTED, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_FAILED_PRECONDITION, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_ABORTED, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OUT_OF_RANGE, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNIMPLEMENTED, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_INTERNAL, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAVAILABLE, 200);
-  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DATA_LOSS, 200);
-
-  const gpr_timespec before_deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_NO_ERROR, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_PROTOCOL_ERROR, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INTERNAL_ERROR, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FLOW_CONTROL_ERROR, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_SETTINGS_TIMEOUT, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_STREAM_CLOSED, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FRAME_SIZE_ERROR, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_REFUSED_STREAM, before_deadline,
-                             GRPC_STATUS_UNAVAILABLE);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CANCEL, before_deadline,
-                             GRPC_STATUS_CANCELLED);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_COMPRESSION_ERROR, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CONNECT_ERROR, before_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_ENHANCE_YOUR_CALM, before_deadline,
-                             GRPC_STATUS_RESOURCE_EXHAUSTED);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INADEQUATE_SECURITY, before_deadline,
-                             GRPC_STATUS_PERMISSION_DENIED);
-
-  const gpr_timespec after_deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_NO_ERROR, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_PROTOCOL_ERROR, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INTERNAL_ERROR, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FLOW_CONTROL_ERROR, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_SETTINGS_TIMEOUT, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_STREAM_CLOSED, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FRAME_SIZE_ERROR, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_REFUSED_STREAM, after_deadline,
-                             GRPC_STATUS_UNAVAILABLE);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CANCEL, after_deadline,
-                             GRPC_STATUS_DEADLINE_EXCEEDED);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_COMPRESSION_ERROR, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CONNECT_ERROR, after_deadline,
-                             GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_ENHANCE_YOUR_CALM, after_deadline,
-                             GRPC_STATUS_RESOURCE_EXHAUSTED);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INADEQUATE_SECURITY, after_deadline,
-                             GRPC_STATUS_PERMISSION_DENIED);
-
-  HTTP2_STATUS_TO_GRPC_STATUS(200, GRPC_STATUS_OK);
-  HTTP2_STATUS_TO_GRPC_STATUS(400, GRPC_STATUS_INVALID_ARGUMENT);
-  HTTP2_STATUS_TO_GRPC_STATUS(401, GRPC_STATUS_UNAUTHENTICATED);
-  HTTP2_STATUS_TO_GRPC_STATUS(403, GRPC_STATUS_PERMISSION_DENIED);
-  HTTP2_STATUS_TO_GRPC_STATUS(404, GRPC_STATUS_NOT_FOUND);
-  HTTP2_STATUS_TO_GRPC_STATUS(409, GRPC_STATUS_ABORTED);
-  HTTP2_STATUS_TO_GRPC_STATUS(412, GRPC_STATUS_FAILED_PRECONDITION);
-  HTTP2_STATUS_TO_GRPC_STATUS(429, GRPC_STATUS_RESOURCE_EXHAUSTED);
-  HTTP2_STATUS_TO_GRPC_STATUS(499, GRPC_STATUS_CANCELLED);
-  HTTP2_STATUS_TO_GRPC_STATUS(500, GRPC_STATUS_UNKNOWN);
-  HTTP2_STATUS_TO_GRPC_STATUS(503, GRPC_STATUS_UNAVAILABLE);
-  HTTP2_STATUS_TO_GRPC_STATUS(504, GRPC_STATUS_DEADLINE_EXCEEDED);
-
-  /* check all status values can be converted */
-  for (i = 0; i <= 999; i++) {
-    grpc_chttp2_http2_status_to_grpc_status(i);
-  }
-
-  return 0;
-}
diff --git a/test/core/transport/chttp2/varint_test.c b/test/core/transport/chttp2/varint_test.c
index e29be4b..f12c340 100644
--- a/test/core/transport/chttp2/varint_test.c
+++ b/test/core/transport/chttp2/varint_test.c
@@ -49,7 +49,7 @@
   slice = grpc_slice_malloc(nbytes);
   GRPC_CHTTP2_WRITE_VARINT(value, prefix_bits, prefix_or,
                            GRPC_SLICE_START_PTR(slice), nbytes);
-  GPR_ASSERT(grpc_slice_cmp(expect, slice) == 0);
+  GPR_ASSERT(grpc_slice_eq(expect, slice));
   grpc_slice_unref(expect);
   grpc_slice_unref(slice);
 }
diff --git a/test/core/transport/connectivity_state_test.c b/test/core/transport/connectivity_state_test.c
index 3520ef0..8314a5f 100644
--- a/test/core/transport/connectivity_state_test.c
+++ b/test/core/transport/connectivity_state_test.c
@@ -77,8 +77,9 @@
   grpc_error *error;
   gpr_log(GPR_DEBUG, "test_check");
   grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx");
-  GPR_ASSERT(grpc_connectivity_state_check(&tracker, &error) ==
+  GPR_ASSERT(grpc_connectivity_state_get(&tracker, &error) ==
              GRPC_CHANNEL_IDLE);
+  GPR_ASSERT(grpc_connectivity_state_check(&tracker) == GRPC_CHANNEL_IDLE);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   grpc_connectivity_state_destroy(&exec_ctx, &tracker);
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c
index 3625043..92e58f2 100644
--- a/test/core/transport/metadata_test.c
+++ b/test/core/transport/metadata_test.c
@@ -47,55 +47,51 @@
 #include "src/core/lib/transport/static_metadata.h"
 #include "test/core/util/test_config.h"
 
-#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
-
 /* a large number */
 #define MANY 10000
 
 static void test_no_op(void) {
-  LOG_TEST("test_no_op");
+  gpr_log(GPR_INFO, "test_no_op");
   grpc_init();
   grpc_shutdown();
 }
 
-static void test_create_string(void) {
-  grpc_mdstr *s1, *s2, *s3;
-
-  LOG_TEST("test_create_string");
-
-  grpc_init();
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  s1 = grpc_mdstr_from_string("hello");
-  s2 = grpc_mdstr_from_string("hello");
-  s3 = grpc_mdstr_from_string("very much not hello");
-  GPR_ASSERT(s1 == s2);
-  GPR_ASSERT(s3 != s1);
-  GPR_ASSERT(grpc_slice_str_cmp(s1->slice, "hello") == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(s3->slice, "very much not hello") == 0);
-  GRPC_MDSTR_UNREF(&exec_ctx, s1);
-  GRPC_MDSTR_UNREF(&exec_ctx, s2);
-  GRPC_MDSTR_UNREF(&exec_ctx, s3);
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_shutdown();
+static grpc_slice maybe_intern(grpc_slice in, bool intern) {
+  grpc_slice out = intern ? grpc_slice_intern(in) : grpc_slice_ref(in);
+  grpc_slice_unref(in);
+  return out;
 }
 
-static void test_create_metadata(void) {
-  grpc_mdelem *m1, *m2, *m3;
+static grpc_slice maybe_dup(grpc_slice in, bool dup) {
+  grpc_slice out = dup ? grpc_slice_dup(in) : grpc_slice_ref(in);
+  grpc_slice_unref(in);
+  return out;
+}
 
-  LOG_TEST("test_create_metadata");
+static void test_create_metadata(bool intern_keys, bool intern_values) {
+  grpc_mdelem m1, m2, m3;
+
+  gpr_log(GPR_INFO, "test_create_metadata: intern_keys=%d intern_values=%d",
+          intern_keys, intern_values);
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  m1 = grpc_mdelem_from_strings(&exec_ctx, "a", "b");
-  m2 = grpc_mdelem_from_strings(&exec_ctx, "a", "b");
-  m3 = grpc_mdelem_from_strings(&exec_ctx, "a", "c");
-  GPR_ASSERT(m1 == m2);
-  GPR_ASSERT(m3 != m1);
-  GPR_ASSERT(m3->key == m1->key);
-  GPR_ASSERT(m3->value != m1->value);
-  GPR_ASSERT(grpc_slice_str_cmp(m1->key->slice, "a") == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(m1->value->slice, "b") == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(m3->value->slice, "c") == 0);
+  m1 = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  m2 = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  m3 = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("c"), intern_values));
+  GPR_ASSERT(grpc_mdelem_eq(m1, m2));
+  GPR_ASSERT(!grpc_mdelem_eq(m3, m1));
+  GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(m3), GRPC_MDKEY(m1)));
+  GPR_ASSERT(!grpc_slice_eq(GRPC_MDVALUE(m3), GRPC_MDVALUE(m1)));
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(m1), "a") == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m1), "b") == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m3), "c") == 0);
   GRPC_MDELEM_UNREF(&exec_ctx, m1);
   GRPC_MDELEM_UNREF(&exec_ctx, m2);
   GRPC_MDELEM_UNREF(&exec_ctx, m3);
@@ -103,19 +99,28 @@
   grpc_shutdown();
 }
 
-static void test_create_many_ephemeral_metadata(void) {
+static void test_create_many_ephemeral_metadata(bool intern_keys,
+                                                bool intern_values) {
   char buffer[GPR_LTOA_MIN_BUFSIZE];
   long i;
 
-  LOG_TEST("test_create_many_ephemeral_metadata");
+  gpr_log(
+      GPR_INFO,
+      "test_create_many_ephemeral_metadata: intern_keys=%d intern_values=%d",
+      intern_keys, intern_values);
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   /* add, and immediately delete a bunch of different elements */
   for (i = 0; i < MANY; i++) {
     gpr_ltoa(i, buffer);
-    GRPC_MDELEM_UNREF(&exec_ctx,
-                      grpc_mdelem_from_strings(&exec_ctx, "a", buffer));
+    GRPC_MDELEM_UNREF(
+        &exec_ctx,
+        grpc_mdelem_from_slices(
+            &exec_ctx,
+            maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+            maybe_intern(grpc_slice_from_copied_string(buffer),
+                         intern_values)));
   }
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
@@ -124,23 +129,27 @@
 static void test_create_many_persistant_metadata(void) {
   char buffer[GPR_LTOA_MIN_BUFSIZE];
   long i;
-  grpc_mdelem **created = gpr_malloc(sizeof(grpc_mdelem *) * MANY);
-  grpc_mdelem *md;
+  grpc_mdelem *created = gpr_malloc(sizeof(grpc_mdelem) * MANY);
+  grpc_mdelem md;
 
-  LOG_TEST("test_create_many_persistant_metadata");
+  gpr_log(GPR_INFO, "test_create_many_persistant_metadata");
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   /* add phase */
   for (i = 0; i < MANY; i++) {
     gpr_ltoa(i, buffer);
-    created[i] = grpc_mdelem_from_strings(&exec_ctx, "a", buffer);
+    created[i] = grpc_mdelem_from_slices(
+        &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("a")),
+        grpc_slice_intern(grpc_slice_from_static_string(buffer)));
   }
   /* verify phase */
   for (i = 0; i < MANY; i++) {
     gpr_ltoa(i, buffer);
-    md = grpc_mdelem_from_strings(&exec_ctx, "a", buffer);
-    GPR_ASSERT(md == created[i]);
+    md = grpc_mdelem_from_slices(
+        &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("a")),
+        grpc_slice_intern(grpc_slice_from_static_string(buffer)));
+    GPR_ASSERT(grpc_mdelem_eq(md, created[i]));
     GRPC_MDELEM_UNREF(&exec_ctx, md);
   }
   /* cleanup phase */
@@ -153,14 +162,77 @@
   gpr_free(created);
 }
 
-static void test_spin_creating_the_same_thing(void) {
-  LOG_TEST("test_spin_creating_the_same_thing");
+static void test_spin_creating_the_same_thing(bool intern_keys,
+                                              bool intern_values) {
+  gpr_log(GPR_INFO,
+          "test_spin_creating_the_same_thing: intern_keys=%d intern_values=%d",
+          intern_keys, intern_values);
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_from_strings(&exec_ctx, "a", "b"));
-  GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_from_strings(&exec_ctx, "a", "b"));
-  GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_from_strings(&exec_ctx, "a", "b"));
+  grpc_mdelem a, b, c;
+  GRPC_MDELEM_UNREF(
+      &exec_ctx,
+      a = grpc_mdelem_from_slices(
+          &exec_ctx,
+          maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+          maybe_intern(grpc_slice_from_static_string("b"), intern_values)));
+  GRPC_MDELEM_UNREF(
+      &exec_ctx,
+      b = grpc_mdelem_from_slices(
+          &exec_ctx,
+          maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+          maybe_intern(grpc_slice_from_static_string("b"), intern_values)));
+  GRPC_MDELEM_UNREF(
+      &exec_ctx,
+      c = grpc_mdelem_from_slices(
+          &exec_ctx,
+          maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+          maybe_intern(grpc_slice_from_static_string("b"), intern_values)));
+  if (intern_keys && intern_values) {
+    GPR_ASSERT(a.payload == b.payload);
+    GPR_ASSERT(a.payload == c.payload);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_shutdown();
+}
+
+static void test_identity_laws(bool intern_keys, bool intern_values) {
+  gpr_log(GPR_INFO, "test_identity_laws: intern_keys=%d intern_values=%d",
+          intern_keys, intern_values);
+
+  grpc_init();
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem a, b, c;
+  a = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  b = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  c = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  GPR_ASSERT(grpc_mdelem_eq(a, a));
+  GPR_ASSERT(grpc_mdelem_eq(b, b));
+  GPR_ASSERT(grpc_mdelem_eq(c, c));
+  GPR_ASSERT(grpc_mdelem_eq(a, b));
+  GPR_ASSERT(grpc_mdelem_eq(b, c));
+  GPR_ASSERT(grpc_mdelem_eq(a, c));
+  GPR_ASSERT(grpc_mdelem_eq(b, a));
+  GPR_ASSERT(grpc_mdelem_eq(c, b));
+  GPR_ASSERT(grpc_mdelem_eq(c, a));
+  if (intern_keys && intern_values) {
+    GPR_ASSERT(a.payload == b.payload);
+    GPR_ASSERT(a.payload == c.payload);
+  } else {
+    GPR_ASSERT(a.payload != b.payload);
+    GPR_ASSERT(a.payload != c.payload);
+    GPR_ASSERT(b.payload != c.payload);
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, a);
+  GRPC_MDELEM_UNREF(&exec_ctx, b);
+  GRPC_MDELEM_UNREF(&exec_ctx, c);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
 }
@@ -169,25 +241,25 @@
   size_t i, j;
   char *buffer;
   size_t nstrs = 1000;
-  grpc_mdstr **strs = gpr_malloc(sizeof(grpc_mdstr *) * nstrs);
+  grpc_slice *strs = gpr_malloc(sizeof(grpc_slice) * nstrs);
   size_t *shuf = gpr_malloc(sizeof(size_t) * nstrs);
-  grpc_mdstr *test;
+  grpc_slice test;
 
-  LOG_TEST("test_things_stick_around");
+  gpr_log(GPR_INFO, "test_things_stick_around");
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
   for (i = 0; i < nstrs; i++) {
     gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x", i);
-    strs[i] = grpc_mdstr_from_string(buffer);
+    strs[i] = grpc_slice_intern(grpc_slice_from_static_string(buffer));
     shuf[i] = i;
     gpr_free(buffer);
   }
 
   for (i = 0; i < nstrs; i++) {
-    GRPC_MDSTR_REF(strs[i]);
-    GRPC_MDSTR_UNREF(&exec_ctx, strs[i]);
+    grpc_slice_ref_internal(strs[i]);
+    grpc_slice_unref_internal(&exec_ctx, strs[i]);
   }
 
   for (i = 0; i < nstrs; i++) {
@@ -199,13 +271,13 @@
   }
 
   for (i = 0; i < nstrs; i++) {
-    GRPC_MDSTR_UNREF(&exec_ctx, strs[shuf[i]]);
+    grpc_slice_unref_internal(&exec_ctx, strs[shuf[i]]);
     for (j = i + 1; j < nstrs; j++) {
       gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x",
                    shuf[j]);
-      test = grpc_mdstr_from_string(buffer);
-      GPR_ASSERT(test == strs[shuf[j]]);
-      GRPC_MDSTR_UNREF(&exec_ctx, test);
+      test = grpc_slice_intern(grpc_slice_from_static_string(buffer));
+      GPR_ASSERT(grpc_slice_is_equivalent(test, strs[shuf[j]]));
+      grpc_slice_unref_internal(&exec_ctx, test);
       gpr_free(buffer);
     }
   }
@@ -216,57 +288,11 @@
   gpr_free(shuf);
 }
 
-static void test_slices_work(void) {
-  /* ensure no memory leaks when switching representation from mdstr to slice */
-  grpc_mdstr *str;
-  grpc_slice slice;
-
-  LOG_TEST("test_slices_work");
-
-  grpc_init();
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  str = grpc_mdstr_from_string(
-      "123456789012345678901234567890123456789012345678901234567890");
-  slice = grpc_slice_ref(str->slice);
-  GRPC_MDSTR_UNREF(&exec_ctx, str);
-  grpc_slice_unref_internal(&exec_ctx, slice);
-
-  str = grpc_mdstr_from_string(
-      "123456789012345678901234567890123456789012345678901234567890");
-  slice = grpc_slice_ref(str->slice);
-  grpc_slice_unref_internal(&exec_ctx, slice);
-  GRPC_MDSTR_UNREF(&exec_ctx, str);
-
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_shutdown();
-}
-
-static void test_base64_and_huffman_works(void) {
-  grpc_mdstr *str;
-  grpc_slice slice1;
-  grpc_slice slice2;
-
-  LOG_TEST("test_base64_and_huffman_works");
-
-  grpc_init();
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  str = grpc_mdstr_from_string("abcdefg");
-  slice1 = grpc_mdstr_as_base64_encoded_and_huffman_compressed(str);
-  slice2 = grpc_chttp2_base64_encode_and_huffman_compress(str->slice);
-  GPR_ASSERT(0 == grpc_slice_cmp(slice1, slice2));
-
-  grpc_slice_unref_internal(&exec_ctx, slice2);
-  GRPC_MDSTR_UNREF(&exec_ctx, str);
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_shutdown();
-}
-
 static void test_user_data_works(void) {
   int *ud1;
   int *ud2;
-  grpc_mdelem *md;
-  LOG_TEST("test_user_data_works");
+  grpc_mdelem md;
+  gpr_log(GPR_INFO, "test_user_data_works");
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -274,7 +300,9 @@
   *ud1 = 1;
   ud2 = gpr_malloc(sizeof(int));
   *ud2 = 2;
-  md = grpc_mdelem_from_strings(&exec_ctx, "abc", "123");
+  md = grpc_mdelem_from_slices(
+      &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc")),
+      grpc_slice_intern(grpc_slice_from_static_string("123")));
   grpc_mdelem_set_user_data(md, gpr_free, ud1);
   grpc_mdelem_set_user_data(md, gpr_free, ud2);
   GPR_ASSERT(grpc_mdelem_get_user_data(md, gpr_free) == ud1);
@@ -284,8 +312,11 @@
 }
 
 static void verify_ascii_header_size(grpc_exec_ctx *exec_ctx, const char *key,
-                                     const char *value) {
-  grpc_mdelem *elem = grpc_mdelem_from_strings(exec_ctx, key, value);
+                                     const char *value, bool intern_key,
+                                     bool intern_value) {
+  grpc_mdelem elem = grpc_mdelem_from_slices(
+      exec_ctx, maybe_intern(grpc_slice_from_static_string(key), intern_key),
+      maybe_intern(grpc_slice_from_static_string(value), intern_value));
   size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
   size_t expected_size = 32 + strlen(key) + strlen(value);
   GPR_ASSERT(expected_size == elem_size);
@@ -293,10 +324,13 @@
 }
 
 static void verify_binary_header_size(grpc_exec_ctx *exec_ctx, const char *key,
-                                      const uint8_t *value, size_t value_len) {
-  grpc_mdelem *elem =
-      grpc_mdelem_from_string_and_buffer(exec_ctx, key, value, value_len);
-  GPR_ASSERT(grpc_is_binary_header(key, strlen(key)));
+                                      const uint8_t *value, size_t value_len,
+                                      bool intern_key, bool intern_value) {
+  grpc_mdelem elem = grpc_mdelem_from_slices(
+      exec_ctx, maybe_intern(grpc_slice_from_static_string(key), intern_key),
+      maybe_intern(grpc_slice_from_static_buffer(value, value_len),
+                   intern_value));
+  GPR_ASSERT(grpc_is_binary_header(GRPC_MDKEY(elem)));
   size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
   grpc_slice value_slice =
       grpc_slice_from_copied_buffer((const char *)value, value_len);
@@ -309,8 +343,9 @@
 }
 
 #define BUFFER_SIZE 64
-static void test_mdelem_sizes_in_hpack(void) {
-  LOG_TEST("test_mdelem_size");
+static void test_mdelem_sizes_in_hpack(bool intern_key, bool intern_value) {
+  gpr_log(GPR_INFO, "test_mdelem_size: intern_key=%d intern_value=%d",
+          intern_key, intern_value);
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
@@ -319,19 +354,44 @@
     binary_value[i] = i;
   }
 
-  verify_ascii_header_size(&exec_ctx, "hello", "world");
+  verify_ascii_header_size(&exec_ctx, "hello", "world", intern_key,
+                           intern_value);
   verify_ascii_header_size(&exec_ctx, "hello",
-                           "worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-  verify_ascii_header_size(&exec_ctx, ":scheme", "http");
+                           "worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", intern_key,
+                           intern_value);
+  verify_ascii_header_size(&exec_ctx, ":scheme", "http", intern_key,
+                           intern_value);
 
   for (uint8_t i = 0; i < BUFFER_SIZE; i++) {
-    verify_binary_header_size(&exec_ctx, "hello-bin", binary_value, i);
+    verify_binary_header_size(&exec_ctx, "hello-bin", binary_value, i,
+                              intern_key, intern_value);
   }
 
-  const char *static_metadata = grpc_static_metadata_strings[0];
-  memcpy(binary_value, static_metadata, strlen(static_metadata));
-  verify_binary_header_size(&exec_ctx, "hello-bin", binary_value,
-                            strlen(static_metadata));
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_shutdown();
+}
+
+static void test_copied_static_metadata(bool dup_key, bool dup_value) {
+  gpr_log(GPR_INFO, "test_static_metadata: dup_key=%d dup_value=%d", dup_key,
+          dup_value);
+  grpc_init();
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
+    grpc_mdelem p = GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[i],
+                                     GRPC_MDELEM_STORAGE_STATIC);
+    grpc_mdelem q =
+        grpc_mdelem_from_slices(&exec_ctx, maybe_dup(GRPC_MDKEY(p), dup_key),
+                                maybe_dup(GRPC_MDVALUE(p), dup_value));
+    GPR_ASSERT(grpc_mdelem_eq(p, q));
+    if (dup_key || dup_value) {
+      GPR_ASSERT(p.payload != q.payload);
+    } else {
+      GPR_ASSERT(p.payload == q.payload);
+    }
+    GRPC_MDELEM_UNREF(&exec_ctx, p);
+    GRPC_MDELEM_UNREF(&exec_ctx, q);
+  }
 
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
@@ -340,15 +400,18 @@
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_no_op();
-  test_create_string();
-  test_create_metadata();
-  test_create_many_ephemeral_metadata();
+  for (int k = 0; k <= 1; k++) {
+    for (int v = 0; v <= 1; v++) {
+      test_create_metadata(k, v);
+      test_create_many_ephemeral_metadata(k, v);
+      test_identity_laws(k, v);
+      test_spin_creating_the_same_thing(k, v);
+      test_mdelem_sizes_in_hpack(k, v);
+      test_copied_static_metadata(k, v);
+    }
+  }
   test_create_many_persistant_metadata();
-  test_spin_creating_the_same_thing();
   test_things_stick_around();
-  test_slices_work();
-  test_base64_and_huffman_works();
   test_user_data_works();
-  test_mdelem_sizes_in_hpack();
   return 0;
 }
diff --git a/test/core/transport/pid_controller_test.c b/test/core/transport/pid_controller_test.c
index 9614983..831343c 100644
--- a/test/core/transport/pid_controller_test.c
+++ b/test/core/transport/pid_controller_test.c
@@ -33,6 +33,7 @@
 
 #include "src/core/lib/transport/pid_controller.h"
 
+#include <float.h>
 #include <math.h>
 
 #include <grpc/support/alloc.h>
@@ -45,7 +46,14 @@
 static void test_noop(void) {
   gpr_log(GPR_INFO, "test_noop");
   grpc_pid_controller pid;
-  grpc_pid_controller_init(&pid, 1, 1, 1);
+  grpc_pid_controller_init(
+      &pid, (grpc_pid_controller_args){.gain_p = 1,
+                                       .gain_i = 1,
+                                       .gain_d = 1,
+                                       .initial_control_value = 1,
+                                       .min_control_value = DBL_MIN,
+                                       .max_control_value = DBL_MAX,
+                                       .integral_range = DBL_MAX});
 }
 
 static void test_simple_convergence(double gain_p, double gain_i, double gain_d,
@@ -55,16 +63,24 @@
           "start=%lf",
           gain_p, gain_i, gain_d, dt, set_point, start);
   grpc_pid_controller pid;
-  grpc_pid_controller_init(&pid, 0.2, 0.1, 0.1);
+  grpc_pid_controller_init(
+      &pid, (grpc_pid_controller_args){.gain_p = gain_p,
+                                       .gain_i = gain_i,
+                                       .gain_d = gain_d,
+                                       .initial_control_value = start,
+                                       .min_control_value = DBL_MIN,
+                                       .max_control_value = DBL_MAX,
+                                       .integral_range = DBL_MAX});
 
-  double current = start;
-
-  for (int i = 0; i < 1000; i++) {
-    current += grpc_pid_controller_update(&pid, set_point - current, 1);
+  for (int i = 0; i < 100000; i++) {
+    grpc_pid_controller_update(&pid, set_point - grpc_pid_controller_last(&pid),
+                               1);
   }
 
-  GPR_ASSERT(fabs(set_point - current) < 0.1);
-  GPR_ASSERT(fabs(pid.error_integral) < 0.1);
+  GPR_ASSERT(fabs(set_point - grpc_pid_controller_last(&pid)) < 0.1);
+  if (gain_i > 0) {
+    GPR_ASSERT(fabs(pid.error_integral) < 0.1);
+  }
 }
 
 int main(int argc, char **argv) {
diff --git a/test/core/transport/status_conversion_test.c b/test/core/transport/status_conversion_test.c
new file mode 100644
index 0000000..65f840b
--- /dev/null
+++ b/test/core/transport/status_conversion_test.c
@@ -0,0 +1,172 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/transport/status_conversion.h"
+#include <grpc/support/log.h>
+#include "test/core/util/test_config.h"
+
+#define GRPC_STATUS_TO_HTTP2_ERROR(a, b) \
+  GPR_ASSERT(grpc_status_to_http2_error(a) == (b))
+#define HTTP2_ERROR_TO_GRPC_STATUS(a, deadline, b) \
+  GPR_ASSERT(grpc_http2_error_to_grpc_status(a, deadline) == (b))
+#define GRPC_STATUS_TO_HTTP2_STATUS(a, b) \
+  GPR_ASSERT(grpc_status_to_http2_status(a) == (b))
+#define HTTP2_STATUS_TO_GRPC_STATUS(a, b) \
+  GPR_ASSERT(grpc_http2_status_to_grpc_status(a) == (b))
+
+int main(int argc, char **argv) {
+  int i;
+
+  grpc_test_init(argc, argv);
+
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OK, GRPC_HTTP2_NO_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_CANCELLED, GRPC_HTTP2_CANCEL);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNKNOWN, GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INVALID_ARGUMENT,
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DEADLINE_EXCEEDED, GRPC_HTTP2_CANCEL);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_NOT_FOUND, GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ALREADY_EXISTS,
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_PERMISSION_DENIED,
+                             GRPC_HTTP2_INADEQUATE_SECURITY);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAUTHENTICATED,
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_RESOURCE_EXHAUSTED,
+                             GRPC_HTTP2_ENHANCE_YOUR_CALM);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_FAILED_PRECONDITION,
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ABORTED, GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OUT_OF_RANGE,
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNIMPLEMENTED,
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INTERNAL, GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAVAILABLE,
+                             GRPC_HTTP2_REFUSED_STREAM);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DATA_LOSS, GRPC_HTTP2_INTERNAL_ERROR);
+
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OK, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_CANCELLED, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNKNOWN, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_INVALID_ARGUMENT, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DEADLINE_EXCEEDED, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_NOT_FOUND, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_ALREADY_EXISTS, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_PERMISSION_DENIED, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAUTHENTICATED, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_RESOURCE_EXHAUSTED, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_FAILED_PRECONDITION, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_ABORTED, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OUT_OF_RANGE, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNIMPLEMENTED, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_INTERNAL, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_UNAVAILABLE, 200);
+  GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DATA_LOSS, 200);
+
+  const gpr_timespec before_deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_NO_ERROR, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_PROTOCOL_ERROR, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INTERNAL_ERROR, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FLOW_CONTROL_ERROR, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_SETTINGS_TIMEOUT, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_STREAM_CLOSED, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FRAME_SIZE_ERROR, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, before_deadline,
+                             GRPC_STATUS_UNAVAILABLE);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, before_deadline,
+                             GRPC_STATUS_CANCELLED);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CONNECT_ERROR, before_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_ENHANCE_YOUR_CALM, before_deadline,
+                             GRPC_STATUS_RESOURCE_EXHAUSTED);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INADEQUATE_SECURITY, before_deadline,
+                             GRPC_STATUS_PERMISSION_DENIED);
+
+  const gpr_timespec after_deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_NO_ERROR, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_PROTOCOL_ERROR, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INTERNAL_ERROR, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FLOW_CONTROL_ERROR, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_SETTINGS_TIMEOUT, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_STREAM_CLOSED, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FRAME_SIZE_ERROR, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, after_deadline,
+                             GRPC_STATUS_UNAVAILABLE);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, after_deadline,
+                             GRPC_STATUS_DEADLINE_EXCEEDED);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CONNECT_ERROR, after_deadline,
+                             GRPC_STATUS_INTERNAL);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_ENHANCE_YOUR_CALM, after_deadline,
+                             GRPC_STATUS_RESOURCE_EXHAUSTED);
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INADEQUATE_SECURITY, after_deadline,
+                             GRPC_STATUS_PERMISSION_DENIED);
+
+  HTTP2_STATUS_TO_GRPC_STATUS(200, GRPC_STATUS_OK);
+  HTTP2_STATUS_TO_GRPC_STATUS(400, GRPC_STATUS_INVALID_ARGUMENT);
+  HTTP2_STATUS_TO_GRPC_STATUS(401, GRPC_STATUS_UNAUTHENTICATED);
+  HTTP2_STATUS_TO_GRPC_STATUS(403, GRPC_STATUS_PERMISSION_DENIED);
+  HTTP2_STATUS_TO_GRPC_STATUS(404, GRPC_STATUS_NOT_FOUND);
+  HTTP2_STATUS_TO_GRPC_STATUS(409, GRPC_STATUS_ABORTED);
+  HTTP2_STATUS_TO_GRPC_STATUS(412, GRPC_STATUS_FAILED_PRECONDITION);
+  HTTP2_STATUS_TO_GRPC_STATUS(429, GRPC_STATUS_RESOURCE_EXHAUSTED);
+  HTTP2_STATUS_TO_GRPC_STATUS(499, GRPC_STATUS_CANCELLED);
+  HTTP2_STATUS_TO_GRPC_STATUS(500, GRPC_STATUS_UNKNOWN);
+  HTTP2_STATUS_TO_GRPC_STATUS(503, GRPC_STATUS_UNAVAILABLE);
+  HTTP2_STATUS_TO_GRPC_STATUS(504, GRPC_STATUS_DEADLINE_EXCEEDED);
+
+  /* check all status values can be converted */
+  for (i = 0; i <= 999; i++) {
+    grpc_http2_status_to_grpc_status(i);
+  }
+
+  return 0;
+}
diff --git a/test/core/transport/timeout_encoding_test.c b/test/core/transport/timeout_encoding_test.c
index b6004af..10e1804 100644
--- a/test/core/transport/timeout_encoding_test.c
+++ b/test/core/transport/timeout_encoding_test.c
@@ -88,7 +88,8 @@
 static void assert_decodes_as(const char *buffer, gpr_timespec expected) {
   gpr_timespec got;
   gpr_log(GPR_INFO, "check decoding '%s'", buffer);
-  GPR_ASSERT(1 == grpc_http2_decode_timeout(buffer, &got));
+  GPR_ASSERT(1 == grpc_http2_decode_timeout(
+                      grpc_slice_from_static_string(buffer), &got));
   GPR_ASSERT(0 == gpr_time_cmp(got, expected));
 }
 
@@ -134,18 +135,23 @@
   assert_decodes_as("9999999999S", gpr_inf_future(GPR_TIMESPAN));
 }
 
-void test_decoding_fails(void) {
+static void assert_decoding_fails(const char *s) {
   gpr_timespec x;
+  GPR_ASSERT(0 ==
+             grpc_http2_decode_timeout(grpc_slice_from_static_string(s), &x));
+}
+
+void test_decoding_fails(void) {
   LOG_TEST("test_decoding_fails");
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout(" ", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("x", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("1", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("1x", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("1ux", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("!", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("n1", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("-1u", &x));
+  assert_decoding_fails("");
+  assert_decoding_fails(" ");
+  assert_decoding_fails("x");
+  assert_decoding_fails("1");
+  assert_decoding_fails("1x");
+  assert_decoding_fails("1ux");
+  assert_decoding_fails("!");
+  assert_decoding_fails("n1");
+  assert_decoding_fails("-1u");
 }
 
 int main(int argc, char **argv) {
diff --git a/test/core/tsi/BUILD b/test/core/tsi/BUILD
new file mode 100644
index 0000000..e6cba34
--- /dev/null
+++ b/test/core/tsi/BUILD
@@ -0,0 +1,37 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+cc_test(
+    name = "transport_security_test",
+    srcs = ["transport_security_test.c"],
+    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    copts = ['-std=c99']
+)
diff --git a/test/core/util/BUILD b/test/core/util/BUILD
index 8769683..5c90f1d 100644
--- a/test/core/util/BUILD
+++ b/test/core/util/BUILD
@@ -46,6 +46,7 @@
 cc_library(
     name = "grpc_test_util",
     srcs = [
+        "debugger_macros.c",
         "grpc_profiler.c",
         "mock_endpoint.c",
         "parse_hexstring.c",
@@ -58,6 +59,7 @@
         "test_tcp_server.c",
     ],
     hdrs = [
+        "debugger_macros.h",
         "grpc_profiler.h",
         "mock_endpoint.h",
         "parse_hexstring.h",
diff --git a/test/core/util/debugger_macros.c b/test/core/util/debugger_macros.c
new file mode 100644
index 0000000..de6a2f3
--- /dev/null
+++ b/test/core/util/debugger_macros.c
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * A collection of 'macros' that help navigating the grpc object hierarchy
+ * Not intended to be robust for main-line code, often cuts across abstraction
+ * boundaries.
+ */
+
+#include <stdio.h>
+
+#include "src/core/ext/client_channel/client_channel.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/surface/call.h"
+
+void grpc_summon_debugger_macros() {}
+
+grpc_stream *grpc_transport_stream_from_call(grpc_call *call) {
+  grpc_call_stack *cs = grpc_call_get_call_stack(call);
+  for (;;) {
+    grpc_call_element *el = grpc_call_stack_element(cs, cs->count - 1);
+    if (el->filter == &grpc_client_channel_filter) {
+      grpc_subchannel_call *scc = grpc_client_channel_get_subchannel_call(el);
+      if (scc == NULL) {
+        fprintf(stderr, "No subchannel-call");
+        return NULL;
+      }
+      cs = grpc_subchannel_call_get_call_stack(scc);
+    } else if (el->filter == &grpc_connected_filter) {
+      return grpc_connected_channel_get_stream(el);
+    } else {
+      fprintf(stderr, "Unrecognized filter: %s", el->filter->name);
+      return NULL;
+    }
+  }
+}
+
+grpc_chttp2_stream *grpc_chttp2_stream_from_call(grpc_call *call) {
+  return (grpc_chttp2_stream *)grpc_transport_stream_from_call(call);
+}
diff --git a/test/core/util/debugger_macros.h b/test/core/util/debugger_macros.h
new file mode 100644
index 0000000..6369ca6
--- /dev/null
+++ b/test/core/util/debugger_macros.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H
+#define GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H
+
+void grpc_summon_debugger_macros();
+
+#endif /* GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H */
diff --git a/test/core/util/memory_counters.c b/test/core/util/memory_counters.c
index bebe94e..7c8b620 100644
--- a/test/core/util/memory_counters.c
+++ b/test/core/util/memory_counters.c
@@ -39,7 +39,6 @@
 
 #include "test/core/util/memory_counters.h"
 
-static gpr_mu g_memory_mutex;
 static struct grpc_memory_counters g_memory_counters;
 static gpr_allocation_functions g_old_allocs;
 
@@ -50,12 +49,14 @@
 static void *guard_malloc(size_t size) {
   size_t *ptr;
   if (!size) return NULL;
-  gpr_mu_lock(&g_memory_mutex);
-  g_memory_counters.total_size_absolute += size;
-  g_memory_counters.total_size_relative += size;
-  g_memory_counters.total_allocs_absolute++;
-  g_memory_counters.total_allocs_relative++;
-  gpr_mu_unlock(&g_memory_mutex);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_absolute,
+                               (gpr_atm)size);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_relative,
+                               (gpr_atm)size);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_allocs_absolute,
+                               (gpr_atm)1);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_allocs_relative,
+                               (gpr_atm)1);
   ptr = g_old_allocs.malloc_fn(size + sizeof(size));
   *ptr++ = size;
   return ptr;
@@ -71,12 +72,14 @@
     return NULL;
   }
   --ptr;
-  gpr_mu_lock(&g_memory_mutex);
-  g_memory_counters.total_size_absolute += size;
-  g_memory_counters.total_size_relative -= *ptr;
-  g_memory_counters.total_size_relative += size;
-  g_memory_counters.total_allocs_absolute++;
-  gpr_mu_unlock(&g_memory_mutex);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_absolute,
+                               (gpr_atm)size);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_relative,
+                               -(gpr_atm)*ptr);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_relative,
+                               (gpr_atm)size);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_allocs_absolute,
+                               (gpr_atm)1);
   ptr = g_old_allocs.realloc_fn(ptr, size + sizeof(size));
   *ptr++ = size;
   return ptr;
@@ -86,32 +89,35 @@
   size_t *ptr = vptr;
   if (!vptr) return;
   --ptr;
-  gpr_mu_lock(&g_memory_mutex);
-  g_memory_counters.total_size_relative -= *ptr;
-  g_memory_counters.total_allocs_relative--;
-  gpr_mu_unlock(&g_memory_mutex);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_relative,
+                               -(gpr_atm)*ptr);
+  gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_allocs_relative,
+                               -(gpr_atm)1);
   g_old_allocs.free_fn(ptr);
 }
 
-struct gpr_allocation_functions g_guard_allocs = {guard_malloc, guard_realloc,
-                                                  guard_free};
+struct gpr_allocation_functions g_guard_allocs = {guard_malloc, NULL,
+                                                  guard_realloc, guard_free};
 
 void grpc_memory_counters_init() {
   memset(&g_memory_counters, 0, sizeof(g_memory_counters));
-  gpr_mu_init(&g_memory_mutex);
   g_old_allocs = gpr_get_allocation_functions();
   gpr_set_allocation_functions(g_guard_allocs);
 }
 
 void grpc_memory_counters_destroy() {
   gpr_set_allocation_functions(g_old_allocs);
-  gpr_mu_destroy(&g_memory_mutex);
 }
 
 struct grpc_memory_counters grpc_memory_counters_snapshot() {
   struct grpc_memory_counters counters;
-  gpr_mu_lock(&g_memory_mutex);
-  counters = g_memory_counters;
-  gpr_mu_unlock(&g_memory_mutex);
+  counters.total_size_relative =
+      gpr_atm_no_barrier_load(&g_memory_counters.total_size_relative);
+  counters.total_size_absolute =
+      gpr_atm_no_barrier_load(&g_memory_counters.total_size_absolute);
+  counters.total_allocs_relative =
+      gpr_atm_no_barrier_load(&g_memory_counters.total_allocs_relative);
+  counters.total_allocs_absolute =
+      gpr_atm_no_barrier_load(&g_memory_counters.total_allocs_absolute);
   return counters;
 }
diff --git a/test/core/util/memory_counters.h b/test/core/util/memory_counters.h
index b9b2b3a..51487c7 100644
--- a/test/core/util/memory_counters.h
+++ b/test/core/util/memory_counters.h
@@ -34,13 +34,13 @@
 #ifndef GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H
 #define GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H
 
-#include <stddef.h>
+#include <grpc/support/atm.h>
 
 struct grpc_memory_counters {
-  size_t total_size_relative;
-  size_t total_size_absolute;
-  size_t total_allocs_relative;
-  size_t total_allocs_absolute;
+  gpr_atm total_size_relative;
+  gpr_atm total_size_absolute;
+  gpr_atm total_allocs_relative;
+  gpr_atm total_allocs_absolute;
 };
 
 void grpc_memory_counters_init();
diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c
index 29ccbd2..b8fed7e 100644
--- a/test/core/util/mock_endpoint.c
+++ b/test/core/util/mock_endpoint.c
@@ -84,16 +84,18 @@
 static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                                   grpc_pollset_set *pollset) {}
 
-static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                        grpc_error *why) {
   grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
   gpr_mu_lock(&m->mu);
   if (m->on_read) {
-    grpc_closure_sched(exec_ctx, m->on_read,
-                       GRPC_ERROR_CREATE("Endpoint Shutdown"));
+    grpc_closure_sched(exec_ctx, m->on_read, GRPC_ERROR_CREATE_REFERENCING(
+                                                 "Endpoint Shutdown", &why, 1));
     m->on_read = NULL;
   }
   gpr_mu_unlock(&m->mu);
   grpc_resource_user_shutdown(exec_ctx, m->resource_user);
+  GRPC_ERROR_UNREF(why);
 }
 
 static void me_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c
index 4a14475..5f27f9a 100644
--- a/test/core/util/passthru_endpoint.c
+++ b/test/core/util/passthru_endpoint.c
@@ -40,6 +40,7 @@
 #include "test/core/util/passthru_endpoint.h"
 
 #include <inttypes.h>
+#include <string.h>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
@@ -61,6 +62,9 @@
 struct passthru_endpoint {
   gpr_mu mu;
   int halves;
+  grpc_passthru_endpoint_stats *stats;
+  grpc_passthru_endpoint_stats
+      dummy_stats;  // used if constructor stats == NULL
   bool shutdown;
   half client;
   half server;
@@ -92,6 +96,7 @@
   half *m = other_half((half *)ep);
   gpr_mu_lock(&m->parent->mu);
   grpc_error *error = GRPC_ERROR_NONE;
+  m->parent->stats->num_writes++;
   if (m->parent->shutdown) {
     error = GRPC_ERROR_CREATE("Endpoint already shutdown");
   } else if (m->on_read != NULL) {
@@ -115,21 +120,25 @@
 static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                                   grpc_pollset_set *pollset) {}
 
-static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+static void me_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                        grpc_error *why) {
   half *m = (half *)ep;
   gpr_mu_lock(&m->parent->mu);
   m->parent->shutdown = true;
   if (m->on_read) {
-    grpc_closure_sched(exec_ctx, m->on_read, GRPC_ERROR_CREATE("Shutdown"));
+    grpc_closure_sched(exec_ctx, m->on_read,
+                       GRPC_ERROR_CREATE_REFERENCING("Shutdown", &why, 1));
     m->on_read = NULL;
   }
   m = other_half(m);
   if (m->on_read) {
-    grpc_closure_sched(exec_ctx, m->on_read, GRPC_ERROR_CREATE("Shutdown"));
+    grpc_closure_sched(exec_ctx, m->on_read,
+                       GRPC_ERROR_CREATE_REFERENCING("Shutdown", &why, 1));
     m->on_read = NULL;
   }
   gpr_mu_unlock(&m->parent->mu);
   grpc_resource_user_shutdown(exec_ctx, m->resource_user);
+  GRPC_ERROR_UNREF(why);
 }
 
 static void me_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
@@ -149,7 +158,9 @@
 }
 
 static char *me_get_peer(grpc_endpoint *ep) {
-  return gpr_strdup("fake:mock_endpoint");
+  passthru_endpoint *p = ((half *)ep)->parent;
+  return ((half *)ep) == &p->client ? gpr_strdup("fake:mock_client_endpoint")
+                                    : gpr_strdup("fake:mock_server_endpoint");
 }
 
 static int me_get_fd(grpc_endpoint *ep) { return -1; }
@@ -190,10 +201,13 @@
 
 void grpc_passthru_endpoint_create(grpc_endpoint **client,
                                    grpc_endpoint **server,
-                                   grpc_resource_quota *resource_quota) {
+                                   grpc_resource_quota *resource_quota,
+                                   grpc_passthru_endpoint_stats *stats) {
   passthru_endpoint *m = gpr_malloc(sizeof(*m));
   m->halves = 2;
   m->shutdown = 0;
+  m->stats = stats == NULL ? &m->dummy_stats : stats;
+  memset(m->stats, 0, sizeof(*m->stats));
   half_init(&m->client, m, resource_quota, "client");
   half_init(&m->server, m, resource_quota, "server");
   gpr_mu_init(&m->mu);
diff --git a/test/core/util/passthru_endpoint.h b/test/core/util/passthru_endpoint.h
index b81ac55..9199925 100644
--- a/test/core/util/passthru_endpoint.h
+++ b/test/core/util/passthru_endpoint.h
@@ -36,8 +36,11 @@
 
 #include "src/core/lib/iomgr/endpoint.h"
 
+typedef struct { int num_writes; } grpc_passthru_endpoint_stats;
+
 void grpc_passthru_endpoint_create(grpc_endpoint **client,
                                    grpc_endpoint **server,
-                                   grpc_resource_quota *resource_quota);
+                                   grpc_resource_quota *resource_quota,
+                                   grpc_passthru_endpoint_stats *stats);
 
 #endif
diff --git a/test/core/util/port_server_client.c b/test/core/util/port_server_client.c
index 4baf63d..f7d723a 100644
--- a/test/core/util/port_server_client.c
+++ b/test/core/util/port_server_client.c
@@ -89,7 +89,7 @@
   memset(&req, 0, sizeof(req));
   memset(&rsp, 0, sizeof(rsp));
 
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &pr.mu);
   pr.pops = grpc_polling_entity_create_from_pollset(pollset);
   shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops,
@@ -103,7 +103,7 @@
   grpc_resource_quota *resource_quota =
       grpc_resource_quota_create("port_server_client/free");
   grpc_httpcli_get(&exec_ctx, &context, &pr.pops, resource_quota, &req,
-                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
+                   grpc_timeout_seconds_to_deadline(10),
                    grpc_closure_create(freed_port_from_server, &pr,
                                        grpc_schedule_on_exec_ctx),
                    &rsp);
@@ -115,13 +115,13 @@
             "pollset_work",
             grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                               &worker, gpr_now(GPR_CLOCK_MONOTONIC),
-                              GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)))) {
+                              grpc_timeout_seconds_to_deadline(1)))) {
       pr.done = 1;
     }
   }
   gpr_mu_unlock(pr.mu);
 
-  grpc_httpcli_context_destroy(&context);
+  grpc_httpcli_context_destroy(&exec_ctx, &context);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                         shutdown_closure);
@@ -152,7 +152,7 @@
     failed = 1;
     const char *msg = grpc_error_string(error);
     gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);
-    grpc_error_free_string(msg);
+
   } else if (response->status != 200) {
     failed = 1;
     gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
@@ -176,7 +176,7 @@
     grpc_resource_quota *resource_quota =
         grpc_resource_quota_create("port_server_client/pick_retry");
     grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, resource_quota, &req,
-                     GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
+                     grpc_timeout_seconds_to_deadline(10),
                      grpc_closure_create(got_port_from_server, pr,
                                          grpc_schedule_on_exec_ctx),
                      &pr->response);
@@ -209,7 +209,7 @@
 
   memset(&pr, 0, sizeof(pr));
   memset(&req, 0, sizeof(req));
-  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(pollset, &pr.mu);
   pr.pops = grpc_polling_entity_create_from_pollset(pollset);
   shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops,
@@ -226,7 +226,7 @@
       grpc_resource_quota_create("port_server_client/pick");
   grpc_httpcli_get(
       &exec_ctx, &context, &pr.pops, resource_quota, &req,
-      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
+      grpc_timeout_seconds_to_deadline(10),
       grpc_closure_create(got_port_from_server, &pr, grpc_schedule_on_exec_ctx),
       &pr.response);
   grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
@@ -238,14 +238,14 @@
             "pollset_work",
             grpc_pollset_work(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                               &worker, gpr_now(GPR_CLOCK_MONOTONIC),
-                              GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)))) {
+                              grpc_timeout_seconds_to_deadline(1)))) {
       pr.port = 0;
     }
   }
   gpr_mu_unlock(pr.mu);
 
   grpc_http_response_destroy(&pr.response);
-  grpc_httpcli_context_destroy(&context);
+  grpc_httpcli_context_destroy(&exec_ctx, &context);
   grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops),
                         shutdown_closure);
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c
index 7bf83a7..7fbd0ca 100644
--- a/test/core/util/reconnect_server.c
+++ b/test/core/util/reconnect_server.c
@@ -80,7 +80,7 @@
   gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
   timestamp_list *new_tail;
   peer = grpc_endpoint_get_peer(tcp);
-  grpc_endpoint_shutdown(exec_ctx, tcp);
+  grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
   grpc_endpoint_destroy(exec_ctx, tcp);
   if (peer) {
     last_colon = strrchr(peer, ':');
diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c
index be15940..0180d6f 100644
--- a/test/core/util/test_config.c
+++ b/test/core/util/test_config.c
@@ -45,8 +45,8 @@
 #include "src/core/lib/support/env.h"
 #include "src/core/lib/support/string.h"
 
-double g_fixture_slowdown_factor = 1.0;
-double g_poller_slowdown_factor = 1.0;
+int64_t g_fixture_slowdown_factor = 1;
+int64_t g_poller_slowdown_factor = 1;
 
 #if GPR_GETPID_IN_UNISTD_H
 #include <unistd.h>
@@ -292,19 +292,109 @@
 static void install_crash_handler() {}
 #endif
 
+bool BuiltUnderValgrind() {
+#ifdef RUNNING_ON_VALGRIND
+  return true;
+#else
+  return false;
+#endif
+}
+
+bool BuiltUnderTsan() {
+#if defined(__has_feature)
+#if __has_feature(thread_sanitizer)
+  return true;
+#else
+  return false;
+#endif
+#else
+#ifdef THREAD_SANITIZER
+  return true;
+#else
+  return false;
+#endif
+#endif
+}
+
+bool BuiltUnderAsan() {
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+  return true;
+#else
+  return false;
+#endif
+#else
+#ifdef ADDRESS_SANITIZER
+  return true;
+#else
+  return false;
+#endif
+#endif
+}
+
+bool BuiltUnderMsan() {
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+  return true;
+#else
+  return false;
+#endif
+#else
+#ifdef MEMORY_SANITIZER
+  return true;
+#else
+  return false;
+#endif
+#endif
+}
+
+int64_t grpc_test_sanitizer_slowdown_factor() {
+  int64_t sanitizer_multiplier = 1;
+  if (BuiltUnderValgrind()) {
+    sanitizer_multiplier = 20;
+  } else if (BuiltUnderTsan()) {
+    sanitizer_multiplier = 5;
+  } else if (BuiltUnderAsan()) {
+    sanitizer_multiplier = 3;
+  } else if (BuiltUnderMsan()) {
+    sanitizer_multiplier = 4;
+  }
+  return sanitizer_multiplier;
+}
+
+int64_t grpc_test_slowdown_factor() {
+  return grpc_test_sanitizer_slowdown_factor() * g_fixture_slowdown_factor *
+         g_poller_slowdown_factor;
+}
+
+gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) {
+  return gpr_time_add(
+      gpr_now(GPR_CLOCK_MONOTONIC),
+      gpr_time_from_millis(grpc_test_slowdown_factor() * (int64_t)1e3 * time_s,
+                           GPR_TIMESPAN));
+}
+
+gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) {
+  return gpr_time_add(
+      gpr_now(GPR_CLOCK_MONOTONIC),
+      gpr_time_from_micros(grpc_test_slowdown_factor() * (int64_t)1e3 * time_ms,
+                           GPR_TIMESPAN));
+}
+
 void grpc_test_init(int argc, char **argv) {
   install_crash_handler();
   { /* poll-cv poll strategy runs much more slowly than anything else */
     char *s = gpr_getenv("GRPC_POLL_STRATEGY");
     if (s != NULL && 0 == strcmp(s, "poll-cv")) {
-      g_poller_slowdown_factor = 5.0;
+      g_poller_slowdown_factor = 5;
     }
     gpr_free(s);
   }
-  gpr_log(GPR_DEBUG, "test slowdown: machine=%f build=%f poll=%f total=%f",
-          (double)GRPC_TEST_SLOWDOWN_MACHINE_FACTOR,
-          (double)GRPC_TEST_SLOWDOWN_BUILD_FACTOR, g_poller_slowdown_factor,
-          (double)GRPC_TEST_SLOWDOWN_FACTOR);
+  gpr_log(GPR_DEBUG,
+          "test slowdown factor: sanitizer=%" PRId64 ", fixture=%" PRId64
+          ", poller=%" PRId64 ", total=%" PRId64,
+          grpc_test_sanitizer_slowdown_factor(), g_fixture_slowdown_factor,
+          g_poller_slowdown_factor, grpc_test_slowdown_factor());
   /* seed rng with pid, so we don't end up with the same random numbers as a
      concurrently running test binary */
   srand(seed());
diff --git a/test/core/util/test_config.h b/test/core/util/test_config.h
index c13fe86..491f011 100644
--- a/test/core/util/test_config.h
+++ b/test/core/util/test_config.h
@@ -40,32 +40,17 @@
 extern "C" {
 #endif /*  __cplusplus */
 
-#ifndef GRPC_TEST_SLOWDOWN_BUILD_FACTOR
-#define GRPC_TEST_SLOWDOWN_BUILD_FACTOR 1.0
-#endif
+extern int64_t g_fixture_slowdown_factor;
+extern int64_t g_poller_slowdown_factor;
 
-#ifndef GRPC_TEST_SLOWDOWN_MACHINE_FACTOR
-#define GRPC_TEST_SLOWDOWN_MACHINE_FACTOR 1.0
-#endif
+/* Returns an appropriate scaling factor for timeouts. */
+int64_t grpc_test_slowdown_factor();
 
-extern double g_fixture_slowdown_factor;
-extern double g_poller_slowdown_factor;
+/* Converts a given timeout (in seconds) to a deadline. */
+gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s);
 
-#define GRPC_TEST_SLOWDOWN_FACTOR                                        \
-  (GRPC_TEST_SLOWDOWN_BUILD_FACTOR * GRPC_TEST_SLOWDOWN_MACHINE_FACTOR * \
-   g_fixture_slowdown_factor * g_poller_slowdown_factor)
-
-#define GRPC_TIMEOUT_SECONDS_TO_DEADLINE(x)                                  \
-  gpr_time_add(                                                              \
-      gpr_now(GPR_CLOCK_MONOTONIC),                                          \
-      gpr_time_from_millis((int64_t)(GRPC_TEST_SLOWDOWN_FACTOR * 1e3 * (x)), \
-                           GPR_TIMESPAN))
-
-#define GRPC_TIMEOUT_MILLIS_TO_DEADLINE(x)                                   \
-  gpr_time_add(                                                              \
-      gpr_now(GPR_CLOCK_MONOTONIC),                                          \
-      gpr_time_from_micros((int64_t)(GRPC_TEST_SLOWDOWN_FACTOR * 1e3 * (x)), \
-                           GPR_TIMESPAN))
+/* Converts a given timeout (in milliseconds) to a deadline. */
+gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms);
 
 #ifndef GRPC_TEST_CUSTOM_PICK_PORT
 #define GRPC_TEST_PICK_PORT
diff --git a/test/core/util/test_tcp_server.c b/test/core/util/test_tcp_server.c
index 2338b81..496e579 100644
--- a/test/core/util/test_tcp_server.c
+++ b/test/core/util/test_tcp_server.c
@@ -60,7 +60,7 @@
   grpc_closure_init(&server->shutdown_complete, on_server_destroyed, server,
                     grpc_schedule_on_exec_ctx);
   server->shutdown = 0;
-  server->pollset = gpr_malloc(grpc_pollset_size());
+  server->pollset = gpr_zalloc(grpc_pollset_size());
   grpc_pollset_init(server->pollset, &server->mu);
   server->on_connect = on_connect;
   server->cb_data = user_data;
diff --git a/test/core/util/trickle_endpoint.c b/test/core/util/trickle_endpoint.c
new file mode 100644
index 0000000..7ab0488
--- /dev/null
+++ b/test/core/util/trickle_endpoint.c
@@ -0,0 +1,196 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/core/util/passthru_endpoint.h"
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/iomgr/sockaddr.h"
+
+#include "src/core/lib/slice/slice_internal.h"
+
+typedef struct {
+  grpc_endpoint base;
+  double bytes_per_second;
+  grpc_endpoint *wrapped;
+  gpr_timespec last_write;
+
+  gpr_mu mu;
+  grpc_slice_buffer write_buffer;
+  grpc_slice_buffer writing_buffer;
+  grpc_error *error;
+  bool writing;
+} trickle_endpoint;
+
+static void te_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                    grpc_slice_buffer *slices, grpc_closure *cb) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  grpc_endpoint_read(exec_ctx, te->wrapped, slices, cb);
+}
+
+static void te_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                     grpc_slice_buffer *slices, grpc_closure *cb) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  for (size_t i = 0; i < slices->count; i++) {
+    grpc_slice_ref_internal(slices->slices[i]);
+  }
+  gpr_mu_lock(&te->mu);
+  if (te->write_buffer.length == 0) {
+    te->last_write = gpr_now(GPR_CLOCK_MONOTONIC);
+  }
+  grpc_slice_buffer_addn(&te->write_buffer, slices->slices, slices->count);
+  grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_REF(te->error));
+  gpr_mu_unlock(&te->mu);
+}
+
+static grpc_workqueue *te_get_workqueue(grpc_endpoint *ep) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  return grpc_endpoint_get_workqueue(te->wrapped);
+}
+
+static void te_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                              grpc_pollset *pollset) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  grpc_endpoint_add_to_pollset(exec_ctx, te->wrapped, pollset);
+}
+
+static void te_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                  grpc_pollset_set *pollset_set) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  grpc_endpoint_add_to_pollset_set(exec_ctx, te->wrapped, pollset_set);
+}
+
+static void te_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                        grpc_error *why) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  gpr_mu_lock(&te->mu);
+  if (te->error == GRPC_ERROR_NONE) {
+    te->error = GRPC_ERROR_REF(why);
+  }
+  gpr_mu_unlock(&te->mu);
+  grpc_endpoint_shutdown(exec_ctx, te->wrapped, why);
+}
+
+static void te_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  grpc_endpoint_destroy(exec_ctx, te->wrapped);
+  gpr_mu_destroy(&te->mu);
+  grpc_slice_buffer_destroy_internal(exec_ctx, &te->write_buffer);
+  grpc_slice_buffer_destroy_internal(exec_ctx, &te->writing_buffer);
+  GRPC_ERROR_UNREF(te->error);
+  gpr_free(te);
+}
+
+static grpc_resource_user *te_get_resource_user(grpc_endpoint *ep) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  return grpc_endpoint_get_resource_user(te->wrapped);
+}
+
+static char *te_get_peer(grpc_endpoint *ep) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  return grpc_endpoint_get_peer(te->wrapped);
+}
+
+static int te_get_fd(grpc_endpoint *ep) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  return grpc_endpoint_get_fd(te->wrapped);
+}
+
+static void te_finish_write(grpc_exec_ctx *exec_ctx, void *arg,
+                            grpc_error *error) {
+  trickle_endpoint *te = arg;
+  gpr_mu_lock(&te->mu);
+  te->writing = false;
+  grpc_slice_buffer_reset_and_unref(&te->writing_buffer);
+  gpr_mu_unlock(&te->mu);
+}
+
+static const grpc_endpoint_vtable vtable = {te_read,
+                                            te_write,
+                                            te_get_workqueue,
+                                            te_add_to_pollset,
+                                            te_add_to_pollset_set,
+                                            te_shutdown,
+                                            te_destroy,
+                                            te_get_resource_user,
+                                            te_get_peer,
+                                            te_get_fd};
+
+grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap,
+                                            double bytes_per_second) {
+  trickle_endpoint *te = gpr_malloc(sizeof(*te));
+  te->base.vtable = &vtable;
+  te->wrapped = wrap;
+  te->bytes_per_second = bytes_per_second;
+  gpr_mu_init(&te->mu);
+  grpc_slice_buffer_init(&te->write_buffer);
+  grpc_slice_buffer_init(&te->writing_buffer);
+  te->error = GRPC_ERROR_NONE;
+  te->writing = false;
+  return &te->base;
+}
+
+static double ts2dbl(gpr_timespec s) {
+  return (double)s.tv_sec + 1e-9 * (double)s.tv_nsec;
+}
+
+size_t grpc_trickle_endpoint_trickle(grpc_exec_ctx *exec_ctx,
+                                     grpc_endpoint *ep) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  gpr_mu_lock(&te->mu);
+  if (!te->writing && te->write_buffer.length > 0) {
+    gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
+    double elapsed = ts2dbl(gpr_time_sub(now, te->last_write));
+    size_t bytes = (size_t)(te->bytes_per_second * elapsed);
+    // gpr_log(GPR_DEBUG, "%lf elapsed --> %" PRIdPTR " bytes", elapsed, bytes);
+    if (bytes > 0) {
+      grpc_slice_buffer_move_first(&te->write_buffer,
+                                   GPR_MIN(bytes, te->write_buffer.length),
+                                   &te->writing_buffer);
+      te->writing = true;
+      te->last_write = now;
+      grpc_endpoint_write(
+          exec_ctx, te->wrapped, &te->writing_buffer,
+          grpc_closure_create(te_finish_write, te, grpc_schedule_on_exec_ctx));
+    }
+  }
+  size_t backlog = te->write_buffer.length;
+  gpr_mu_unlock(&te->mu);
+  return backlog;
+}
diff --git a/test/core/util/trickle_endpoint.h b/test/core/util/trickle_endpoint.h
new file mode 100644
index 0000000..7e8d9d9
--- /dev/null
+++ b/test/core/util/trickle_endpoint.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef TRICKLE_ENDPOINT_H
+#define TRICKLE_ENDPOINT_H
+
+#include "src/core/lib/iomgr/endpoint.h"
+
+grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap,
+                                            double bytes_per_second);
+
+/* Allow up to \a bytes through the endpoint. Returns the new backlog. */
+size_t grpc_trickle_endpoint_trickle(grpc_exec_ctx *exec_ctx,
+                                     grpc_endpoint *endpoint);
+
+#endif
diff --git a/test/cpp/codegen/BUILD b/test/cpp/codegen/BUILD
new file mode 100644
index 0000000..14d5733
--- /dev/null
+++ b/test/cpp/codegen/BUILD
@@ -0,0 +1,77 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+cc_test(
+    name = "codegen_test_full",
+    srcs = ["codegen_test_full.cc"],
+    deps = [
+        "//:grpc++",
+        "//external:gtest",
+        "//test/core/util:gpr_test_util",
+    ],
+)
+
+cc_test(
+    name = "codegen_test_minimal",
+    srcs = ["codegen_test_minimal.cc"],
+    deps = [
+        "//:grpc++",
+        "//external:gtest",
+        "//test/core/util:gpr_test_util",
+    ],
+)
+
+cc_test(
+    name = "proto_utils_test",
+    srcs = ["proto_utils_test.cc"],
+    deps = [
+        "//:grpc++",
+        "//external:gtest",
+        "//test/core/util:gpr_test_util",
+    ],
+)
+
+cc_test(
+    name = "golden_file_test",
+    srcs = ["golden_file_test.cc"],
+    args = ["--generated_file_path=$(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.h"],
+    data = [
+        ":compiler_test_golden",
+        "//src/proto/grpc/testing:_compiler_test_proto_grpc_codegen",
+    ],
+    deps = [
+        "//:grpc++",
+        "//external:gflags",
+        "//external:gtest",
+        "//src/proto/grpc/testing:compiler_test_proto",
+        "//test/core/util:gpr_test_util",
+    ],
+)
diff --git a/test/cpp/codegen/codegen_test_full.cc b/test/cpp/codegen/codegen_test_full.cc
index d6e2416..bc19fc9 100644
--- a/test/cpp/codegen/codegen_test_full.cc
+++ b/test/cpp/codegen/codegen_test_full.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2016, Google Inc.
+ * Copyright 2017, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/codegen/golden_file_test.cc b/test/cpp/codegen/golden_file_test.cc
index ec08d08..158a4d9 100644
--- a/test/cpp/codegen/golden_file_test.cc
+++ b/test/cpp/codegen/golden_file_test.cc
@@ -34,15 +34,18 @@
 #include <fstream>
 #include <sstream>
 
+#include <gflags/gflags.h>
 #include <gtest/gtest.h>
 
-// These paths rely on the fact that we run our tests under grpc/
-const char kGeneratedFilePath[] =
-    "gens/src/proto/grpc/testing/compiler_test.grpc.pb.h";
+DEFINE_string(generated_file_path, "",
+              "path to the generated compiler_test.grpc.pb.h file");
+
 const char kGoldenFilePath[] = "test/cpp/codegen/compiler_test_golden";
 
 TEST(GoldenFileTest, TestGeneratedFile) {
-  std::ifstream generated(kGeneratedFilePath);
+  ASSERT_FALSE(FLAGS_generated_file_path.empty());
+
+  std::ifstream generated(FLAGS_generated_file_path);
   std::ifstream golden(kGoldenFilePath);
 
   ASSERT_TRUE(generated.good());
@@ -60,5 +63,6 @@
 
 int main(int argc, char **argv) {
   ::testing::InitGoogleTest(&argc, argv);
+  ::google::ParseCommandLineFlags(&argc, &argv, true);
   return RUN_ALL_TESTS();
 }
diff --git a/test/cpp/codegen/proto_utils_test.cc b/test/cpp/codegen/proto_utils_test.cc
new file mode 100644
index 0000000..1daa142
--- /dev/null
+++ b/test/cpp/codegen/proto_utils_test.cc
@@ -0,0 +1,93 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc++/impl/codegen/proto_utils.h>
+#include <grpc++/impl/grpc_library.h>
+#include <gtest/gtest.h>
+
+namespace grpc {
+namespace internal {
+
+static GrpcLibraryInitializer g_gli_initializer;
+
+// Provide access to GrpcBufferWriter internals.
+class GrpcBufferWriterPeer {
+ public:
+  explicit GrpcBufferWriterPeer(internal::GrpcBufferWriter* writer)
+      : writer_(writer) {}
+  bool have_backup() const { return writer_->have_backup_; }
+  const grpc_slice& backup_slice() const { return writer_->backup_slice_; }
+  const grpc_slice& slice() const { return writer_->slice_; }
+
+ private:
+  GrpcBufferWriter* writer_;
+};
+
+class ProtoUtilsTest : public ::testing::Test {};
+
+// Regression test for a memory corruption bug where a series of
+// GrpcBufferWriter Next()/Backup() invocations could result in a dangling
+// pointer returned by Next() due to the interaction between grpc_slice inlining
+// and GRPC_SLICE_START_PTR.
+TEST_F(ProtoUtilsTest, BackupNext) {
+  // Ensure the GrpcBufferWriter internals are initialized.
+  g_gli_initializer.summon();
+
+  grpc_byte_buffer* bp;
+  GrpcBufferWriter writer(&bp, 8192);
+  GrpcBufferWriterPeer peer(&writer);
+
+  void* data;
+  int size;
+  // Allocate a slice.
+  ASSERT_TRUE(writer.Next(&data, &size));
+  EXPECT_EQ(8192, size);
+  // Return a single byte. Before the fix that this test acts as a regression
+  // for, this would have resulted in an inlined backup slice.
+  writer.BackUp(1);
+  EXPECT_TRUE(!peer.have_backup());
+  // On the next allocation, the slice is non-inlined.
+  ASSERT_TRUE(writer.Next(&data, &size));
+  EXPECT_TRUE(peer.slice().refcount != NULL);
+
+  // Cleanup.
+  g_core_codegen_interface->grpc_byte_buffer_destroy(bp);
+}
+
+}  // namespace internal
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/common/BUILD b/test/cpp/common/BUILD
new file mode 100644
index 0000000..0e2db00
--- /dev/null
+++ b/test/cpp/common/BUILD
@@ -0,0 +1,36 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+cc_test(
+    name = "alarm_cpp_test",
+    srcs = ["alarm_cpp_test.cc"],
+    deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util"],
+)
diff --git a/test/cpp/common/alarm_cpp_test.cc b/test/cpp/common/alarm_cpp_test.cc
index a05ac30..4108517 100644
--- a/test/cpp/common/alarm_cpp_test.cc
+++ b/test/cpp/common/alarm_cpp_test.cc
@@ -43,12 +43,12 @@
 TEST(AlarmTest, RegularExpiry) {
   CompletionQueue cq;
   void* junk = reinterpret_cast<void*>(1618033);
-  Alarm alarm(&cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), junk);
+  Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(1), junk);
 
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status = cq.AsyncNext(
-      (void**)&output_tag, &ok, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2));
+      (void**)&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
@@ -65,7 +65,7 @@
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status = cq.AsyncNext(
-      (void**)&output_tag, &ok, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2));
+      (void**)&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
@@ -75,12 +75,12 @@
 TEST(AlarmTest, ZeroExpiry) {
   CompletionQueue cq;
   void* junk = reinterpret_cast<void*>(1618033);
-  Alarm alarm(&cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(0), junk);
+  Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(0), junk);
 
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status = cq.AsyncNext(
-      (void**)&output_tag, &ok, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(0));
+      (void**)&output_tag, &ok, grpc_timeout_seconds_to_deadline(0));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
@@ -90,12 +90,12 @@
 TEST(AlarmTest, NegativeExpiry) {
   CompletionQueue cq;
   void* junk = reinterpret_cast<void*>(1618033);
-  Alarm alarm(&cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(-1), junk);
+  Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(-1), junk);
 
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status = cq.AsyncNext(
-      (void**)&output_tag, &ok, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(0));
+      (void**)&output_tag, &ok, grpc_timeout_seconds_to_deadline(0));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
@@ -105,13 +105,13 @@
 TEST(AlarmTest, Cancellation) {
   CompletionQueue cq;
   void* junk = reinterpret_cast<void*>(1618033);
-  Alarm alarm(&cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2), junk);
+  Alarm alarm(&cq, grpc_timeout_seconds_to_deadline(2), junk);
   alarm.Cancel();
 
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status = cq.AsyncNext(
-      (void**)&output_tag, &ok, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
+      (void**)&output_tag, &ok, grpc_timeout_seconds_to_deadline(1));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_FALSE(ok);
diff --git a/test/cpp/common/channel_filter_test.cc b/test/cpp/common/channel_filter_test.cc
index 32246a4..d78b05e 100644
--- a/test/cpp/common/channel_filter_test.cc
+++ b/test/cpp/common/channel_filter_test.cc
@@ -55,7 +55,7 @@
   MyCallData() {}
 
   grpc_error* Init(grpc_exec_ctx* exec_ctx, ChannelData* channel_data,
-                   grpc_call_element_args* args) override {
+                   const grpc_call_element_args* args) override {
     (void)args->path;  // Make sure field is available.
     return GRPC_ERROR_NONE;
   }
diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD
new file mode 100644
index 0000000..0bf7948
--- /dev/null
+++ b/test/cpp/end2end/BUILD
@@ -0,0 +1,323 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+cc_library(
+    name = "test_service_impl",
+    srcs = ["test_service_impl.cc"],
+    hdrs = ["test_service_impl.h"],
+    deps = [
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_proto",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "async_end2end_test",
+    srcs = ["async_end2end_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "client_crash_test",
+    srcs = ["client_crash_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "client_crash_test_server",
+    srcs = ["client_crash_test_server.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gflags",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "end2end_test",
+    srcs = ["end2end_test.cc"],
+    deps = [
+        ":test_service_impl",
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "filter_end2end_test",
+    srcs = ["filter_end2end_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "generic_end2end_test",
+    srcs = ["generic_end2end_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "hybrid_end2end_test",
+    srcs = ["hybrid_end2end_test.cc"],
+    deps = [
+        ":test_service_impl",
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "mock_test",
+    srcs = ["mock_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "round_robin_end2end_test",
+    srcs = ["round_robin_end2end_test.cc"],
+    deps = [
+        ":test_service_impl",
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "proto_server_reflection_test",
+    srcs = ["proto_server_reflection_test.cc"],
+    deps = [
+        ":test_service_impl",
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//:grpc++_reflection",
+        "//external:gflags",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:grpc++_proto_reflection_desc_db",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "server_builder_plugin_test",
+    srcs = ["server_builder_plugin_test.cc"],
+    deps = [
+        ":test_service_impl",
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "server_crash_test",
+    srcs = ["server_crash_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "server_crash_test_client",
+    srcs = ["server_crash_test_client.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gflags",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "shutdown_test",
+    srcs = ["shutdown_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "streaming_throughput_test",
+    srcs = ["streaming_throughput_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
+
+cc_test(
+    name = "thread_stress_test",
+    srcs = ["thread_stress_test.cc"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//:grpc++",
+        "//external:gtest",
+        "//src/proto/grpc/testing:echo_messages_proto",
+        "//src/proto/grpc/testing:echo_proto",
+        "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+        "//test/cpp/util:test_util",
+    ],
+)
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index 2ce3f2f..32e8a41 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -42,6 +42,7 @@
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
 #include <grpc/grpc.h>
+#include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 #include <grpc/support/tls.h>
@@ -228,12 +229,7 @@
       : disable_blocking(non_block),
         credentials_type(creds_type),
         message_content(content) {}
-  void Log() const {
-    gpr_log(
-        GPR_INFO,
-        "Scenario: disable_blocking %d, credentials %s, message size %" PRIuPTR,
-        disable_blocking, credentials_type.c_str(), message_content.size());
-  }
+  void Log() const;
   bool disable_blocking;
   // Although the below grpc::string's are logically const, we can't declare
   // them const because of a limitation in the way old compilers (e.g., gcc-4.4)
@@ -242,6 +238,20 @@
   grpc::string message_content;
 };
 
+static std::ostream& operator<<(std::ostream& out,
+                                const TestScenario& scenario) {
+  return out << "TestScenario{disable_blocking="
+             << (scenario.disable_blocking ? "true" : "false")
+             << ", credentials='" << scenario.credentials_type
+             << "', message_size=" << scenario.message_content.size() << "}";
+}
+
+void TestScenario::Log() const {
+  std::ostringstream out;
+  out << *this;
+  gpr_log(GPR_DEBUG, "%s", out.str().c_str());
+}
+
 class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
  protected:
   AsyncEnd2endTest() { GetParam().Log(); }
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 1a1a94e..df78557 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -209,10 +209,7 @@
  public:
   TestScenario(bool proxy, const grpc::string& creds_type)
       : use_proxy(proxy), credentials_type(creds_type) {}
-  void Log() const {
-    gpr_log(GPR_INFO, "Scenario: proxy %d, credentials %s", use_proxy,
-            credentials_type.c_str());
-  }
+  void Log() const;
   bool use_proxy;
   // Although the below grpc::string is logically const, we can't declare
   // them const because of a limitation in the way old compilers (e.g., gcc-4.4)
@@ -220,6 +217,19 @@
   grpc::string credentials_type;
 };
 
+static std::ostream& operator<<(std::ostream& out,
+                                const TestScenario& scenario) {
+  return out << "TestScenario{use_proxy="
+             << (scenario.use_proxy ? "true" : "false") << ", credentials='"
+             << scenario.credentials_type << "'}";
+}
+
+void TestScenario::Log() const {
+  std::ostringstream out;
+  out << *this;
+  gpr_log(GPR_DEBUG, "%s", out.str().c_str());
+}
+
 class End2endTest : public ::testing::TestWithParam<TestScenario> {
  protected:
   End2endTest()
@@ -636,7 +646,7 @@
   TestBidiStreamServerCancel(CANCEL_AFTER_PROCESSING, 5);
 }
 
-TEST_P(End2endTest, SimpleRpcWithCustomeUserAgentPrefix) {
+TEST_P(End2endTest, SimpleRpcWithCustomUserAgentPrefix) {
   user_agent_prefix_ = "custom_prefix";
   ResetStub();
   EchoRequest request;
@@ -891,6 +901,7 @@
   EchoRequest request;
   EchoResponse response;
   request.set_message(string(kMaxMessageSize_ * 2, 'a'));
+  request.mutable_param()->set_server_die(true);
 
   ClientContext context;
   Status s = stub_->Echo(&context, request, &response);
@@ -1293,6 +1304,7 @@
   EXPECT_FALSE(s.ok());
   EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
 }
+
 TEST_P(SecureEnd2endTest, SetPerCallCredentials) {
   ResetStub();
   EchoRequest request;
diff --git a/test/cpp/end2end/health_service_end2end_test.cc b/test/cpp/end2end/health_service_end2end_test.cc
new file mode 100644
index 0000000..3d51007
--- /dev/null
+++ b/test/cpp/end2end/health_service_end2end_test.cc
@@ -0,0 +1,323 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include <grpc++/channel.h>
+#include <grpc++/client_context.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/ext/health_check_service_server_builder_option.h>
+#include <grpc++/health_check_service_interface.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc++/server_context.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <gtest/gtest.h>
+
+#include "src/proto/grpc/health/v1/health.grpc.pb.h"
+#include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+#include "test/cpp/end2end/test_service_impl.h"
+
+using grpc::health::v1::Health;
+using grpc::health::v1::HealthCheckRequest;
+using grpc::health::v1::HealthCheckResponse;
+
+namespace grpc {
+namespace testing {
+namespace {
+
+// A sample sync implementation of the health checking service. This does the
+// same thing as the default one.
+class HealthCheckServiceImpl : public ::grpc::health::v1::Health::Service {
+ public:
+  Status Check(ServerContext* context, const HealthCheckRequest* request,
+               HealthCheckResponse* response) override {
+    std::lock_guard<std::mutex> lock(mu_);
+    auto iter = status_map_.find(request->service());
+    if (iter == status_map_.end()) {
+      return Status(StatusCode::NOT_FOUND, "");
+    }
+    response->set_status(iter->second);
+    return Status::OK;
+  }
+
+  void SetStatus(const grpc::string& service_name,
+                 HealthCheckResponse::ServingStatus status) {
+    std::lock_guard<std::mutex> lock(mu_);
+    status_map_[service_name] = status;
+  }
+
+  void SetAll(HealthCheckResponse::ServingStatus status) {
+    std::lock_guard<std::mutex> lock(mu_);
+    for (auto iter = status_map_.begin(); iter != status_map_.end(); ++iter) {
+      iter->second = status;
+    }
+  }
+
+ private:
+  std::mutex mu_;
+  std::map<const grpc::string, HealthCheckResponse::ServingStatus> status_map_;
+};
+
+// A custom implementation of the health checking service interface. This is
+// used to test that it prevents the server from creating a default service and
+// also serves as an example of how to override the default service.
+class CustomHealthCheckService : public HealthCheckServiceInterface {
+ public:
+  explicit CustomHealthCheckService(HealthCheckServiceImpl* impl)
+      : impl_(impl) {
+    impl_->SetStatus("", HealthCheckResponse::SERVING);
+  }
+  void SetServingStatus(const grpc::string& service_name,
+                        bool serving) override {
+    impl_->SetStatus(service_name, serving ? HealthCheckResponse::SERVING
+                                           : HealthCheckResponse::NOT_SERVING);
+  }
+
+  void SetServingStatus(bool serving) override {
+    impl_->SetAll(serving ? HealthCheckResponse::SERVING
+                          : HealthCheckResponse::NOT_SERVING);
+  }
+
+ private:
+  HealthCheckServiceImpl* impl_;  // not owned
+};
+
+void LoopCompletionQueue(ServerCompletionQueue* cq) {
+  void* tag;
+  bool ok;
+  while (cq->Next(&tag, &ok)) {
+    abort();  // Nothing should come out of the cq.
+  }
+}
+
+class HealthServiceEnd2endTest : public ::testing::Test {
+ protected:
+  HealthServiceEnd2endTest() {}
+
+  void SetUpServer(bool register_sync_test_service, bool add_async_cq,
+                   bool explicit_health_service,
+                   std::unique_ptr<HealthCheckServiceInterface> service) {
+    int port = grpc_pick_unused_port_or_die();
+    server_address_ << "localhost:" << port;
+
+    bool register_sync_health_service_impl =
+        explicit_health_service && service != nullptr;
+
+    // Setup server
+    ServerBuilder builder;
+    if (explicit_health_service) {
+      std::unique_ptr<ServerBuilderOption> option(
+          new HealthCheckServiceServerBuilderOption(std::move(service)));
+      builder.SetOption(std::move(option));
+    }
+    builder.AddListeningPort(server_address_.str(),
+                             grpc::InsecureServerCredentials());
+    if (register_sync_test_service) {
+      // Register a sync service.
+      builder.RegisterService(&echo_test_service_);
+    }
+    if (register_sync_health_service_impl) {
+      builder.RegisterService(&health_check_service_impl_);
+    }
+    if (add_async_cq) {
+      cq_ = builder.AddCompletionQueue();
+    }
+    server_ = builder.BuildAndStart();
+  }
+
+  void TearDown() override {
+    if (server_) {
+      server_->Shutdown();
+      if (cq_ != nullptr) {
+        cq_->Shutdown();
+      }
+      if (cq_thread_.joinable()) {
+        cq_thread_.join();
+      }
+    }
+  }
+
+  void ResetStubs() {
+    std::shared_ptr<Channel> channel =
+        CreateChannel(server_address_.str(), InsecureChannelCredentials());
+    hc_stub_ = grpc::health::v1::Health::NewStub(channel);
+  }
+
+  // When the expected_status is NOT OK, we do not care about the response.
+  void SendHealthCheckRpc(const grpc::string& service_name,
+                          const Status& expected_status) {
+    EXPECT_FALSE(expected_status.ok());
+    SendHealthCheckRpc(service_name, expected_status,
+                       HealthCheckResponse::UNKNOWN);
+  }
+
+  void SendHealthCheckRpc(
+      const grpc::string& service_name, const Status& expected_status,
+      HealthCheckResponse::ServingStatus expected_serving_status) {
+    HealthCheckRequest request;
+    request.set_service(service_name);
+    HealthCheckResponse response;
+    ClientContext context;
+    Status s = hc_stub_->Check(&context, request, &response);
+    EXPECT_EQ(expected_status.error_code(), s.error_code());
+    if (s.ok()) {
+      EXPECT_EQ(expected_serving_status, response.status());
+    }
+  }
+
+  void VerifyHealthCheckService() {
+    HealthCheckServiceInterface* service = server_->GetHealthCheckService();
+    EXPECT_TRUE(service != nullptr);
+    const grpc::string kHealthyService("healthy_service");
+    const grpc::string kUnhealthyService("unhealthy_service");
+    const grpc::string kNotRegisteredService("not_registered");
+    service->SetServingStatus(kHealthyService, true);
+    service->SetServingStatus(kUnhealthyService, false);
+
+    ResetStubs();
+
+    SendHealthCheckRpc("", Status::OK, HealthCheckResponse::SERVING);
+    SendHealthCheckRpc(kHealthyService, Status::OK,
+                       HealthCheckResponse::SERVING);
+    SendHealthCheckRpc(kUnhealthyService, Status::OK,
+                       HealthCheckResponse::NOT_SERVING);
+    SendHealthCheckRpc(kNotRegisteredService,
+                       Status(StatusCode::NOT_FOUND, ""));
+
+    service->SetServingStatus(false);
+    SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING);
+    SendHealthCheckRpc(kHealthyService, Status::OK,
+                       HealthCheckResponse::NOT_SERVING);
+    SendHealthCheckRpc(kUnhealthyService, Status::OK,
+                       HealthCheckResponse::NOT_SERVING);
+    SendHealthCheckRpc(kNotRegisteredService,
+                       Status(StatusCode::NOT_FOUND, ""));
+  }
+
+  TestServiceImpl echo_test_service_;
+  HealthCheckServiceImpl health_check_service_impl_;
+  std::unique_ptr<Health::Stub> hc_stub_;
+  std::unique_ptr<ServerCompletionQueue> cq_;
+  std::unique_ptr<Server> server_;
+  std::ostringstream server_address_;
+  std::thread cq_thread_;
+};
+
+TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) {
+  EnableDefaultHealthCheckService(false);
+  EXPECT_FALSE(DefaultHealthCheckServiceEnabled());
+  SetUpServer(true, false, false, nullptr);
+  HealthCheckServiceInterface* default_service =
+      server_->GetHealthCheckService();
+  EXPECT_TRUE(default_service == nullptr);
+
+  ResetStubs();
+
+  SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, ""));
+}
+
+TEST_F(HealthServiceEnd2endTest, DefaultHealthService) {
+  EnableDefaultHealthCheckService(true);
+  EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
+  SetUpServer(true, false, false, nullptr);
+  VerifyHealthCheckService();
+
+  // The default service has a size limit of the service name.
+  const grpc::string kTooLongServiceName(201, 'x');
+  SendHealthCheckRpc(kTooLongServiceName,
+                     Status(StatusCode::INVALID_ARGUMENT, ""));
+}
+
+// The server has no sync service.
+TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceAsyncOnly) {
+  EnableDefaultHealthCheckService(true);
+  EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
+  SetUpServer(false, true, false, nullptr);
+  cq_thread_ = std::thread(LoopCompletionQueue, cq_.get());
+
+  HealthCheckServiceInterface* default_service =
+      server_->GetHealthCheckService();
+  EXPECT_TRUE(default_service == nullptr);
+
+  ResetStubs();
+
+  SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, ""));
+}
+
+// Provide an empty service to disable the default service.
+TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) {
+  EnableDefaultHealthCheckService(true);
+  EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
+  std::unique_ptr<HealthCheckServiceInterface> empty_service;
+  SetUpServer(true, false, true, std::move(empty_service));
+  HealthCheckServiceInterface* service = server_->GetHealthCheckService();
+  EXPECT_TRUE(service == nullptr);
+
+  ResetStubs();
+
+  SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, ""));
+}
+
+// Provide an explicit override of health checking service interface.
+TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) {
+  EnableDefaultHealthCheckService(true);
+  EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
+  std::unique_ptr<HealthCheckServiceInterface> override_service(
+      new CustomHealthCheckService(&health_check_service_impl_));
+  HealthCheckServiceInterface* underlying_service = override_service.get();
+  SetUpServer(false, false, true, std::move(override_service));
+  HealthCheckServiceInterface* service = server_->GetHealthCheckService();
+  EXPECT_TRUE(service == underlying_service);
+
+  ResetStubs();
+
+  VerifyHealthCheckService();
+}
+
+}  // namespace
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  grpc_test_init(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc
index 5b52b1f..bd68e85 100644
--- a/test/cpp/end2end/shutdown_test.cc
+++ b/test/cpp/end2end/shutdown_test.cc
@@ -49,6 +49,7 @@
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
+#include "test/cpp/util/test_credentials_provider.h"
 
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
@@ -72,7 +73,7 @@
   gpr_event* ev_;
 };
 
-class ShutdownTest : public ::testing::Test {
+class ShutdownTest : public ::testing::TestWithParam<string> {
  public:
   ShutdownTest() : shutdown_(false), service_(&ev_) { gpr_event_init(&ev_); }
 
@@ -85,7 +86,9 @@
     grpc::string server_address = "localhost:" + to_string(port);
 
     ServerBuilder builder;
-    builder.AddListeningPort(server_address, InsecureServerCredentials());
+    auto server_creds =
+        GetCredentialsProvider()->GetServerCredentials(GetParam());
+    builder.AddListeningPort(server_address, server_creds);
     builder.RegisterService(&service_);
     std::unique_ptr<Server> server = builder.BuildAndStart();
     return server;
@@ -95,7 +98,10 @@
 
   void ResetStub() {
     string target = "dns:localhost:" + to_string(port_);
-    channel_ = CreateChannel(target, InsecureChannelCredentials());
+    ChannelArguments args;
+    auto channel_creds =
+        GetCredentialsProvider()->GetChannelCredentials(GetParam(), &args);
+    channel_ = CreateCustomChannel(target, channel_creds, args);
     stub_ = grpc::testing::EchoTestService::NewStub(channel_);
   }
 
@@ -125,8 +131,31 @@
   TestServiceImpl service_;
 };
 
+std::vector<string> GetAllCredentialsTypeList() {
+  std::vector<grpc::string> credentials_types;
+  if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType,
+                                                      nullptr) != nullptr) {
+    credentials_types.push_back(kInsecureCredentialsType);
+  }
+  auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList();
+  for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) {
+    credentials_types.push_back(*sec);
+  }
+  GPR_ASSERT(!credentials_types.empty());
+
+  std::string credentials_type_list("credentials types:");
+  for (const string& type : credentials_types) {
+    credentials_type_list.append(" " + type);
+  }
+  gpr_log(GPR_INFO, "%s", credentials_type_list.c_str());
+  return credentials_types;
+}
+
+INSTANTIATE_TEST_CASE_P(End2EndShutdown, ShutdownTest,
+                        ::testing::ValuesIn(GetAllCredentialsTypeList()));
+
 // TODO(ctiller): leaked objects in this test
-TEST_F(ShutdownTest, ShutdownTest) {
+TEST_P(ShutdownTest, ShutdownTest) {
   ResetStub();
 
   // send the request in a background thread
diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc
index 0010477..59d36e9 100644
--- a/test/cpp/end2end/test_service_impl.cc
+++ b/test/cpp/end2end/test_service_impl.cc
@@ -88,6 +88,10 @@
 
 Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request,
                              EchoResponse* response) {
+  if (request->has_param() && request->param().server_die()) {
+    gpr_log(GPR_ERROR, "The request should not reach application handler.");
+    GPR_ASSERT(0);
+  }
   int server_try_cancel = GetIntValueFromMetadata(
       kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL);
   if (server_try_cancel > DO_NOT_CANCEL) {
diff --git a/test/cpp/grpclb/grpclb_api_test.cc b/test/cpp/grpclb/grpclb_api_test.cc
index 191d729..82ccf43 100644
--- a/test/cpp/grpclb/grpclb_api_test.cc
+++ b/test/cpp/grpclb/grpclb_api_test.cc
@@ -63,7 +63,7 @@
   } else {
     abort();
   }
-  GPR_ASSERT(inet_ntop(af, pb_ip.bytes, ip_str, 46) != NULL);
+  GPR_ASSERT(inet_ntop(af, (void*)pb_ip.bytes, ip_str, 46) != NULL);
   return ip_str;
 }
 
diff --git a/test/cpp/grpclb/grpclb_test.cc b/test/cpp/grpclb/grpclb_test.cc
index 3637190..89ed924 100644
--- a/test/cpp/grpclb/grpclb_test.cc
+++ b/test/cpp/grpclb/grpclb_test.cc
@@ -52,8 +52,10 @@
 #include <grpc++/impl/codegen/config.h>
 extern "C" {
 #include "src/core/ext/client_channel/client_channel.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_stack.h"
 #include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/security/credentials/fake/fake_credentials.h"
 #include "src/core/lib/support/string.h"
 #include "src/core/lib/support/tmpfile.h"
 #include "src/core/lib/surface/channel.h"
@@ -110,6 +112,7 @@
   grpc_call *server_call;
   grpc_completion_queue *cq;
   char *servers_hostport;
+  const char *balancer_name;
   int port;
   const char *lb_token_prefix;
   gpr_thd_id tid;
@@ -170,7 +173,7 @@
 static void drain_cq(grpc_completion_queue *cq) {
   grpc_event ev;
   do {
-    ev = grpc_completion_queue_next(cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
+    ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5),
                                     NULL);
   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
 }
@@ -201,10 +204,12 @@
                                    &request_metadata_recv, sf->cq, sf->cq,
                                    tag(200));
   GPR_ASSERT(GRPC_CALL_OK == error);
-  gpr_log(GPR_INFO, "LB Server[%s] up", sf->servers_hostport);
+  gpr_log(GPR_INFO, "LB Server[%s](%s) up", sf->servers_hostport,
+          sf->balancer_name);
   CQ_EXPECT_COMPLETION(cqv, tag(200), 1);
   cq_verify(cqv);
-  gpr_log(GPR_INFO, "LB Server[%s] after tag 200", sf->servers_hostport);
+  gpr_log(GPR_INFO, "LB Server[%s](%s) after tag 200", sf->servers_hostport,
+          sf->balancer_name);
 
   // make sure we've received the initial metadata from the grpclb request.
   GPR_ASSERT(request_metadata_recv.count > 0);
@@ -221,7 +226,8 @@
   GPR_ASSERT(GRPC_CALL_OK == error);
   CQ_EXPECT_COMPLETION(cqv, tag(202), 1);
   cq_verify(cqv);
-  gpr_log(GPR_INFO, "LB Server[%s] after RECV_MSG", sf->servers_hostport);
+  gpr_log(GPR_INFO, "LB Server[%s](%s) after RECV_MSG", sf->servers_hostport,
+          sf->balancer_name);
 
   // validate initial request.
   grpc_byte_buffer_reader bbr;
@@ -250,7 +256,8 @@
   op++;
   error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(201), NULL);
   GPR_ASSERT(GRPC_CALL_OK == error);
-  gpr_log(GPR_INFO, "LB Server[%s] after tag 201", sf->servers_hostport);
+  gpr_log(GPR_INFO, "LB Server[%s](%s) after tag 201", sf->servers_hostport,
+          sf->balancer_name);
 
   for (int i = 0; i < 2; i++) {
     if (i == 0) {
@@ -276,19 +283,21 @@
     GPR_ASSERT(GRPC_CALL_OK == error);
     CQ_EXPECT_COMPLETION(cqv, tag(203), 1);
     cq_verify(cqv);
-    gpr_log(GPR_INFO, "LB Server[%s] after SEND_MESSAGE, iter %d",
-            sf->servers_hostport, i);
+    gpr_log(GPR_INFO, "LB Server[%s](%s) after SEND_MESSAGE, iter %d",
+            sf->servers_hostport, sf->balancer_name, i);
 
     grpc_byte_buffer_destroy(response_payload);
     grpc_slice_unref(response_payload_slice);
   }
-  gpr_log(GPR_INFO, "LB Server[%s] shutting down", sf->servers_hostport);
+  gpr_log(GPR_INFO, "LB Server[%s](%s) shutting down", sf->servers_hostport,
+          sf->balancer_name);
 
   op = ops;
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -298,8 +307,8 @@
   CQ_EXPECT_COMPLETION(cqv, tag(201), 1);
   CQ_EXPECT_COMPLETION(cqv, tag(204), 1);
   cq_verify(cqv);
-  gpr_log(GPR_INFO, "LB Server[%s] after tag 204. All done. LB server out",
-          sf->servers_hostport);
+  gpr_log(GPR_INFO, "LB Server[%s](%s) after tag 204. All done. LB server out",
+          sf->servers_hostport, sf->balancer_name);
 
   grpc_call_destroy(s);
 
@@ -335,7 +344,7 @@
     GPR_ASSERT(GRPC_CALL_OK == error);
     gpr_log(GPR_INFO, "Server[%s] up", sf->servers_hostport);
     ev = grpc_completion_queue_next(sf->cq,
-                                    GRPC_TIMEOUT_SECONDS_TO_DEADLINE(60), NULL);
+                                    grpc_timeout_seconds_to_deadline(60), NULL);
     if (!ev.success) {
       gpr_log(GPR_INFO, "Server[%s] being torn down", sf->servers_hostport);
       cq_verifier_destroy(cqv);
@@ -379,7 +388,7 @@
       error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
       GPR_ASSERT(GRPC_CALL_OK == error);
       ev = grpc_completion_queue_next(
-          sf->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), NULL);
+          sf->cq, grpc_timeout_seconds_to_deadline(3), NULL);
       if (ev.type == GRPC_OP_COMPLETE && ev.success) {
         GPR_ASSERT(ev.tag = tag(102));
         if (request_payload_recv == NULL) {
@@ -409,7 +418,7 @@
             grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL);
         GPR_ASSERT(GRPC_CALL_OK == error);
         ev = grpc_completion_queue_next(
-            sf->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), NULL);
+            sf->cq, grpc_timeout_seconds_to_deadline(3), NULL);
         if (ev.type == GRPC_OP_COMPLETE && ev.success) {
           GPR_ASSERT(ev.tag = tag(103));
         } else {
@@ -433,7 +442,9 @@
     op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
     op->data.send_status_from_server.trailing_metadata_count = 0;
     op->data.send_status_from_server.status = GRPC_STATUS_OK;
-    op->data.send_status_from_server.status_details = "Backend server out a-ok";
+    grpc_slice status_details =
+        grpc_slice_from_static_string("Backend server out a-ok");
+    op->data.send_status_from_server.status_details = &status_details;
     op->flags = 0;
     op->reserved = NULL;
     op++;
@@ -462,8 +473,7 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *request_payload;
   grpc_byte_buffer *response_payload_recv;
   int i;
@@ -472,9 +482,11 @@
   grpc_slice request_payload_slice =
       grpc_slice_from_copied_string("hello world");
 
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr:1234");
   c = grpc_channel_create_call(cf->client, NULL, GRPC_PROPAGATE_DEFAULTS,
-                               cf->cq, "/foo", "foo.test.google.fr:1234",
-                               GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL);
+                               cf->cq, grpc_slice_from_static_string("/foo"),
+                               &host, grpc_timeout_seconds_to_deadline(5),
+                               NULL);
   gpr_log(GPR_INFO, "Call 0x%" PRIxPTR " created", (intptr_t)c);
   GPR_ASSERT(c);
   char *peer;
@@ -497,7 +509,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -553,15 +564,43 @@
 
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
   gpr_log(GPR_INFO, "Client call (peer %s) DESTROYED.", peer);
   gpr_free(peer);
 }
 
-static void setup_client(const char *server_hostport, client_fixture *cf) {
+#define BALANCERS_NAME "lb.name"
+static void setup_client(const server_fixture *lb_server,
+                         const server_fixture *backends, client_fixture *cf) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  char *lb_uri;
+  // The grpclb LB policy will be automatically selected by virtue of
+  // the fact that the returned addresses are balancer addresses.
+  gpr_asprintf(&lb_uri, "test:///%s?lb_enabled=1&balancer_names=%s",
+               lb_server->servers_hostport, lb_server->balancer_name);
+
+  grpc_arg expected_target_arg;
+  expected_target_arg.type = GRPC_ARG_STRING;
+  expected_target_arg.key =
+      const_cast<char *>(GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS);
+
+  char *expected_target_names = NULL;
+  const char *backends_name = lb_server->servers_hostport;
+  gpr_asprintf(&expected_target_names, "%s;%s", backends_name, BALANCERS_NAME);
+
+  expected_target_arg.value.string = const_cast<char *>(expected_target_names);
+  grpc_channel_args *args =
+      grpc_channel_args_copy_and_add(NULL, &expected_target_arg, 1);
+  gpr_free(expected_target_names);
+
   cf->cq = grpc_completion_queue_create(NULL);
-  cf->server_uri = gpr_strdup(server_hostport);
-  cf->client = grpc_insecure_channel_create(cf->server_uri, NULL, NULL);
+  cf->server_uri = lb_uri;
+  grpc_channel_credentials *fake_creds =
+      grpc_fake_transport_security_credentials_create();
+  cf->client =
+      grpc_secure_channel_create(fake_creds, cf->server_uri, args, NULL);
+  grpc_channel_credentials_unref(&exec_ctx, fake_creds);
+  grpc_channel_args_destroy(&exec_ctx, args);
 }
 
 static void teardown_client(client_fixture *cf) {
@@ -588,10 +627,14 @@
     gpr_join_host_port(&sf->servers_hostport, host, sf->port);
   }
 
+  grpc_server_credentials *server_creds =
+      grpc_fake_transport_security_server_credentials_create();
+
   sf->server = grpc_server_create(NULL, NULL);
   grpc_server_register_completion_queue(sf->server, sf->cq, NULL);
-  GPR_ASSERT((assigned_port = grpc_server_add_insecure_http2_port(
-                  sf->server, sf->servers_hostport)) > 0);
+  GPR_ASSERT((assigned_port = grpc_server_add_secure_http2_port(
+                  sf->server, sf->servers_hostport, server_creds)) > 0);
+  grpc_server_credentials_release(server_creds);
   GPR_ASSERT(sf->port == assigned_port);
   grpc_server_start(sf->server);
 }
@@ -602,7 +645,7 @@
   gpr_log(GPR_INFO, "Server[%s] shutting down", sf->servers_hostport);
   grpc_server_shutdown_and_notify(sf->server, sf->cq, tag(1000));
   GPR_ASSERT(grpc_completion_queue_pluck(
-                 sf->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 sf->cq, tag(1000), grpc_timeout_seconds_to_deadline(5), NULL)
                  .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(sf->server);
   gpr_thd_join(sf->tid);
@@ -653,17 +696,10 @@
   }
 
   tf.lb_server.lb_token_prefix = LB_TOKEN_PREFIX;
+  tf.lb_server.balancer_name = BALANCERS_NAME;
   setup_server("127.0.0.1", &tf.lb_server);
   gpr_thd_new(&tf.lb_server.tid, fork_lb_server, &tf.lb_server, &options);
-
-  char *server_uri;
-  // The grpclb LB policy will be automatically selected by virtue of
-  // the fact that the returned addresses are balancer addresses.
-  gpr_asprintf(&server_uri, "test:///%s?lb_enabled=1",
-               tf.lb_server.servers_hostport);
-  setup_client(server_uri, &tf.client);
-  gpr_free(server_uri);
-
+  setup_client(&tf.lb_server, tf.lb_backends, &tf.client);
   return tf;
 }
 
@@ -708,8 +744,9 @@
   // batch 1. All subsequent picks will come from the second half of the
   // backends, those coming in the LB update.
   tf_result = grpc::test_update(800);
-  GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1);
-  GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 0);
+  GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced +
+                 tf_result.lb_backends[1].num_calls_serviced ==
+             1);
   GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced +
                  tf_result.lb_backends[3].num_calls_serviced >
              0);
@@ -725,8 +762,9 @@
   // update. In any case, the total number of serviced calls must again be equal
   // to four across all the backends.
   tf_result = grpc::test_update(2500);
-  GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced >= 1);
-  GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1);
+  GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced +
+                 tf_result.lb_backends[1].num_calls_serviced >=
+             2);
   GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced +
                  tf_result.lb_backends[3].num_calls_serviced >
              0);
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index 3265554..5688ab7 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -32,8 +32,7 @@
  */
 
 #include <memory>
-
-#include <unistd.h>
+#include <unordered_map>
 
 #include <gflags/gflags.h>
 #include <grpc++/channel.h>
@@ -52,7 +51,7 @@
 DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
 DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
 DEFINE_int32(server_port, 0, "Server port.");
-DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
+DEFINE_string(server_host, "localhost", "Server host to connect to");
 DEFINE_string(server_host_override, "foo.test.google.fr",
               "Override the server host which is sent in HTTP header");
 DEFINE_string(
@@ -108,119 +107,78 @@
   grpc::testing::InteropClient client(CreateChannelForTestCase(FLAGS_test_case),
                                       true,
                                       FLAGS_do_not_abort_on_transient_failures);
-  if (FLAGS_test_case == "empty_unary") {
-    client.DoEmpty();
-  } else if (FLAGS_test_case == "large_unary") {
-    client.DoLargeUnary();
-  } else if (FLAGS_test_case == "server_compressed_unary") {
-    client.DoServerCompressedUnary();
-  } else if (FLAGS_test_case == "client_compressed_unary") {
-    client.DoClientCompressedUnary();
-  } else if (FLAGS_test_case == "client_streaming") {
-    client.DoRequestStreaming();
-  } else if (FLAGS_test_case == "server_streaming") {
-    client.DoResponseStreaming();
-  } else if (FLAGS_test_case == "server_compressed_streaming") {
-    client.DoServerCompressedStreaming();
-  } else if (FLAGS_test_case == "client_compressed_streaming") {
-    client.DoClientCompressedStreaming();
-  } else if (FLAGS_test_case == "slow_consumer") {
-    client.DoResponseStreamingWithSlowConsumer();
-  } else if (FLAGS_test_case == "half_duplex") {
-    client.DoHalfDuplex();
-  } else if (FLAGS_test_case == "ping_pong") {
-    client.DoPingPong();
-  } else if (FLAGS_test_case == "cancel_after_begin") {
-    client.DoCancelAfterBegin();
-  } else if (FLAGS_test_case == "cancel_after_first_response") {
-    client.DoCancelAfterFirstResponse();
-  } else if (FLAGS_test_case == "timeout_on_sleeping_server") {
-    client.DoTimeoutOnSleepingServer();
-  } else if (FLAGS_test_case == "empty_stream") {
-    client.DoEmptyStream();
-  } else if (FLAGS_test_case == "compute_engine_creds") {
-    client.DoComputeEngineCreds(FLAGS_default_service_account,
-                                FLAGS_oauth_scope);
-  } else if (FLAGS_test_case == "jwt_token_creds") {
-    grpc::string json_key = GetServiceAccountJsonKey();
-    client.DoJwtTokenCreds(json_key);
-  } else if (FLAGS_test_case == "oauth2_auth_token") {
-    client.DoOauth2AuthToken(FLAGS_default_service_account, FLAGS_oauth_scope);
-  } else if (FLAGS_test_case == "per_rpc_creds") {
-    grpc::string json_key = GetServiceAccountJsonKey();
-    client.DoPerRpcCreds(json_key);
-  } else if (FLAGS_test_case == "status_code_and_message") {
-    client.DoStatusWithMessage();
-  } else if (FLAGS_test_case == "custom_metadata") {
-    client.DoCustomMetadata();
-  } else if (FLAGS_test_case == "unimplemented_method") {
-    client.DoUnimplementedMethod();
-  } else if (FLAGS_test_case == "unimplemented_service") {
-    client.DoUnimplementedService();
-  } else if (FLAGS_test_case == "cacheable_unary") {
-    client.DoCacheableUnary();
-  } else if (FLAGS_test_case == "all") {
-    client.DoEmpty();
-    client.DoLargeUnary();
-    client.DoClientCompressedUnary();
-    client.DoServerCompressedUnary();
-    client.DoRequestStreaming();
-    client.DoResponseStreaming();
-    client.DoClientCompressedStreaming();
-    client.DoServerCompressedStreaming();
-    client.DoHalfDuplex();
-    client.DoPingPong();
-    client.DoCancelAfterBegin();
-    client.DoCancelAfterFirstResponse();
-    client.DoTimeoutOnSleepingServer();
-    client.DoEmptyStream();
-    client.DoStatusWithMessage();
-    client.DoCustomMetadata();
-    client.DoUnimplementedMethod();
-    client.DoUnimplementedService();
-    client.DoCacheableUnary();
-    // service_account_creds and jwt_token_creds can only run with ssl.
-    if (FLAGS_use_tls) {
-      grpc::string json_key = GetServiceAccountJsonKey();
-      client.DoJwtTokenCreds(json_key);
-      client.DoOauth2AuthToken(FLAGS_default_service_account,
-                               FLAGS_oauth_scope);
-      client.DoPerRpcCreds(json_key);
-    }
-    // compute_engine_creds only runs in GCE.
-  } else {
-    const char* testcases[] = {"all",
-                               "cacheable_unary",
-                               "cancel_after_begin",
-                               "cancel_after_first_response",
-                               "client_compressed_streaming",
-                               "client_compressed_unary",
-                               "client_streaming",
-                               "compute_engine_creds",
-                               "custom_metadata",
-                               "empty_stream",
-                               "empty_unary",
-                               "half_duplex",
-                               "jwt_token_creds",
-                               "large_unary",
-                               "oauth2_auth_token",
-                               "oauth2_auth_token",
-                               "per_rpc_creds",
-                               "per_rpc_creds",
-                               "ping_pong",
-                               "server_compressed_streaming",
-                               "server_compressed_unary",
-                               "server_streaming",
-                               "status_code_and_message",
-                               "timeout_on_sleeping_server",
-                               "unimplemented_method",
-                               "unimplemented_service"};
-    char* joined_testcases =
-        gpr_strjoin_sep(testcases, GPR_ARRAY_SIZE(testcases), "\n", NULL);
 
+  std::unordered_map<grpc::string, std::function<bool()>> actions;
+  actions["empty_unary"] =
+      std::bind(&grpc::testing::InteropClient::DoEmpty, &client);
+  actions["large_unary"] =
+      std::bind(&grpc::testing::InteropClient::DoLargeUnary, &client);
+  actions["server_compressed_unary"] = std::bind(
+      &grpc::testing::InteropClient::DoServerCompressedUnary, &client);
+  actions["client_compressed_unary"] = std::bind(
+      &grpc::testing::InteropClient::DoClientCompressedUnary, &client);
+  actions["client_streaming"] =
+      std::bind(&grpc::testing::InteropClient::DoRequestStreaming, &client);
+  actions["server_streaming"] =
+      std::bind(&grpc::testing::InteropClient::DoResponseStreaming, &client);
+  actions["server_compressed_streaming"] = std::bind(
+      &grpc::testing::InteropClient::DoServerCompressedStreaming, &client);
+  actions["client_compressed_streaming"] = std::bind(
+      &grpc::testing::InteropClient::DoClientCompressedStreaming, &client);
+  actions["slow_consumer"] = std::bind(
+      &grpc::testing::InteropClient::DoResponseStreamingWithSlowConsumer,
+      &client);
+  actions["half_duplex"] =
+      std::bind(&grpc::testing::InteropClient::DoHalfDuplex, &client);
+  actions["ping_pong"] =
+      std::bind(&grpc::testing::InteropClient::DoPingPong, &client);
+  actions["cancel_after_begin"] =
+      std::bind(&grpc::testing::InteropClient::DoCancelAfterBegin, &client);
+  actions["cancel_after_first_response"] = std::bind(
+      &grpc::testing::InteropClient::DoCancelAfterFirstResponse, &client);
+  actions["timeout_on_sleeping_server"] = std::bind(
+      &grpc::testing::InteropClient::DoTimeoutOnSleepingServer, &client);
+  actions["empty_stream"] =
+      std::bind(&grpc::testing::InteropClient::DoEmptyStream, &client);
+  if (FLAGS_use_tls) {
+    actions["compute_engine_creds"] =
+        std::bind(&grpc::testing::InteropClient::DoComputeEngineCreds, &client,
+                  FLAGS_default_service_account, FLAGS_oauth_scope);
+    actions["jwt_token_creds"] =
+        std::bind(&grpc::testing::InteropClient::DoJwtTokenCreds, &client,
+                  GetServiceAccountJsonKey());
+    actions["oauth2_auth_token"] =
+        std::bind(&grpc::testing::InteropClient::DoOauth2AuthToken, &client,
+                  FLAGS_default_service_account, FLAGS_oauth_scope);
+    actions["per_rpc_creds"] =
+        std::bind(&grpc::testing::InteropClient::DoPerRpcCreds, &client,
+                  GetServiceAccountJsonKey());
+  }
+  actions["status_code_and_message"] =
+      std::bind(&grpc::testing::InteropClient::DoStatusWithMessage, &client);
+  actions["custom_metadata"] =
+      std::bind(&grpc::testing::InteropClient::DoCustomMetadata, &client);
+  actions["unimplemented_method"] =
+      std::bind(&grpc::testing::InteropClient::DoUnimplementedMethod, &client);
+  actions["unimplemented_service"] =
+      std::bind(&grpc::testing::InteropClient::DoUnimplementedService, &client);
+  // actions["cacheable_unary"] =
+  //    std::bind(&grpc::testing::InteropClient::DoCacheableUnary, &client);
+
+  if (FLAGS_test_case == "all") {
+    for (const auto& action : actions) {
+      action.second();
+    }
+  } else if (actions.find(FLAGS_test_case) != actions.end()) {
+    actions.find(FLAGS_test_case)->second();
+  } else {
+    grpc::string test_cases;
+    for (const auto& action : actions) {
+      if (!test_cases.empty()) test_cases += "\n";
+      test_cases += action.first;
+    }
     gpr_log(GPR_ERROR, "Unsupported test case %s. Valid options are\n%s",
-            FLAGS_test_case.c_str(), joined_testcases);
-    gpr_free(joined_testcases);
+            FLAGS_test_case.c_str(), test_cases.c_str());
     ret = 1;
   }
 
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index 91564e5..d3192ad 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -33,8 +33,6 @@
 
 #include "test/cpp/interop/client_helper.h"
 
-#include <unistd.h>
-
 #include <fstream>
 #include <memory>
 #include <sstream>
diff --git a/test/cpp/interop/http2_client.cc b/test/cpp/interop/http2_client.cc
index 38aee43..b96e9fa 100644
--- a/test/cpp/interop/http2_client.cc
+++ b/test/cpp/interop/http2_client.cc
@@ -223,7 +223,7 @@
 }  // namespace grpc
 
 DEFINE_int32(server_port, 0, "Server port.");
-DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
+DEFINE_string(server_host, "localhost", "Server host to connect to");
 DEFINE_string(test_case, "rst_after_header",
               "Configure different test cases. Valid options are:\n\n"
               "goaway\n"
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index d124262..b7f2723 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -31,7 +31,6 @@
  *
  */
 
-#include <unistd.h>
 #include <cinttypes>
 #include <fstream>
 #include <memory>
@@ -43,6 +42,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
 #include <grpc/support/useful.h>
 
 #include "src/core/lib/transport/byte_stream.h"
@@ -109,7 +109,10 @@
 
 UnimplementedService::Stub*
 InteropClient::ServiceStub::GetUnimplementedServiceStub() {
-  return UnimplementedService::NewStub(channel_).get();
+  if (unimplemented_service_stub_ == nullptr) {
+    unimplemented_service_stub_ = UnimplementedService::NewStub(channel_);
+  }
+  return unimplemented_service_stub_.get();
 }
 
 void InteropClient::ServiceStub::Reset(std::shared_ptr<Channel> channel) {
@@ -615,7 +618,9 @@
     GPR_ASSERT(response.payload().body() ==
                grpc::string(kResponseMessageSize, '\0'));
     gpr_log(GPR_DEBUG, "received message %d", i);
-    usleep(kReceiveDelayMilliSeconds * 1000);
+    gpr_sleep_until(gpr_time_add(
+        gpr_now(GPR_CLOCK_REALTIME),
+        gpr_time_from_millis(kReceiveDelayMilliSeconds, GPR_TIMESPAN)));
     ++i;
   }
 
@@ -943,7 +948,7 @@
     const auto& server_initial_metadata = context.GetServerInitialMetadata();
     auto iter = server_initial_metadata.find(kEchoInitialMetadataKey);
     GPR_ASSERT(iter != server_initial_metadata.end());
-    GPR_ASSERT(iter->second.data() == kInitialMetadataValue);
+    GPR_ASSERT(iter->second == kInitialMetadataValue);
     const auto& server_trailing_metadata = context.GetServerTrailingMetadata();
     iter = server_trailing_metadata.find(kEchoTrailingBinMetadataKey);
     GPR_ASSERT(iter != server_trailing_metadata.end());
@@ -994,7 +999,7 @@
     const auto& server_initial_metadata = context.GetServerInitialMetadata();
     auto iter = server_initial_metadata.find(kEchoInitialMetadataKey);
     GPR_ASSERT(iter != server_initial_metadata.end());
-    GPR_ASSERT(iter->second.data() == kInitialMetadataValue);
+    GPR_ASSERT(iter->second == kInitialMetadataValue);
     const auto& server_trailing_metadata = context.GetServerTrailingMetadata();
     iter = server_trailing_metadata.find(kEchoTrailingBinMetadataKey);
     GPR_ASSERT(iter != server_trailing_metadata.end());
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index 7ec7ebe..74f4db6 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -107,6 +107,7 @@
 
    private:
     std::unique_ptr<TestService::Stub> stub_;
+    std::unique_ptr<UnimplementedService::Stub> unimplemented_service_stub_;
     std::shared_ptr<Channel> channel_;
     bool new_stub_every_call_;  // If true, a new stub is returned by every
                                 // Get() call
diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc
index 956840b..5a810b4 100644
--- a/test/cpp/interop/interop_server.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -31,8 +31,6 @@
  *
  */
 
-#include <unistd.h>
-
 #include <fstream>
 #include <memory>
 #include <sstream>
@@ -45,6 +43,7 @@
 #include <grpc++/server_context.h>
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/time.h>
 #include <grpc/support/useful.h>
 
 #include "src/core/lib/support/string.h"
@@ -91,7 +90,9 @@
 
   auto iter = client_metadata.find(kEchoInitialMetadataKey);
   if (iter != client_metadata.end()) {
-    context->AddInitialMetadata(kEchoInitialMetadataKey, iter->second.data());
+    context->AddInitialMetadata(
+        kEchoInitialMetadataKey,
+        grpc::string(iter->second.begin(), iter->second.end()));
   }
   iter = client_metadata.find(kEchoTrailingBinMetadataKey);
   if (iter != client_metadata.end()) {
@@ -105,7 +106,9 @@
   if (iter != client_metadata.end()) {
     iter = client_metadata.find("user-agent");
     if (iter != client_metadata.end()) {
-      context->AddInitialMetadata(kEchoUserAgentKey, iter->second.data());
+      context->AddInitialMetadata(
+          kEchoUserAgentKey,
+          grpc::string(iter->second.begin(), iter->second.end()));
     }
   }
 }
@@ -346,6 +349,7 @@
   std::unique_ptr<Server> server(builder.BuildAndStart());
   gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str());
   while (!gpr_atm_no_barrier_load(&g_got_sigint)) {
-    sleep(5);
+    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                                 gpr_time_from_seconds(5, GPR_TIMESPAN)));
   }
 }
diff --git a/test/cpp/interop/interop_server_bootstrap.cc b/test/cpp/interop/interop_server_bootstrap.cc
index 99518c6..7cbf221 100644
--- a/test/cpp/interop/interop_server_bootstrap.cc
+++ b/test/cpp/interop/interop_server_bootstrap.cc
@@ -32,7 +32,6 @@
  */
 
 #include <signal.h>
-#include <unistd.h>
 
 #include "test/cpp/interop/server_helper.h"
 #include "test/cpp/util/test_config.h"
diff --git a/test/cpp/interop/reconnect_interop_client.cc b/test/cpp/interop/reconnect_interop_client.cc
index 797e52c..1c2f606 100644
--- a/test/cpp/interop/reconnect_interop_client.cc
+++ b/test/cpp/interop/reconnect_interop_client.cc
@@ -48,7 +48,7 @@
 
 DEFINE_int32(server_control_port, 0, "Server port for control rpcs.");
 DEFINE_int32(server_retry_port, 0, "Server port for testing reconnection.");
-DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
+DEFINE_string(server_host, "localhost", "Server host to connect to");
 DEFINE_int32(max_reconnect_backoff_ms, 0,
              "Maximum backoff time, or 0 for default.");
 
diff --git a/test/cpp/interop/reconnect_interop_server.cc b/test/cpp/interop/reconnect_interop_server.cc
index 53d51e8..634d0a9 100644
--- a/test/cpp/interop/reconnect_interop_server.cc
+++ b/test/cpp/interop/reconnect_interop_server.cc
@@ -34,7 +34,6 @@
 // Test description at doc/connection-backoff-interop-test-description.md
 
 #include <signal.h>
-#include <unistd.h>
 
 #include <condition_variable>
 #include <memory>
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
new file mode 100644
index 0000000..76d5030
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -0,0 +1,382 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* This benchmark exists to ensure that the benchmark integration is
+ * working */
+
+#include <string.h>
+#include <sstream>
+
+#include <grpc++/support/channel_arguments.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+extern "C" {
+#include "src/core/ext/client_channel/client_channel.h"
+#include "src/core/ext/load_reporting/load_reporting_filter.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/compress_filter.h"
+#include "src/core/lib/channel/connected_channel.h"
+#include "src/core/lib/channel/deadline_filter.h"
+#include "src/core/lib/channel/http_client_filter.h"
+#include "src/core/lib/channel/http_server_filter.h"
+#include "src/core/lib/channel/message_size_filter.h"
+#include "src/core/lib/transport/transport_impl.h"
+}
+
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+static struct Init {
+  Init() { grpc_init(); }
+  ~Init() { grpc_shutdown(); }
+} g_init;
+
+static void BM_InsecureChannelWithDefaults(benchmark::State &state) {
+  grpc_channel *channel =
+      grpc_insecure_channel_create("localhost:12345", NULL, NULL);
+  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+  grpc_slice method = grpc_slice_from_static_string("/foo/bar");
+  gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  while (state.KeepRunning()) {
+    grpc_call_destroy(grpc_channel_create_call(channel, NULL,
+                                               GRPC_PROPAGATE_DEFAULTS, cq,
+                                               method, NULL, deadline, NULL));
+  }
+  grpc_channel_destroy(channel);
+  grpc_completion_queue_destroy(cq);
+}
+BENCHMARK(BM_InsecureChannelWithDefaults);
+
+static void FilterDestroy(grpc_exec_ctx *exec_ctx, void *arg,
+                          grpc_error *error) {
+  gpr_free(arg);
+}
+
+static void DoNothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
+
+class FakeClientChannelFactory : public grpc_client_channel_factory {
+ public:
+  FakeClientChannelFactory() { vtable = &vtable_; }
+
+ private:
+  static void NoRef(grpc_client_channel_factory *factory) {}
+  static void NoUnref(grpc_exec_ctx *exec_ctx,
+                      grpc_client_channel_factory *factory) {}
+  static grpc_subchannel *CreateSubchannel(grpc_exec_ctx *exec_ctx,
+                                           grpc_client_channel_factory *factory,
+                                           const grpc_subchannel_args *args) {
+    return nullptr;
+  }
+  static grpc_channel *CreateClientChannel(grpc_exec_ctx *exec_ctx,
+                                           grpc_client_channel_factory *factory,
+                                           const char *target,
+                                           grpc_client_channel_type type,
+                                           const grpc_channel_args *args) {
+    return nullptr;
+  }
+
+  static const grpc_client_channel_factory_vtable vtable_;
+};
+
+const grpc_client_channel_factory_vtable FakeClientChannelFactory::vtable_ = {
+    NoRef, NoUnref, CreateSubchannel, CreateClientChannel};
+
+static grpc_arg StringArg(const char *key, const char *value) {
+  grpc_arg a;
+  a.type = GRPC_ARG_STRING;
+  a.key = const_cast<char *>(key);
+  a.value.string = const_cast<char *>(value);
+  return a;
+}
+
+enum FixtureFlags : uint32_t {
+  CHECKS_NOT_LAST = 1,
+  REQUIRES_TRANSPORT = 2,
+};
+
+template <const grpc_channel_filter *kFilter, uint32_t kFlags>
+struct Fixture {
+  const grpc_channel_filter *filter = kFilter;
+  const uint32_t flags = kFlags;
+};
+
+namespace dummy_filter {
+
+static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
+                                   grpc_call_element *elem,
+                                   grpc_transport_stream_op *op) {}
+
+static void StartTransportOp(grpc_exec_ctx *exec_ctx,
+                             grpc_channel_element *elem,
+                             grpc_transport_op *op) {}
+
+static grpc_error *InitCallElem(grpc_exec_ctx *exec_ctx,
+                                grpc_call_element *elem,
+                                const grpc_call_element_args *args) {
+  return GRPC_ERROR_NONE;
+}
+
+static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
+                                   grpc_call_element *elem,
+                                   grpc_polling_entity *pollent) {}
+
+static void DestroyCallElem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+                            const grpc_call_final_info *final_info,
+                            void *and_free_memory) {}
+
+grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
+                            grpc_channel_element_args *args) {
+  return GRPC_ERROR_NONE;
+}
+
+void DestroyChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
+
+char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+  return gpr_strdup("peer");
+}
+
+void GetChannelInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
+                    const grpc_channel_info *channel_info) {}
+
+static const grpc_channel_filter dummy_filter = {StartTransportStreamOp,
+                                                 StartTransportOp,
+                                                 0,
+                                                 InitCallElem,
+                                                 SetPollsetOrPollsetSet,
+                                                 DestroyCallElem,
+                                                 0,
+                                                 InitChannelElem,
+                                                 DestroyChannelElem,
+                                                 GetPeer,
+                                                 GetChannelInfo,
+                                                 "dummy_filter"};
+
+}  // namespace dummy_filter
+
+namespace dummy_transport {
+
+/* Memory required for a single stream element - this is allocated by upper
+   layers and initialized by the transport */
+size_t sizeof_stream; /* = sizeof(transport stream) */
+
+/* name of this transport implementation */
+const char *name;
+
+/* implementation of grpc_transport_init_stream */
+int InitStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+               grpc_stream *stream, grpc_stream_refcount *refcount,
+               const void *server_data) {
+  return 0;
+}
+
+/* implementation of grpc_transport_set_pollset */
+void SetPollset(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                grpc_stream *stream, grpc_pollset *pollset) {}
+
+/* implementation of grpc_transport_set_pollset */
+void SetPollsetSet(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                   grpc_stream *stream, grpc_pollset_set *pollset_set) {}
+
+/* implementation of grpc_transport_perform_stream_op */
+void PerformStreamOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                     grpc_stream *stream, grpc_transport_stream_op *op) {
+  grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_NONE);
+}
+
+/* implementation of grpc_transport_perform_op */
+void PerformOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+               grpc_transport_op *op) {}
+
+/* implementation of grpc_transport_destroy_stream */
+void DestroyStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
+                   grpc_stream *stream, void *and_free_memory) {}
+
+/* implementation of grpc_transport_destroy */
+void Destroy(grpc_exec_ctx *exec_ctx, grpc_transport *self) {}
+
+/* implementation of grpc_transport_get_peer */
+char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_transport *self) {
+  return gpr_strdup("transport_peer");
+}
+
+/* implementation of grpc_transport_get_endpoint */
+grpc_endpoint *GetEndpoint(grpc_exec_ctx *exec_ctx, grpc_transport *self) {
+  return nullptr;
+}
+
+static const grpc_transport_vtable dummy_transport_vtable = {
+    0,          "dummy_http2", InitStream,
+    SetPollset, SetPollsetSet, PerformStreamOp,
+    PerformOp,  DestroyStream, Destroy,
+    GetPeer,    GetEndpoint};
+
+static grpc_transport dummy_transport = {&dummy_transport_vtable};
+
+}  // namespace dummy_transport
+
+class NoOp {
+ public:
+  class Op {
+   public:
+    Op(grpc_exec_ctx *exec_ctx, NoOp *p, grpc_call_stack *s) {}
+    void Finish(grpc_exec_ctx *exec_ctx) {}
+  };
+};
+
+class SendEmptyMetadata {
+ public:
+  SendEmptyMetadata() {
+    memset(&op_, 0, sizeof(op_));
+    op_.on_complete = grpc_closure_init(&closure_, DoNothing, nullptr,
+                                        grpc_schedule_on_exec_ctx);
+  }
+
+  class Op {
+   public:
+    Op(grpc_exec_ctx *exec_ctx, SendEmptyMetadata *p, grpc_call_stack *s) {
+      grpc_metadata_batch_init(&batch_);
+      p->op_.send_initial_metadata = &batch_;
+    }
+    void Finish(grpc_exec_ctx *exec_ctx) {
+      grpc_metadata_batch_destroy(exec_ctx, &batch_);
+    }
+
+   private:
+    grpc_metadata_batch batch_;
+  };
+
+ private:
+  const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  const gpr_timespec start_time_ = gpr_now(GPR_CLOCK_MONOTONIC);
+  const grpc_slice method_ = grpc_slice_from_static_string("/foo/bar");
+  grpc_transport_stream_op op_;
+  grpc_closure closure_;
+};
+
+// Test a filter in isolation. Fixture specifies the filter under test (use the
+// Fixture<> template to specify this), and TestOp defines some unit of work to
+// perform on said filter.
+template <class Fixture, class TestOp>
+static void BM_IsolatedFilter(benchmark::State &state) {
+  Fixture fixture;
+  std::ostringstream label;
+
+  std::vector<grpc_arg> args;
+  FakeClientChannelFactory fake_client_channel_factory;
+  args.push_back(grpc_client_channel_factory_create_channel_arg(
+      &fake_client_channel_factory));
+  args.push_back(StringArg(GRPC_ARG_SERVER_URI, "localhost"));
+
+  grpc_channel_args channel_args = {args.size(), &args[0]};
+
+  std::vector<const grpc_channel_filter *> filters;
+  if (fixture.filter != nullptr) {
+    filters.push_back(fixture.filter);
+  }
+  if (fixture.flags & CHECKS_NOT_LAST) {
+    filters.push_back(&dummy_filter::dummy_filter);
+    label << " #has_dummy_filter";
+  }
+
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  size_t channel_size = grpc_channel_stack_size(&filters[0], filters.size());
+  grpc_channel_stack *channel_stack =
+      static_cast<grpc_channel_stack *>(gpr_zalloc(channel_size));
+  GPR_ASSERT(GRPC_LOG_IF_ERROR(
+      "call_stack_init",
+      grpc_channel_stack_init(&exec_ctx, 1, FilterDestroy, channel_stack,
+                              &filters[0], filters.size(), &channel_args,
+                              fixture.flags & REQUIRES_TRANSPORT
+                                  ? &dummy_transport::dummy_transport
+                                  : nullptr,
+                              "CHANNEL", channel_stack)));
+  grpc_exec_ctx_flush(&exec_ctx);
+  grpc_call_stack *call_stack = static_cast<grpc_call_stack *>(
+      gpr_zalloc(channel_stack->call_stack_size));
+  gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC);
+  grpc_slice method = grpc_slice_from_static_string("/foo/bar");
+  grpc_call_final_info final_info;
+  TestOp test_op_data;
+  while (state.KeepRunning()) {
+    GRPC_ERROR_UNREF(grpc_call_stack_init(&exec_ctx, channel_stack, 1,
+                                          DoNothing, NULL, NULL, NULL, method,
+                                          start_time, deadline, call_stack));
+    typename TestOp::Op op(&exec_ctx, &test_op_data, call_stack);
+    grpc_call_stack_destroy(&exec_ctx, call_stack, &final_info, NULL);
+    op.Finish(&exec_ctx);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_channel_stack_destroy(&exec_ctx, channel_stack);
+  grpc_exec_ctx_finish(&exec_ctx);
+  gpr_free(channel_stack);
+  gpr_free(call_stack);
+
+  state.SetLabel(label.str());
+}
+
+typedef Fixture<nullptr, 0> NoFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, NoFilter, NoOp);
+typedef Fixture<&dummy_filter::dummy_filter, 0> DummyFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, DummyFilter, NoOp);
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, DummyFilter, SendEmptyMetadata);
+typedef Fixture<&grpc_client_channel_filter, 0> ClientChannelFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientChannelFilter, NoOp);
+typedef Fixture<&grpc_compress_filter, CHECKS_NOT_LAST> CompressFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, CompressFilter, NoOp);
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, CompressFilter, SendEmptyMetadata);
+typedef Fixture<&grpc_client_deadline_filter, CHECKS_NOT_LAST>
+    ClientDeadlineFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientDeadlineFilter, NoOp);
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientDeadlineFilter, SendEmptyMetadata);
+typedef Fixture<&grpc_server_deadline_filter, CHECKS_NOT_LAST>
+    ServerDeadlineFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, ServerDeadlineFilter, NoOp);
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, ServerDeadlineFilter, SendEmptyMetadata);
+typedef Fixture<&grpc_http_client_filter, CHECKS_NOT_LAST | REQUIRES_TRANSPORT>
+    HttpClientFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpClientFilter, NoOp);
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpClientFilter, SendEmptyMetadata);
+typedef Fixture<&grpc_http_server_filter, CHECKS_NOT_LAST> HttpServerFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpServerFilter, NoOp);
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpServerFilter, SendEmptyMetadata);
+typedef Fixture<&grpc_message_size_filter, CHECKS_NOT_LAST> MessageSizeFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, NoOp);
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, SendEmptyMetadata);
+typedef Fixture<&grpc_load_reporting_filter, CHECKS_NOT_LAST>
+    LoadReportingFilter;
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, NoOp);
+BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, SendEmptyMetadata);
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
new file mode 100644
index 0000000..5fb3f37
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
@@ -0,0 +1,443 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Microbenchmarks around CHTTP2 HPACK operations */
+
+#include <grpc/support/log.h>
+#include <string.h>
+#include <sstream>
+extern "C" {
+#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
+#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/static_metadata.h"
+}
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+static struct Init {
+  Init() { grpc_init(); }
+  ~Init() { grpc_shutdown(); }
+} g_init;
+
+////////////////////////////////////////////////////////////////////////////////
+// HPACK encoder
+//
+
+static void BM_HpackEncoderInitDestroy(benchmark::State &state) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_chttp2_hpack_compressor c;
+  while (state.KeepRunning()) {
+    grpc_chttp2_hpack_compressor_init(&c);
+    grpc_chttp2_hpack_compressor_destroy(&exec_ctx, &c);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_HpackEncoderInitDestroy);
+
+template <class Fixture>
+static void BM_HpackEncoderEncodeHeader(benchmark::State &state) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  grpc_metadata_batch b;
+  grpc_metadata_batch_init(&b);
+  std::vector<grpc_mdelem> elems = Fixture::GetElems(&exec_ctx);
+  std::vector<grpc_linked_mdelem> storage(elems.size());
+  for (size_t i = 0; i < elems.size(); i++) {
+    GPR_ASSERT(GRPC_LOG_IF_ERROR(
+        "addmd",
+        grpc_metadata_batch_add_tail(&exec_ctx, &b, &storage[i], elems[i])));
+  }
+
+  grpc_chttp2_hpack_compressor c;
+  grpc_chttp2_hpack_compressor_init(&c);
+  grpc_transport_one_way_stats stats;
+  memset(&stats, 0, sizeof(stats));
+  grpc_slice_buffer outbuf;
+  grpc_slice_buffer_init(&outbuf);
+  while (state.KeepRunning()) {
+    grpc_chttp2_encode_header(&exec_ctx, &c, (uint32_t)state.iterations(), &b,
+                              state.range(0), state.range(1), &stats, &outbuf);
+    grpc_slice_buffer_reset_and_unref_internal(&exec_ctx, &outbuf);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_metadata_batch_destroy(&exec_ctx, &b);
+  grpc_chttp2_hpack_compressor_destroy(&exec_ctx, &c);
+  grpc_slice_buffer_destroy_internal(&exec_ctx, &outbuf);
+  grpc_exec_ctx_finish(&exec_ctx);
+
+  std::ostringstream label;
+  label << "framing_bytes/iter:" << (static_cast<double>(stats.framing_bytes) /
+                                     static_cast<double>(state.iterations()))
+        << " header_bytes/iter:" << (static_cast<double>(stats.header_bytes) /
+                                     static_cast<double>(state.iterations()));
+  state.SetLabel(label.str());
+}
+
+namespace hpack_encoder_fixtures {
+
+class EmptyBatch {
+ public:
+  static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+    return {};
+  }
+};
+
+class SingleStaticElem {
+ public:
+  static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+    return {GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE};
+  }
+};
+
+class SingleInternedElem {
+ public:
+  static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+    return {grpc_mdelem_from_slices(
+        exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc")),
+        grpc_slice_intern(grpc_slice_from_static_string("def")))};
+  }
+};
+
+class SingleInternedKeyElem {
+ public:
+  static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+    return {grpc_mdelem_from_slices(
+        exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc")),
+        grpc_slice_from_static_string("def"))};
+  }
+};
+
+class SingleNonInternedElem {
+ public:
+  static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+    return {grpc_mdelem_from_slices(exec_ctx,
+                                    grpc_slice_from_static_string("abc"),
+                                    grpc_slice_from_static_string("def"))};
+  }
+};
+
+class RepresentativeClientInitialMetadata {
+ public:
+  static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+    return {
+        GRPC_MDELEM_SCHEME_HTTP, GRPC_MDELEM_METHOD_POST,
+        grpc_mdelem_from_slices(
+            exec_ctx, GRPC_MDSTR_PATH,
+            grpc_slice_intern(grpc_slice_from_static_string("/foo/bar"))),
+        grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY,
+                                grpc_slice_intern(grpc_slice_from_static_string(
+                                    "foo.test.google.fr:1234"))),
+        GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP,
+        GRPC_MDELEM_TE_TRAILERS,
+        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
+        grpc_mdelem_from_slices(
+            exec_ctx, GRPC_MDSTR_USER_AGENT,
+            grpc_slice_intern(grpc_slice_from_static_string(
+                "grpc-c/3.0.0-dev (linux; chttp2; green)")))};
+  }
+};
+
+class RepresentativeServerInitialMetadata {
+ public:
+  static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+    return {GRPC_MDELEM_STATUS_200,
+            GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
+            GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP};
+  }
+};
+
+class RepresentativeServerTrailingMetadata {
+ public:
+  static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
+    return {GRPC_MDELEM_GRPC_STATUS_0};
+  }
+};
+
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, EmptyBatch)->Args({0, 16384});
+// test with eof (shouldn't affect anything)
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, EmptyBatch)->Args({1, 16384});
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleStaticElem)
+    ->Args({0, 16384});
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedKeyElem)
+    ->Args({0, 16384});
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedElem)
+    ->Args({0, 16384});
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedElem)
+    ->Args({0, 16384});
+// test with a tiny frame size, to highlight continuation costs
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedElem)
+    ->Args({0, 1});
+
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
+                   RepresentativeClientInitialMetadata)
+    ->Args({0, 16384});
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
+                   RepresentativeServerInitialMetadata)
+    ->Args({0, 16384});
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
+                   RepresentativeServerTrailingMetadata)
+    ->Args({1, 16384});
+
+}  // namespace hpack_encoder_fixtures
+
+////////////////////////////////////////////////////////////////////////////////
+// HPACK parser
+//
+
+static void BM_HpackParserInitDestroy(benchmark::State &state) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_chttp2_hpack_parser p;
+  while (state.KeepRunning()) {
+    grpc_chttp2_hpack_parser_init(&exec_ctx, &p);
+    grpc_chttp2_hpack_parser_destroy(&exec_ctx, &p);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_HpackParserInitDestroy);
+
+static void UnrefHeader(grpc_exec_ctx *exec_ctx, void *user_data,
+                        grpc_mdelem md) {
+  GRPC_MDELEM_UNREF(exec_ctx, md);
+}
+
+template <class Fixture>
+static void BM_HpackParserParseHeader(benchmark::State &state) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  std::vector<grpc_slice> init_slices = Fixture::GetInitSlices();
+  std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices();
+  grpc_chttp2_hpack_parser p;
+  grpc_chttp2_hpack_parser_init(&exec_ctx, &p);
+  p.on_header = UnrefHeader;
+  p.on_header_user_data = nullptr;
+  for (auto slice : init_slices) {
+    grpc_chttp2_hpack_parser_parse(&exec_ctx, &p, slice);
+  }
+  while (state.KeepRunning()) {
+    for (auto slice : benchmark_slices) {
+      grpc_chttp2_hpack_parser_parse(&exec_ctx, &p, slice);
+    }
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_chttp2_hpack_parser_destroy(&exec_ctx, &p);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+namespace hpack_parser_fixtures {
+
+static grpc_slice MakeSlice(std::initializer_list<uint8_t> bytes) {
+  grpc_slice s = grpc_slice_malloc(bytes.size());
+  uint8_t *p = GRPC_SLICE_START_PTR(s);
+  for (auto b : bytes) {
+    *p++ = b;
+  }
+  return s;
+}
+
+class EmptyBatch {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() { return {}; }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice({})};
+  }
+};
+
+class IndexedSingleStaticElem {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {MakeSlice(
+        {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice({0xbe})};
+  }
+};
+
+class AddIndexedSingleStaticElem {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() { return {}; }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice(
+        {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})};
+  }
+};
+
+class KeyIndexedSingleStaticElem {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {MakeSlice(
+        {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice({0x7e, 0x03, 'd', 'e', 'f'})};
+  }
+};
+
+class IndexedSingleInternedElem {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice({0xbe})};
+  }
+};
+
+class AddIndexedSingleInternedElem {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() { return {}; }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})};
+  }
+};
+
+class KeyIndexedSingleInternedElem {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice({0x7e, 0x03, 'g', 'h', 'i'})};
+  }
+};
+
+class NonIndexedElem {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() { return {}; }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice({0x00, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})};
+  }
+};
+
+class RepresentativeClientInitialMetadata {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {grpc_slice_from_static_string(
+        // generated with:
+        // ```
+        // tools/codegen/core/gen_header_frame.py --compression inc --no_framing
+        // < test/core/bad_client/tests/simple_request.headers
+        // ```
+        "@\x05:path\x08/foo/bar"
+        "@\x07:scheme\x04http"
+        "@\x07:method\x04POST"
+        "@\x0a:authority\x09localhost"
+        "@\x0c"
+        "content-type\x10"
+        "application/grpc"
+        "@\x14grpc-accept-encoding\x15identity,deflate,gzip"
+        "@\x02te\x08trailers"
+        "@\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)")};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    // generated with:
+    // ```
+    // tools/codegen/core/gen_header_frame.py --compression pre --no_framing
+    // --hex < test/core/bad_client/tests/simple_request.headers
+    // ```
+    return {MakeSlice({0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe})};
+  }
+};
+
+class RepresentativeServerInitialMetadata {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {grpc_slice_from_static_string(
+        // generated with:
+        // ```
+        // tools/codegen/core/gen_header_frame.py --compression inc --no_framing
+        // <
+        // test/cpp/microbenchmarks/representative_server_initial_metadata.headers
+        // ```
+        "@\x07:status\x03"
+        "200"
+        "@\x0c"
+        "content-type\x10"
+        "application/grpc"
+        "@\x14grpc-accept-encoding\x15identity,deflate,gzip")};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    // generated with:
+    // ```
+    // tools/codegen/core/gen_header_frame.py --compression pre --no_framing
+    // --hex <
+    // test/cpp/microbenchmarks/representative_server_initial_metadata.headers
+    // ```
+    return {MakeSlice({0xc0, 0xbf, 0xbe})};
+  }
+};
+
+class RepresentativeServerTrailingMetadata {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {grpc_slice_from_static_string(
+        // generated with:
+        // ```
+        // tools/codegen/core/gen_header_frame.py --compression inc --no_framing
+        // <
+        // test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
+        // ```
+        "@\x0bgrpc-status\x01"
+        "0"
+        "@\x0cgrpc-message\x00")};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    // generated with:
+    // ```
+    // tools/codegen/core/gen_header_frame.py --compression pre --no_framing
+    // --hex <
+    // test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
+    // ```
+    return {MakeSlice({0xbf, 0xbe})};
+  }
+};
+
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, EmptyBatch);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleStaticElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleStaticElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleStaticElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleInternedElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleInternedElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleInternedElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedElem);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
+                   RepresentativeClientInitialMetadata);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
+                   RepresentativeServerInitialMetadata);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
+                   RepresentativeServerTrailingMetadata);
+
+}  // namespace hpack_parser_fixtures
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_closure.cc b/test/cpp/microbenchmarks/bm_closure.cc
new file mode 100644
index 0000000..1f54e8c
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_closure.cc
@@ -0,0 +1,464 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Test various closure related operations */
+
+#include <grpc/grpc.h>
+
+extern "C" {
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/support/spinlock.h"
+}
+
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+#include <sstream>
+
+#ifdef GPR_LOW_LEVEL_COUNTERS
+extern "C" gpr_atm gpr_mu_locks;
+#endif
+
+static class InitializeStuff {
+ public:
+  InitializeStuff() { grpc_init(); }
+  ~InitializeStuff() { grpc_shutdown(); }
+} initialize_stuff;
+
+class TrackCounters {
+ public:
+  TrackCounters(benchmark::State& state) : state_(state) {}
+
+  ~TrackCounters() {
+    std::ostringstream out;
+#ifdef GPR_LOW_LEVEL_COUNTERS
+    out << " locks/iter:" << ((double)(gpr_atm_no_barrier_load(&gpr_mu_locks) -
+                                       mu_locks_at_start_) /
+                              (double)state_.iterations())
+        << " atm_cas/iter:"
+        << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_cas) -
+                     atm_cas_at_start_) /
+            (double)state_.iterations())
+        << " atm_add/iter:"
+        << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_add) -
+                     atm_add_at_start_) /
+            (double)state_.iterations());
+#endif
+    state_.SetLabel(out.str());
+  }
+
+ private:
+  benchmark::State& state_;
+#ifdef GPR_LOW_LEVEL_COUNTERS
+  const size_t mu_locks_at_start_ = gpr_atm_no_barrier_load(&gpr_mu_locks);
+  const size_t atm_cas_at_start_ =
+      gpr_atm_no_barrier_load(&gpr_counter_atm_cas);
+  const size_t atm_add_at_start_ =
+      gpr_atm_no_barrier_load(&gpr_counter_atm_add);
+#endif
+};
+
+static void BM_NoOpExecCtx(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  while (state.KeepRunning()) {
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_exec_ctx_finish(&exec_ctx);
+  }
+}
+BENCHMARK(BM_NoOpExecCtx);
+
+static void BM_WellFlushed(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_WellFlushed);
+
+static void DoNothing(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {}
+
+static void BM_ClosureInitAgainstExecCtx(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_closure c;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(
+        grpc_closure_init(&c, DoNothing, NULL, grpc_schedule_on_exec_ctx));
+  }
+}
+BENCHMARK(BM_ClosureInitAgainstExecCtx);
+
+static void BM_ClosureInitAgainstCombiner(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_combiner* combiner = grpc_combiner_create(NULL);
+  grpc_closure c;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(grpc_closure_init(
+        &c, DoNothing, NULL, grpc_combiner_scheduler(combiner, false)));
+  }
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureInitAgainstCombiner);
+
+static void BM_ClosureRunOnExecCtx(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_closure c;
+  grpc_closure_init(&c, DoNothing, NULL, grpc_schedule_on_exec_ctx);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_run(&exec_ctx, &c, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureRunOnExecCtx);
+
+static void BM_ClosureCreateAndRun(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_run(&exec_ctx, grpc_closure_create(DoNothing, NULL,
+                                                    grpc_schedule_on_exec_ctx),
+                     GRPC_ERROR_NONE);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureCreateAndRun);
+
+static void BM_ClosureInitAndRun(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_closure c;
+  while (state.KeepRunning()) {
+    grpc_closure_run(&exec_ctx, grpc_closure_init(&c, DoNothing, NULL,
+                                                  grpc_schedule_on_exec_ctx),
+                     GRPC_ERROR_NONE);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureInitAndRun);
+
+static void BM_ClosureSchedOnExecCtx(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_closure c;
+  grpc_closure_init(&c, DoNothing, NULL, grpc_schedule_on_exec_ctx);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_sched(&exec_ctx, &c, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureSchedOnExecCtx);
+
+static void BM_ClosureSched2OnExecCtx(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_closure c1;
+  grpc_closure c2;
+  grpc_closure_init(&c1, DoNothing, NULL, grpc_schedule_on_exec_ctx);
+  grpc_closure_init(&c2, DoNothing, NULL, grpc_schedule_on_exec_ctx);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_sched(&exec_ctx, &c1, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c2, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureSched2OnExecCtx);
+
+static void BM_ClosureSched3OnExecCtx(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_closure c1;
+  grpc_closure c2;
+  grpc_closure c3;
+  grpc_closure_init(&c1, DoNothing, NULL, grpc_schedule_on_exec_ctx);
+  grpc_closure_init(&c2, DoNothing, NULL, grpc_schedule_on_exec_ctx);
+  grpc_closure_init(&c3, DoNothing, NULL, grpc_schedule_on_exec_ctx);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_sched(&exec_ctx, &c1, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c2, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c3, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureSched3OnExecCtx);
+
+static void BM_AcquireMutex(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  // for comparison with the combiner stuff below
+  gpr_mu mu;
+  gpr_mu_init(&mu);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    gpr_mu_lock(&mu);
+    DoNothing(&exec_ctx, NULL, GRPC_ERROR_NONE);
+    gpr_mu_unlock(&mu);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_AcquireMutex);
+
+static void BM_TryAcquireMutex(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  // for comparison with the combiner stuff below
+  gpr_mu mu;
+  gpr_mu_init(&mu);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    if (gpr_mu_trylock(&mu)) {
+      DoNothing(&exec_ctx, NULL, GRPC_ERROR_NONE);
+      gpr_mu_unlock(&mu);
+    } else {
+      abort();
+    }
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_TryAcquireMutex);
+
+static void BM_AcquireSpinlock(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  // for comparison with the combiner stuff below
+  gpr_spinlock mu = GPR_SPINLOCK_INITIALIZER;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    gpr_spinlock_lock(&mu);
+    DoNothing(&exec_ctx, NULL, GRPC_ERROR_NONE);
+    gpr_spinlock_unlock(&mu);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_AcquireSpinlock);
+
+static void BM_TryAcquireSpinlock(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  // for comparison with the combiner stuff below
+  gpr_spinlock mu = GPR_SPINLOCK_INITIALIZER;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    if (gpr_spinlock_trylock(&mu)) {
+      DoNothing(&exec_ctx, NULL, GRPC_ERROR_NONE);
+      gpr_spinlock_unlock(&mu);
+    } else {
+      abort();
+    }
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_TryAcquireSpinlock);
+
+static void BM_ClosureSchedOnCombiner(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_combiner* combiner = grpc_combiner_create(NULL);
+  grpc_closure c;
+  grpc_closure_init(&c, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner, false));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_sched(&exec_ctx, &c, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureSchedOnCombiner);
+
+static void BM_ClosureSched2OnCombiner(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_combiner* combiner = grpc_combiner_create(NULL);
+  grpc_closure c1;
+  grpc_closure c2;
+  grpc_closure_init(&c1, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner, false));
+  grpc_closure_init(&c2, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner, false));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_sched(&exec_ctx, &c1, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c2, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureSched2OnCombiner);
+
+static void BM_ClosureSched3OnCombiner(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_combiner* combiner = grpc_combiner_create(NULL);
+  grpc_closure c1;
+  grpc_closure c2;
+  grpc_closure c3;
+  grpc_closure_init(&c1, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner, false));
+  grpc_closure_init(&c2, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner, false));
+  grpc_closure_init(&c3, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner, false));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_sched(&exec_ctx, &c1, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c2, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c3, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureSched3OnCombiner);
+
+static void BM_ClosureSched2OnTwoCombiners(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_combiner* combiner1 = grpc_combiner_create(NULL);
+  grpc_combiner* combiner2 = grpc_combiner_create(NULL);
+  grpc_closure c1;
+  grpc_closure c2;
+  grpc_closure_init(&c1, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner1, false));
+  grpc_closure_init(&c2, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner2, false));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_sched(&exec_ctx, &c1, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c2, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner1, "finished");
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner2, "finished");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureSched2OnTwoCombiners);
+
+static void BM_ClosureSched4OnTwoCombiners(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_combiner* combiner1 = grpc_combiner_create(NULL);
+  grpc_combiner* combiner2 = grpc_combiner_create(NULL);
+  grpc_closure c1;
+  grpc_closure c2;
+  grpc_closure c3;
+  grpc_closure c4;
+  grpc_closure_init(&c1, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner1, false));
+  grpc_closure_init(&c2, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner2, false));
+  grpc_closure_init(&c3, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner1, false));
+  grpc_closure_init(&c4, DoNothing, NULL,
+                    grpc_combiner_scheduler(combiner2, false));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    grpc_closure_sched(&exec_ctx, &c1, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c2, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c3, GRPC_ERROR_NONE);
+    grpc_closure_sched(&exec_ctx, &c4, GRPC_ERROR_NONE);
+    grpc_exec_ctx_flush(&exec_ctx);
+  }
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner1, "finished");
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner2, "finished");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureSched4OnTwoCombiners);
+
+// Helper that continuously reschedules the same closure against something until
+// the benchmark is complete
+class Rescheduler {
+ public:
+  Rescheduler(benchmark::State& state, grpc_closure_scheduler* scheduler)
+      : state_(state) {
+    grpc_closure_init(&closure_, Step, this, scheduler);
+  }
+
+  void ScheduleFirst(grpc_exec_ctx* exec_ctx) {
+    grpc_closure_sched(exec_ctx, &closure_, GRPC_ERROR_NONE);
+  }
+
+  void ScheduleFirstAgainstDifferentScheduler(
+      grpc_exec_ctx* exec_ctx, grpc_closure_scheduler* scheduler) {
+    grpc_closure_sched(exec_ctx, grpc_closure_create(Step, this, scheduler),
+                       GRPC_ERROR_NONE);
+  }
+
+ private:
+  benchmark::State& state_;
+  grpc_closure closure_;
+
+  static void Step(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
+    Rescheduler* self = static_cast<Rescheduler*>(arg);
+    if (self->state_.KeepRunning()) {
+      grpc_closure_sched(exec_ctx, &self->closure_, GRPC_ERROR_NONE);
+    }
+  }
+};
+
+static void BM_ClosureReschedOnExecCtx(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  Rescheduler r(state, grpc_schedule_on_exec_ctx);
+  r.ScheduleFirst(&exec_ctx);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureReschedOnExecCtx);
+
+static void BM_ClosureReschedOnCombiner(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_combiner* combiner = grpc_combiner_create(NULL);
+  Rescheduler r(state, grpc_combiner_scheduler(combiner, false));
+  r.ScheduleFirst(&exec_ctx);
+  grpc_exec_ctx_flush(&exec_ctx);
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureReschedOnCombiner);
+
+static void BM_ClosureReschedOnCombinerFinally(benchmark::State& state) {
+  TrackCounters track_counters(state);
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_combiner* combiner = grpc_combiner_create(NULL);
+  Rescheduler r(state, grpc_combiner_finally_scheduler(combiner, false));
+  r.ScheduleFirstAgainstDifferentScheduler(
+      &exec_ctx, grpc_combiner_scheduler(combiner, false));
+  grpc_exec_ctx_flush(&exec_ctx);
+  GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_ClosureReschedOnCombinerFinally);
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_cq.cc b/test/cpp/microbenchmarks/bm_cq.cc
new file mode 100644
index 0000000..c017474
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_cq.cc
@@ -0,0 +1,145 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* This benchmark exists to ensure that the benchmark integration is
+ * working */
+
+#include <grpc++/completion_queue.h>
+#include <grpc++/impl/grpc_library.h>
+#include <grpc/grpc.h>
+
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+extern "C" {
+#include "src/core/lib/surface/completion_queue.h"
+}
+
+namespace grpc {
+namespace testing {
+
+static class InitializeStuff {
+ public:
+  InitializeStuff() { init_lib_.init(); }
+  ~InitializeStuff() { init_lib_.shutdown(); }
+
+ private:
+  internal::GrpcLibrary init_lib_;
+  internal::GrpcLibraryInitializer init_;
+} initialize_stuff;
+
+static void BM_CreateDestroyCpp(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    CompletionQueue cq;
+  }
+}
+BENCHMARK(BM_CreateDestroyCpp);
+
+static void BM_CreateDestroyCore(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    grpc_completion_queue_destroy(grpc_completion_queue_create(NULL));
+  }
+}
+BENCHMARK(BM_CreateDestroyCore);
+
+static void DoneWithCompletionOnStack(grpc_exec_ctx* exec_ctx, void* arg,
+                                      grpc_cq_completion* completion) {}
+
+class DummyTag final : public CompletionQueueTag {
+ public:
+  bool FinalizeResult(void** tag, bool* status) override { return true; }
+};
+
+static void BM_Pass1Cpp(benchmark::State& state) {
+  CompletionQueue cq;
+  grpc_completion_queue* c_cq = cq.cq();
+  while (state.KeepRunning()) {
+    grpc_cq_completion completion;
+    DummyTag dummy_tag;
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_cq_begin_op(c_cq, &dummy_tag);
+    grpc_cq_end_op(&exec_ctx, c_cq, &dummy_tag, GRPC_ERROR_NONE,
+                   DoneWithCompletionOnStack, NULL, &completion);
+    grpc_exec_ctx_finish(&exec_ctx);
+    void* tag;
+    bool ok;
+    cq.Next(&tag, &ok);
+  }
+}
+BENCHMARK(BM_Pass1Cpp);
+
+static void BM_Pass1Core(benchmark::State& state) {
+  grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
+  gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  while (state.KeepRunning()) {
+    grpc_cq_completion completion;
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_cq_begin_op(cq, NULL);
+    grpc_cq_end_op(&exec_ctx, cq, NULL, GRPC_ERROR_NONE,
+                   DoneWithCompletionOnStack, NULL, &completion);
+    grpc_exec_ctx_finish(&exec_ctx);
+    grpc_completion_queue_next(cq, deadline, NULL);
+  }
+  grpc_completion_queue_destroy(cq);
+}
+BENCHMARK(BM_Pass1Core);
+
+static void BM_Pluck1Core(benchmark::State& state) {
+  grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
+  gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  while (state.KeepRunning()) {
+    grpc_cq_completion completion;
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_cq_begin_op(cq, NULL);
+    grpc_cq_end_op(&exec_ctx, cq, NULL, GRPC_ERROR_NONE,
+                   DoneWithCompletionOnStack, NULL, &completion);
+    grpc_exec_ctx_finish(&exec_ctx);
+    grpc_completion_queue_pluck(cq, NULL, deadline, NULL);
+  }
+  grpc_completion_queue_destroy(cq);
+}
+BENCHMARK(BM_Pluck1Core);
+
+static void BM_EmptyCore(benchmark::State& state) {
+  grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
+  gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
+  while (state.KeepRunning()) {
+    grpc_completion_queue_next(cq, deadline, NULL);
+  }
+  grpc_completion_queue_destroy(cq);
+}
+BENCHMARK(BM_EmptyCore);
+
+}  // namespace testing
+}  // namespace grpc
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_error.cc b/test/cpp/microbenchmarks/bm_error.cc
new file mode 100644
index 0000000..8a4b86f
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_error.cc
@@ -0,0 +1,248 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Test various operations on grpc_error */
+
+#include <memory>
+
+extern "C" {
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/transport/error_utils.h"
+}
+
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+class ErrorDeleter {
+ public:
+  void operator()(grpc_error* error) { GRPC_ERROR_UNREF(error); }
+};
+typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr;
+
+static void BM_ErrorCreate(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    GRPC_ERROR_UNREF(GRPC_ERROR_CREATE("Error"));
+  }
+}
+BENCHMARK(BM_ErrorCreate);
+
+static void BM_ErrorCreateAndSetStatus(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    GRPC_ERROR_UNREF(grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
+                                        GRPC_ERROR_INT_GRPC_STATUS,
+                                        GRPC_STATUS_ABORTED));
+  }
+}
+BENCHMARK(BM_ErrorCreateAndSetStatus);
+
+static void BM_ErrorRefUnref(benchmark::State& state) {
+  grpc_error* error = GRPC_ERROR_CREATE("Error");
+  while (state.KeepRunning()) {
+    GRPC_ERROR_UNREF(GRPC_ERROR_REF(error));
+  }
+  GRPC_ERROR_UNREF(error);
+}
+BENCHMARK(BM_ErrorRefUnref);
+
+static void BM_ErrorUnrefNone(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    GRPC_ERROR_UNREF(GRPC_ERROR_NONE);
+  }
+}
+BENCHMARK(BM_ErrorUnrefNone);
+
+static void BM_ErrorGetIntFromNoError(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    intptr_t value;
+    grpc_error_get_int(GRPC_ERROR_NONE, GRPC_ERROR_INT_GRPC_STATUS, &value);
+  }
+}
+BENCHMARK(BM_ErrorGetIntFromNoError);
+
+static void BM_ErrorGetMissingInt(benchmark::State& state) {
+  ErrorPtr error(
+      grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_INDEX, 1));
+  while (state.KeepRunning()) {
+    intptr_t value;
+    grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
+  }
+}
+BENCHMARK(BM_ErrorGetMissingInt);
+
+static void BM_ErrorGetPresentInt(benchmark::State& state) {
+  ErrorPtr error(
+      grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_OFFSET, 1));
+  while (state.KeepRunning()) {
+    intptr_t value;
+    grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
+  }
+}
+BENCHMARK(BM_ErrorGetPresentInt);
+
+// Fixtures for tests: generate different kinds of errors
+class ErrorNone {
+ public:
+  gpr_timespec deadline() const { return deadline_; }
+  grpc_error* error() const { return GRPC_ERROR_NONE; }
+
+ private:
+  const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+};
+
+class ErrorCancelled {
+ public:
+  gpr_timespec deadline() const { return deadline_; }
+  grpc_error* error() const { return GRPC_ERROR_CANCELLED; }
+
+ private:
+  const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+};
+
+class SimpleError {
+ public:
+  gpr_timespec deadline() const { return deadline_; }
+  grpc_error* error() const { return error_.get(); }
+
+ private:
+  const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  ErrorPtr error_{GRPC_ERROR_CREATE("Error")};
+};
+
+class ErrorWithGrpcStatus {
+ public:
+  gpr_timespec deadline() const { return deadline_; }
+  grpc_error* error() const { return error_.get(); }
+
+ private:
+  const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  ErrorPtr error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
+                                     GRPC_ERROR_INT_GRPC_STATUS,
+                                     GRPC_STATUS_UNIMPLEMENTED)};
+};
+
+class ErrorWithHttpError {
+ public:
+  gpr_timespec deadline() const { return deadline_; }
+  grpc_error* error() const { return error_.get(); }
+
+ private:
+  const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  ErrorPtr error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
+                                     GRPC_ERROR_INT_HTTP2_ERROR,
+                                     GRPC_HTTP2_COMPRESSION_ERROR)};
+};
+
+class ErrorWithNestedGrpcStatus {
+ public:
+  gpr_timespec deadline() const { return deadline_; }
+  grpc_error* error() const { return error_.get(); }
+
+ private:
+  const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+  ErrorPtr nested_error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
+                                            GRPC_ERROR_INT_GRPC_STATUS,
+                                            GRPC_STATUS_UNIMPLEMENTED)};
+  grpc_error* nested_errors_[1] = {nested_error_.get()};
+  ErrorPtr error_{GRPC_ERROR_CREATE_REFERENCING("Error", nested_errors_, 1)};
+};
+
+template <class Fixture>
+static void BM_ErrorStringOnNewError(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    Fixture fixture;
+    grpc_error_string(fixture.error());
+  }
+}
+
+template <class Fixture>
+static void BM_ErrorStringRepeatedly(benchmark::State& state) {
+  Fixture fixture;
+  while (state.KeepRunning()) {
+    grpc_error_string(fixture.error());
+  }
+}
+
+template <class Fixture>
+static void BM_ErrorGetStatus(benchmark::State& state) {
+  Fixture fixture;
+  while (state.KeepRunning()) {
+    grpc_status_code status;
+    const char* msg;
+    grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &msg,
+                          NULL);
+  }
+}
+
+template <class Fixture>
+static void BM_ErrorGetStatusCode(benchmark::State& state) {
+  Fixture fixture;
+  while (state.KeepRunning()) {
+    grpc_status_code status;
+    grpc_error_get_status(fixture.error(), fixture.deadline(), &status, NULL,
+                          NULL);
+  }
+}
+
+template <class Fixture>
+static void BM_ErrorHttpError(benchmark::State& state) {
+  Fixture fixture;
+  while (state.KeepRunning()) {
+    grpc_http2_error_code error;
+    grpc_error_get_status(fixture.error(), fixture.deadline(), NULL, NULL,
+                          &error);
+  }
+}
+
+template <class Fixture>
+static void BM_HasClearGrpcStatus(benchmark::State& state) {
+  Fixture fixture;
+  while (state.KeepRunning()) {
+    grpc_error_has_clear_grpc_status(fixture.error());
+  }
+}
+
+#define BENCHMARK_SUITE(fixture)                         \
+  BENCHMARK_TEMPLATE(BM_ErrorStringOnNewError, fixture); \
+  BENCHMARK_TEMPLATE(BM_ErrorStringRepeatedly, fixture); \
+  BENCHMARK_TEMPLATE(BM_ErrorGetStatus, fixture);        \
+  BENCHMARK_TEMPLATE(BM_ErrorGetStatusCode, fixture);    \
+  BENCHMARK_TEMPLATE(BM_ErrorHttpError, fixture);        \
+  BENCHMARK_TEMPLATE(BM_HasClearGrpcStatus, fixture)
+
+BENCHMARK_SUITE(ErrorNone);
+BENCHMARK_SUITE(ErrorCancelled);
+BENCHMARK_SUITE(SimpleError);
+BENCHMARK_SUITE(ErrorWithGrpcStatus);
+BENCHMARK_SUITE(ErrorWithHttpError);
+BENCHMARK_SUITE(ErrorWithNestedGrpcStatus);
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_fullstack.cc b/test/cpp/microbenchmarks/bm_fullstack.cc
index 6c0bf80..48e131f 100644
--- a/test/cpp/microbenchmarks/bm_fullstack.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack.cc
@@ -46,6 +46,7 @@
 
 extern "C" {
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/endpoint_pair.h"
@@ -54,9 +55,12 @@
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/surface/completion_queue.h"
 #include "src/core/lib/surface/server.h"
+#include "test/core/util/memory_counters.h"
 #include "test/core/util/passthru_endpoint.h"
 #include "test/core/util/port.h"
+#include "test/core/util/trickle_endpoint.h"
 }
+#include "src/core/lib/profiling/timers.h"
 #include "src/cpp/client/create_channel_internal.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "third_party/benchmark/include/benchmark/benchmark.h"
@@ -67,6 +71,7 @@
 static class InitializeStuff {
  public:
   InitializeStuff() {
+    grpc_memory_counters_init();
     init_lib_.init();
     rq_ = grpc_resource_quota_create("bm");
   }
@@ -84,15 +89,77 @@
  * FIXTURES
  */
 
-class FullstackFixture {
+static void ApplyCommonServerBuilderConfig(ServerBuilder* b) {
+  b->SetMaxReceiveMessageSize(INT_MAX);
+  b->SetMaxSendMessageSize(INT_MAX);
+}
+
+static void ApplyCommonChannelArguments(ChannelArguments* c) {
+  c->SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, INT_MAX);
+  c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
+}
+
+#ifdef GPR_LOW_LEVEL_COUNTERS
+extern "C" gpr_atm gpr_mu_locks;
+extern "C" gpr_atm gpr_counter_atm_cas;
+extern "C" gpr_atm gpr_counter_atm_add;
+#endif
+
+class BaseFixture {
+ public:
+  void Finish(benchmark::State& s) {
+    std::ostringstream out;
+    this->AddToLabel(out, s);
+#ifdef GPR_LOW_LEVEL_COUNTERS
+    out << " locks/iter:" << ((double)(gpr_atm_no_barrier_load(&gpr_mu_locks) -
+                                       mu_locks_at_start_) /
+                              (double)s.iterations())
+        << " atm_cas/iter:"
+        << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_cas) -
+                     atm_cas_at_start_) /
+            (double)s.iterations())
+        << " atm_add/iter:"
+        << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_add) -
+                     atm_add_at_start_) /
+            (double)s.iterations());
+#endif
+    grpc_memory_counters counters_at_end = grpc_memory_counters_snapshot();
+    out << " allocs/iter:"
+        << ((double)(counters_at_end.total_allocs_absolute -
+                     counters_at_start_.total_allocs_absolute) /
+            (double)s.iterations());
+    auto label = out.str();
+    if (label.length() && label[0] == ' ') {
+      label = label.substr(1);
+    }
+    s.SetLabel(label);
+  }
+
+  virtual void AddToLabel(std::ostream& out, benchmark::State& s) = 0;
+
+ private:
+#ifdef GPR_LOW_LEVEL_COUNTERS
+  const size_t mu_locks_at_start_ = gpr_atm_no_barrier_load(&gpr_mu_locks);
+  const size_t atm_cas_at_start_ =
+      gpr_atm_no_barrier_load(&gpr_counter_atm_cas);
+  const size_t atm_add_at_start_ =
+      gpr_atm_no_barrier_load(&gpr_counter_atm_add);
+#endif
+  grpc_memory_counters counters_at_start_ = grpc_memory_counters_snapshot();
+};
+
+class FullstackFixture : public BaseFixture {
  public:
   FullstackFixture(Service* service, const grpc::string& address) {
     ServerBuilder b;
     b.AddListeningPort(address, InsecureServerCredentials());
     cq_ = b.AddCompletionQueue(true);
     b.RegisterService(service);
+    ApplyCommonServerBuilderConfig(&b);
     server_ = b.BuildAndStart();
-    channel_ = CreateChannel(address, InsecureChannelCredentials());
+    ChannelArguments args;
+    ApplyCommonChannelArguments(&args);
+    channel_ = CreateCustomChannel(address, InsecureChannelCredentials(), args);
   }
 
   virtual ~FullstackFixture() {
@@ -117,6 +184,8 @@
  public:
   TCP(Service* service) : FullstackFixture(service, MakeAddress()) {}
 
+  void AddToLabel(std::ostream& out, benchmark::State& state) {}
+
  private:
   static grpc::string MakeAddress() {
     int port = grpc_pick_unused_port_or_die();
@@ -130,6 +199,8 @@
  public:
   UDS(Service* service) : FullstackFixture(service, MakeAddress()) {}
 
+  void AddToLabel(std::ostream& out, benchmark::State& state) override {}
+
  private:
   static grpc::string MakeAddress() {
     int port = grpc_pick_unused_port_or_die();  // just for a unique id - not a
@@ -140,12 +211,14 @@
   }
 };
 
-class EndpointPairFixture {
+class EndpointPairFixture : public BaseFixture {
  public:
-  EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints) {
+  EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints)
+      : endpoint_pair_(endpoints) {
     ServerBuilder b;
     cq_ = b.AddCompletionQueue(true);
     b.RegisterService(service);
+    ApplyCommonServerBuilderConfig(&b);
     server_ = b.BuildAndStart();
 
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -154,7 +227,7 @@
     {
       const grpc_channel_args* server_args =
           grpc_server_get_channel_args(server_->c_server());
-      grpc_transport* transport = grpc_create_chttp2_transport(
+      server_transport_ = grpc_create_chttp2_transport(
           &exec_ctx, server_args, endpoints.server, 0 /* is_client */);
 
       grpc_pollset** pollsets;
@@ -165,23 +238,25 @@
         grpc_endpoint_add_to_pollset(&exec_ctx, endpoints.server, pollsets[i]);
       }
 
-      grpc_server_setup_transport(&exec_ctx, server_->c_server(), transport,
-                                  NULL, server_args);
-      grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
+      grpc_server_setup_transport(&exec_ctx, server_->c_server(),
+                                  server_transport_, NULL, server_args);
+      grpc_chttp2_transport_start_reading(&exec_ctx, server_transport_, NULL);
     }
 
     /* create channel */
     {
       ChannelArguments args;
       args.SetString(GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
+      ApplyCommonChannelArguments(&args);
 
       grpc_channel_args c_args = args.c_channel_args();
-      grpc_transport* transport =
+      client_transport_ =
           grpc_create_chttp2_transport(&exec_ctx, &c_args, endpoints.client, 1);
-      GPR_ASSERT(transport);
-      grpc_channel* channel = grpc_channel_create(
-          &exec_ctx, "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, transport);
-      grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
+      GPR_ASSERT(client_transport_);
+      grpc_channel* channel =
+          grpc_channel_create(&exec_ctx, "target", &c_args,
+                              GRPC_CLIENT_DIRECT_CHANNEL, client_transport_);
+      grpc_chttp2_transport_start_reading(&exec_ctx, client_transport_, NULL);
 
       channel_ = CreateChannelInternal("", channel);
     }
@@ -201,6 +276,11 @@
   ServerCompletionQueue* cq() { return cq_.get(); }
   std::shared_ptr<Channel> channel() { return channel_; }
 
+ protected:
+  grpc_endpoint_pair endpoint_pair_;
+  grpc_transport* client_transport_;
+  grpc_transport* server_transport_;
+
  private:
   std::unique_ptr<Server> server_;
   std::unique_ptr<ServerCompletionQueue> cq_;
@@ -213,6 +293,8 @@
       : EndpointPairFixture(service, grpc_iomgr_create_endpoint_pair(
                                          "test", initialize_stuff.rq(), 8192)) {
   }
+
+  void AddToLabel(std::ostream& out, benchmark::State& state) {}
 };
 
 class InProcessCHTTP2 : public EndpointPairFixture {
@@ -220,14 +302,91 @@
   InProcessCHTTP2(Service* service)
       : EndpointPairFixture(service, MakeEndpoints()) {}
 
+  void AddToLabel(std::ostream& out, benchmark::State& state) {
+    out << " writes/iter:"
+        << ((double)stats_.num_writes / (double)state.iterations());
+  }
+
  private:
+  grpc_passthru_endpoint_stats stats_;
+
   grpc_endpoint_pair MakeEndpoints() {
     grpc_endpoint_pair p;
-    grpc_passthru_endpoint_create(&p.client, &p.server, initialize_stuff.rq());
+    grpc_passthru_endpoint_create(&p.client, &p.server, initialize_stuff.rq(),
+                                  &stats_);
     return p;
   }
 };
 
+class TrickledCHTTP2 : public EndpointPairFixture {
+ public:
+  TrickledCHTTP2(Service* service, size_t megabits_per_second)
+      : EndpointPairFixture(service, MakeEndpoints(megabits_per_second)) {}
+
+  void AddToLabel(std::ostream& out, benchmark::State& state) {
+    out << " writes/iter:"
+        << ((double)stats_.num_writes / (double)state.iterations())
+        << " cli_transport_stalls/iter:"
+        << ((double)
+                client_stats_.streams_stalled_due_to_transport_flow_control /
+            (double)state.iterations())
+        << " cli_stream_stalls/iter:"
+        << ((double)client_stats_.streams_stalled_due_to_stream_flow_control /
+            (double)state.iterations())
+        << " svr_transport_stalls/iter:"
+        << ((double)
+                server_stats_.streams_stalled_due_to_transport_flow_control /
+            (double)state.iterations())
+        << " svr_stream_stalls/iter:"
+        << ((double)server_stats_.streams_stalled_due_to_stream_flow_control /
+            (double)state.iterations());
+  }
+
+  void Step() {
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    size_t client_backlog =
+        grpc_trickle_endpoint_trickle(&exec_ctx, endpoint_pair_.client);
+    size_t server_backlog =
+        grpc_trickle_endpoint_trickle(&exec_ctx, endpoint_pair_.server);
+    grpc_exec_ctx_finish(&exec_ctx);
+
+    UpdateStats((grpc_chttp2_transport*)client_transport_, &client_stats_,
+                client_backlog);
+    UpdateStats((grpc_chttp2_transport*)server_transport_, &server_stats_,
+                server_backlog);
+  }
+
+ private:
+  grpc_passthru_endpoint_stats stats_;
+  struct Stats {
+    int streams_stalled_due_to_stream_flow_control = 0;
+    int streams_stalled_due_to_transport_flow_control = 0;
+  };
+  Stats client_stats_;
+  Stats server_stats_;
+
+  grpc_endpoint_pair MakeEndpoints(size_t kilobits) {
+    grpc_endpoint_pair p;
+    grpc_passthru_endpoint_create(&p.client, &p.server, initialize_stuff.rq(),
+                                  &stats_);
+    double bytes_per_second = 125.0 * kilobits;
+    p.client = grpc_trickle_endpoint_create(p.client, bytes_per_second);
+    p.server = grpc_trickle_endpoint_create(p.server, bytes_per_second);
+    return p;
+  }
+
+  void UpdateStats(grpc_chttp2_transport* t, Stats* s, size_t backlog) {
+    if (backlog == 0) {
+      if (t->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != NULL) {
+        s->streams_stalled_due_to_stream_flow_control++;
+      }
+      if (t->lists[GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT].head != NULL) {
+        s->streams_stalled_due_to_transport_flow_control++;
+      }
+    }
+  }
+};
+
 /*******************************************************************************
  * CONTEXT MUTATORS
  */
@@ -343,6 +502,12 @@
   EchoRequest send_request;
   EchoResponse send_response;
   EchoResponse recv_response;
+  if (state.range(0) > 0) {
+    send_request.set_message(std::string(state.range(0), 'a'));
+  }
+  if (state.range(1) > 0) {
+    send_response.set_message(std::string(state.range(1), 'a'));
+  }
   Status recv_status;
   struct ServerEnv {
     ServerContext ctx;
@@ -365,6 +530,8 @@
   std::unique_ptr<EchoTestService::Stub> stub(
       EchoTestService::NewStub(fixture->channel()));
   while (state.KeepRunning()) {
+    GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+    recv_response.Clear();
     ClientContext cli_ctx;
     ClientContextMutator cli_ctx_mut(&cli_ctx);
     std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
@@ -393,56 +560,518 @@
     service.RequestEcho(&senv->ctx, &senv->recv_request, &senv->response_writer,
                         fixture->cq(), fixture->cq(), tag(slot));
   }
+  fixture->Finish(state);
   fixture.reset();
   server_env[0]->~ServerEnv();
   server_env[1]->~ServerEnv();
+  state.SetBytesProcessed(state.range(0) * state.iterations() +
+                          state.range(1) * state.iterations());
+}
+
+// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
+// messages in each call) in a loop on a single channel
+//
+//  First parmeter (i.e state.range(0)):  Message size (in bytes) to use
+//  Second parameter (i.e state.range(1)): Number of ping pong messages.
+//      Note: One ping-pong means two messages (one from client to server and
+//      the other from server to client):
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPong(benchmark::State& state) {
+  const int msg_size = state.range(0);
+  const int max_ping_pongs = state.range(1);
+
+  EchoTestService::AsyncService service;
+  std::unique_ptr<Fixture> fixture(new Fixture(&service));
+  {
+    EchoResponse send_response;
+    EchoResponse recv_response;
+    EchoRequest send_request;
+    EchoRequest recv_request;
+
+    if (msg_size > 0) {
+      send_request.set_message(std::string(msg_size, 'a'));
+      send_response.set_message(std::string(msg_size, 'b'));
+    }
+
+    std::unique_ptr<EchoTestService::Stub> stub(
+        EchoTestService::NewStub(fixture->channel()));
+
+    while (state.KeepRunning()) {
+      ServerContext svr_ctx;
+      ServerContextMutator svr_ctx_mut(&svr_ctx);
+      ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+      service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+                                fixture->cq(), tag(0));
+
+      ClientContext cli_ctx;
+      ClientContextMutator cli_ctx_mut(&cli_ctx);
+      auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+
+      // Establish async stream between client side and server side
+      void* t;
+      bool ok;
+      int need_tags = (1 << 0) | (1 << 1);
+      while (need_tags) {
+        GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+        GPR_ASSERT(ok);
+        int i = (int)(intptr_t)t;
+        GPR_ASSERT(need_tags & (1 << i));
+        need_tags &= ~(1 << i);
+      }
+
+      // Send 'max_ping_pongs' number of ping pong messages
+      int ping_pong_cnt = 0;
+      while (ping_pong_cnt < max_ping_pongs) {
+        request_rw->Write(send_request, tag(0));   // Start client send
+        response_rw.Read(&recv_request, tag(1));   // Start server recv
+        request_rw->Read(&recv_response, tag(2));  // Start client recv
+
+        need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
+        while (need_tags) {
+          GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+          GPR_ASSERT(ok);
+          int i = (int)(intptr_t)t;
+
+          // If server recv is complete, start the server send operation
+          if (i == 1) {
+            response_rw.Write(send_response, tag(3));
+          }
+
+          GPR_ASSERT(need_tags & (1 << i));
+          need_tags &= ~(1 << i);
+        }
+
+        ping_pong_cnt++;
+      }
+
+      request_rw->WritesDone(tag(0));
+      response_rw.Finish(Status::OK, tag(1));
+
+      Status recv_status;
+      request_rw->Finish(&recv_status, tag(2));
+
+      need_tags = (1 << 0) | (1 << 1) | (1 << 2);
+      while (need_tags) {
+        GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+        int i = (int)(intptr_t)t;
+        GPR_ASSERT(need_tags & (1 << i));
+        need_tags &= ~(1 << i);
+      }
+
+      GPR_ASSERT(recv_status.ok());
+    }
+  }
+
+  fixture->Finish(state);
+  fixture.reset();
+  state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
+}
+
+// Repeatedly sends ping pong messages in a single streaming Bidi call in a loop
+//     First parmeter (i.e state.range(0)):  Message size (in bytes) to use
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPongMsgs(benchmark::State& state) {
+  const int msg_size = state.range(0);
+
+  EchoTestService::AsyncService service;
+  std::unique_ptr<Fixture> fixture(new Fixture(&service));
+  {
+    EchoResponse send_response;
+    EchoResponse recv_response;
+    EchoRequest send_request;
+    EchoRequest recv_request;
+
+    if (msg_size > 0) {
+      send_request.set_message(std::string(msg_size, 'a'));
+      send_response.set_message(std::string(msg_size, 'b'));
+    }
+
+    std::unique_ptr<EchoTestService::Stub> stub(
+        EchoTestService::NewStub(fixture->channel()));
+
+    ServerContext svr_ctx;
+    ServerContextMutator svr_ctx_mut(&svr_ctx);
+    ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+    service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+                              fixture->cq(), tag(0));
+
+    ClientContext cli_ctx;
+    ClientContextMutator cli_ctx_mut(&cli_ctx);
+    auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+
+    // Establish async stream between client side and server side
+    void* t;
+    bool ok;
+    int need_tags = (1 << 0) | (1 << 1);
+    while (need_tags) {
+      GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+      GPR_ASSERT(ok);
+      int i = (int)(intptr_t)t;
+      GPR_ASSERT(need_tags & (1 << i));
+      need_tags &= ~(1 << i);
+    }
+
+    while (state.KeepRunning()) {
+      GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+      request_rw->Write(send_request, tag(0));   // Start client send
+      response_rw.Read(&recv_request, tag(1));   // Start server recv
+      request_rw->Read(&recv_response, tag(2));  // Start client recv
+
+      need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
+      while (need_tags) {
+        GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+        GPR_ASSERT(ok);
+        int i = (int)(intptr_t)t;
+
+        // If server recv is complete, start the server send operation
+        if (i == 1) {
+          response_rw.Write(send_response, tag(3));
+        }
+
+        GPR_ASSERT(need_tags & (1 << i));
+        need_tags &= ~(1 << i);
+      }
+    }
+
+    request_rw->WritesDone(tag(0));
+    response_rw.Finish(Status::OK, tag(1));
+    Status recv_status;
+    request_rw->Finish(&recv_status, tag(2));
+
+    need_tags = (1 << 0) | (1 << 1) | (1 << 2);
+    while (need_tags) {
+      GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+      int i = (int)(intptr_t)t;
+      GPR_ASSERT(need_tags & (1 << i));
+      need_tags &= ~(1 << i);
+    }
+
+    GPR_ASSERT(recv_status.ok());
+  }
+
+  fixture->Finish(state);
+  fixture.reset();
+  state.SetBytesProcessed(msg_size * state.iterations() * 2);
+}
+
+template <class Fixture>
+static void BM_PumpStreamClientToServer(benchmark::State& state) {
+  EchoTestService::AsyncService service;
+  std::unique_ptr<Fixture> fixture(new Fixture(&service));
+  {
+    EchoRequest send_request;
+    EchoRequest recv_request;
+    if (state.range(0) > 0) {
+      send_request.set_message(std::string(state.range(0), 'a'));
+    }
+    Status recv_status;
+    ServerContext svr_ctx;
+    ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+    service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+                              fixture->cq(), tag(0));
+    std::unique_ptr<EchoTestService::Stub> stub(
+        EchoTestService::NewStub(fixture->channel()));
+    ClientContext cli_ctx;
+    auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+    int need_tags = (1 << 0) | (1 << 1);
+    void* t;
+    bool ok;
+    while (need_tags) {
+      GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+      GPR_ASSERT(ok);
+      int i = (int)(intptr_t)t;
+      GPR_ASSERT(need_tags & (1 << i));
+      need_tags &= ~(1 << i);
+    }
+    response_rw.Read(&recv_request, tag(0));
+    while (state.KeepRunning()) {
+      GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+      request_rw->Write(send_request, tag(1));
+      while (true) {
+        GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+        if (t == tag(0)) {
+          response_rw.Read(&recv_request, tag(0));
+        } else if (t == tag(1)) {
+          break;
+        } else {
+          GPR_ASSERT(false);
+        }
+      }
+    }
+    request_rw->WritesDone(tag(1));
+    need_tags = (1 << 0) | (1 << 1);
+    while (need_tags) {
+      GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+      int i = (int)(intptr_t)t;
+      GPR_ASSERT(need_tags & (1 << i));
+      need_tags &= ~(1 << i);
+    }
+  }
+  fixture->Finish(state);
+  fixture.reset();
+  state.SetBytesProcessed(state.range(0) * state.iterations());
+}
+
+template <class Fixture>
+static void BM_PumpStreamServerToClient(benchmark::State& state) {
+  EchoTestService::AsyncService service;
+  std::unique_ptr<Fixture> fixture(new Fixture(&service));
+  {
+    EchoResponse send_response;
+    EchoResponse recv_response;
+    if (state.range(0) > 0) {
+      send_response.set_message(std::string(state.range(0), 'a'));
+    }
+    Status recv_status;
+    ServerContext svr_ctx;
+    ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+    service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+                              fixture->cq(), tag(0));
+    std::unique_ptr<EchoTestService::Stub> stub(
+        EchoTestService::NewStub(fixture->channel()));
+    ClientContext cli_ctx;
+    auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+    int need_tags = (1 << 0) | (1 << 1);
+    void* t;
+    bool ok;
+    while (need_tags) {
+      GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+      GPR_ASSERT(ok);
+      int i = (int)(intptr_t)t;
+      GPR_ASSERT(need_tags & (1 << i));
+      need_tags &= ~(1 << i);
+    }
+    request_rw->Read(&recv_response, tag(0));
+    while (state.KeepRunning()) {
+      GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+      response_rw.Write(send_response, tag(1));
+      while (true) {
+        GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+        if (t == tag(0)) {
+          request_rw->Read(&recv_response, tag(0));
+        } else if (t == tag(1)) {
+          break;
+        } else {
+          GPR_ASSERT(false);
+        }
+      }
+    }
+    response_rw.Finish(Status::OK, tag(1));
+    need_tags = (1 << 0) | (1 << 1);
+    while (need_tags) {
+      GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+      int i = (int)(intptr_t)t;
+      GPR_ASSERT(need_tags & (1 << i));
+      need_tags &= ~(1 << i);
+    }
+  }
+  fixture->Finish(state);
+  fixture.reset();
+  state.SetBytesProcessed(state.range(0) * state.iterations());
+}
+
+static void TrickleCQNext(TrickledCHTTP2* fixture, void** t, bool* ok) {
+  while (true) {
+    switch (fixture->cq()->AsyncNext(
+        t, ok, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                            gpr_time_from_micros(100, GPR_TIMESPAN)))) {
+      case CompletionQueue::TIMEOUT:
+        fixture->Step();
+        break;
+      case CompletionQueue::SHUTDOWN:
+        GPR_ASSERT(false);
+        break;
+      case CompletionQueue::GOT_EVENT:
+        return;
+    }
+  }
+}
+
+static void BM_PumpStreamServerToClient_Trickle(benchmark::State& state) {
+  EchoTestService::AsyncService service;
+  std::unique_ptr<TrickledCHTTP2> fixture(
+      new TrickledCHTTP2(&service, state.range(1)));
+  {
+    EchoResponse send_response;
+    EchoResponse recv_response;
+    if (state.range(0) > 0) {
+      send_response.set_message(std::string(state.range(0), 'a'));
+    }
+    Status recv_status;
+    ServerContext svr_ctx;
+    ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+    service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+                              fixture->cq(), tag(0));
+    std::unique_ptr<EchoTestService::Stub> stub(
+        EchoTestService::NewStub(fixture->channel()));
+    ClientContext cli_ctx;
+    auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+    int need_tags = (1 << 0) | (1 << 1);
+    void* t;
+    bool ok;
+    while (need_tags) {
+      TrickleCQNext(fixture.get(), &t, &ok);
+      GPR_ASSERT(ok);
+      int i = (int)(intptr_t)t;
+      GPR_ASSERT(need_tags & (1 << i));
+      need_tags &= ~(1 << i);
+    }
+    request_rw->Read(&recv_response, tag(0));
+    while (state.KeepRunning()) {
+      GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+      response_rw.Write(send_response, tag(1));
+      while (true) {
+        TrickleCQNext(fixture.get(), &t, &ok);
+        if (t == tag(0)) {
+          request_rw->Read(&recv_response, tag(0));
+        } else if (t == tag(1)) {
+          break;
+        } else {
+          GPR_ASSERT(false);
+        }
+      }
+    }
+    response_rw.Finish(Status::OK, tag(1));
+    need_tags = (1 << 0) | (1 << 1);
+    while (need_tags) {
+      TrickleCQNext(fixture.get(), &t, &ok);
+      int i = (int)(intptr_t)t;
+      GPR_ASSERT(need_tags & (1 << i));
+      need_tags &= ~(1 << i);
+    }
+  }
+  fixture->Finish(state);
+  fixture.reset();
+  state.SetBytesProcessed(state.range(0) * state.iterations());
 }
 
 /*******************************************************************************
  * CONFIGURATIONS
  */
 
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, TCP, NoOpMutator, NoOpMutator);
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, UDS, NoOpMutator, NoOpMutator);
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, SockPair, NoOpMutator, NoOpMutator);
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator, NoOpMutator);
+static void SweepSizesArgs(benchmark::internal::Benchmark* b) {
+  b->Args({0, 0});
+  for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) {
+    b->Args({i, 0});
+    b->Args({0, i});
+    b->Args({i, i});
+  }
+}
+
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, TCP, NoOpMutator, NoOpMutator)
+    ->Apply(SweepSizesArgs);
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, UDS, NoOpMutator, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, SockPair, NoOpMutator, NoOpMutator)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator, NoOpMutator)
+    ->Apply(SweepSizesArgs);
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
-                   Client_AddMetadata<RandomBinaryMetadata<10>, 1>,
-                   NoOpMutator);
+                   Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
-                   Client_AddMetadata<RandomBinaryMetadata<31>, 1>,
-                   NoOpMutator);
+                   Client_AddMetadata<RandomBinaryMetadata<31>, 1>, NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
                    Client_AddMetadata<RandomBinaryMetadata<100>, 1>,
-                   NoOpMutator);
+                   NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
-                   Client_AddMetadata<RandomBinaryMetadata<10>, 2>,
-                   NoOpMutator);
+                   Client_AddMetadata<RandomBinaryMetadata<10>, 2>, NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
-                   Client_AddMetadata<RandomBinaryMetadata<31>, 2>,
-                   NoOpMutator);
+                   Client_AddMetadata<RandomBinaryMetadata<31>, 2>, NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
                    Client_AddMetadata<RandomBinaryMetadata<100>, 2>,
-                   NoOpMutator);
+                   NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
-                   Server_AddInitialMetadata<RandomBinaryMetadata<10>, 1>);
+                   Server_AddInitialMetadata<RandomBinaryMetadata<10>, 1>)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
-                   Server_AddInitialMetadata<RandomBinaryMetadata<31>, 1>);
+                   Server_AddInitialMetadata<RandomBinaryMetadata<31>, 1>)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
-                   Server_AddInitialMetadata<RandomBinaryMetadata<100>, 1>);
+                   Server_AddInitialMetadata<RandomBinaryMetadata<100>, 1>)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
-                   Client_AddMetadata<RandomAsciiMetadata<10>, 1>, NoOpMutator);
+                   Client_AddMetadata<RandomAsciiMetadata<10>, 1>, NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
-                   Client_AddMetadata<RandomAsciiMetadata<31>, 1>, NoOpMutator);
+                   Client_AddMetadata<RandomAsciiMetadata<31>, 1>, NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
-                   Client_AddMetadata<RandomAsciiMetadata<100>, 1>,
-                   NoOpMutator);
+                   Client_AddMetadata<RandomAsciiMetadata<100>, 1>, NoOpMutator)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
-                   Server_AddInitialMetadata<RandomAsciiMetadata<10>, 1>);
+                   Server_AddInitialMetadata<RandomAsciiMetadata<10>, 1>)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
-                   Server_AddInitialMetadata<RandomAsciiMetadata<31>, 1>);
+                   Server_AddInitialMetadata<RandomAsciiMetadata<31>, 1>)
+    ->Args({0, 0});
 BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
-                   Server_AddInitialMetadata<RandomAsciiMetadata<100>, 1>);
+                   Server_AddInitialMetadata<RandomAsciiMetadata<100>, 1>)
+    ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
+                   Server_AddInitialMetadata<RandomAsciiMetadata<10>, 100>)
+    ->Args({0, 0});
+
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, TCP)
+    ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, UDS)
+    ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, SockPair)
+    ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcessCHTTP2)
+    ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, TCP)
+    ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, UDS)
+    ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, SockPair)
+    ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcessCHTTP2)
+    ->Range(0, 128 * 1024 * 1024);
+
+static void TrickleArgs(benchmark::internal::Benchmark* b) {
+  for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) {
+    for (int j = 1; j <= 128 * 1024 * 1024; j *= 8) {
+      double expected_time =
+          static_cast<double>(14 + i) / (125.0 * static_cast<double>(j));
+      if (expected_time > 0.01) continue;
+      b->Args({i, j});
+    }
+  }
+}
+
+BENCHMARK(BM_PumpStreamServerToClient_Trickle)->Apply(TrickleArgs);
+
+// Generate Args for StreamingPingPong benchmarks. Currently generates args for
+// only "small streams" (i.e streams with 0, 1 or 2 messages)
+static void StreamingPingPongArgs(benchmark::internal::Benchmark* b) {
+  int msg_size = 0;
+
+  b->Args({0, 0});  // spl case: 0 ping-pong msgs (msg_size doesn't matter here)
+
+  for (msg_size = 0; msg_size <= 128 * 1024 * 1024;
+       msg_size == 0 ? msg_size++ : msg_size *= 8) {
+    b->Args({msg_size, 1});
+    b->Args({msg_size, 2});
+  }
+}
+
+BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcessCHTTP2, NoOpMutator,
+                   NoOpMutator)
+    ->Apply(StreamingPingPongArgs);
+BENCHMARK_TEMPLATE(BM_StreamingPingPong, TCP, NoOpMutator, NoOpMutator)
+    ->Apply(StreamingPingPongArgs);
+
+BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcessCHTTP2, NoOpMutator,
+                   NoOpMutator)
+    ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator)
+    ->Range(0, 128 * 1024 * 1024);
 
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/cpp/microbenchmarks/bm_metadata.cc b/test/cpp/microbenchmarks/bm_metadata.cc
new file mode 100644
index 0000000..7f81fba
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_metadata.cc
@@ -0,0 +1,282 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Test out various metadata handling primitives */
+
+#include <grpc/grpc.h>
+
+extern "C" {
+#include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/static_metadata.h"
+}
+
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+static class InitializeStuff {
+ public:
+  InitializeStuff() { grpc_init(); }
+  ~InitializeStuff() { grpc_shutdown(); }
+} initialize_stuff;
+
+static void BM_SliceFromStatic(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(grpc_slice_from_static_string("abc"));
+  }
+}
+BENCHMARK(BM_SliceFromStatic);
+
+static void BM_SliceFromCopied(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    grpc_slice_unref(grpc_slice_from_copied_string("abc"));
+  }
+}
+BENCHMARK(BM_SliceFromCopied);
+
+static void BM_SliceIntern(benchmark::State& state) {
+  gpr_slice slice = grpc_slice_from_static_string("abc");
+  while (state.KeepRunning()) {
+    grpc_slice_unref(grpc_slice_intern(slice));
+  }
+}
+BENCHMARK(BM_SliceIntern);
+
+static void BM_SliceReIntern(benchmark::State& state) {
+  gpr_slice slice = grpc_slice_intern(grpc_slice_from_static_string("abc"));
+  while (state.KeepRunning()) {
+    grpc_slice_unref(grpc_slice_intern(slice));
+  }
+  grpc_slice_unref(slice);
+}
+BENCHMARK(BM_SliceReIntern);
+
+static void BM_SliceInternStaticMetadata(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    grpc_slice_intern(GRPC_MDSTR_GZIP);
+  }
+}
+BENCHMARK(BM_SliceInternStaticMetadata);
+
+static void BM_SliceInternEqualToStaticMetadata(benchmark::State& state) {
+  gpr_slice slice = grpc_slice_from_static_string("gzip");
+  while (state.KeepRunning()) {
+    grpc_slice_intern(slice);
+  }
+}
+BENCHMARK(BM_SliceInternEqualToStaticMetadata);
+
+static void BM_MetadataFromNonInternedSlices(benchmark::State& state) {
+  gpr_slice k = grpc_slice_from_static_string("key");
+  gpr_slice v = grpc_slice_from_static_string("value");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataFromNonInternedSlices);
+
+static void BM_MetadataFromInternedSlices(benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+  grpc_slice_unref(v);
+}
+BENCHMARK(BM_MetadataFromInternedSlices);
+
+static void BM_MetadataFromInternedSlicesAlreadyInIndex(
+    benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem seed = grpc_mdelem_create(&exec_ctx, k, v, NULL);
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, seed);
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+  grpc_slice_unref(v);
+}
+BENCHMARK(BM_MetadataFromInternedSlicesAlreadyInIndex);
+
+static void BM_MetadataFromInternedKey(benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_from_static_string("value");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+}
+BENCHMARK(BM_MetadataFromInternedKey);
+
+static void BM_MetadataFromNonInternedSlicesWithBackingStore(
+    benchmark::State& state) {
+  gpr_slice k = grpc_slice_from_static_string("key");
+  gpr_slice v = grpc_slice_from_static_string("value");
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(
+        &exec_ctx,
+        grpc_mdelem_create(&exec_ctx, k, v,
+                           reinterpret_cast<grpc_mdelem_data*>(backing_store)));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataFromNonInternedSlicesWithBackingStore);
+
+static void BM_MetadataFromInternedSlicesWithBackingStore(
+    benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(
+        &exec_ctx,
+        grpc_mdelem_create(&exec_ctx, k, v,
+                           reinterpret_cast<grpc_mdelem_data*>(backing_store)));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+  grpc_slice_unref(v);
+}
+BENCHMARK(BM_MetadataFromInternedSlicesWithBackingStore);
+
+static void BM_MetadataFromInternedKeyWithBackingStore(
+    benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_from_static_string("value");
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(
+        &exec_ctx,
+        grpc_mdelem_create(&exec_ctx, k, v,
+                           reinterpret_cast<grpc_mdelem_data*>(backing_store)));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+}
+BENCHMARK(BM_MetadataFromInternedKeyWithBackingStore);
+
+static void BM_MetadataFromStaticMetadataStrings(benchmark::State& state) {
+  gpr_slice k = GRPC_MDSTR_STATUS;
+  gpr_slice v = GRPC_MDSTR_200;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+}
+BENCHMARK(BM_MetadataFromStaticMetadataStrings);
+
+static void BM_MetadataFromStaticMetadataStringsNotIndexed(
+    benchmark::State& state) {
+  gpr_slice k = GRPC_MDSTR_STATUS;
+  gpr_slice v = GRPC_MDSTR_GZIP;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+}
+BENCHMARK(BM_MetadataFromStaticMetadataStringsNotIndexed);
+
+static void BM_MetadataRefUnrefExternal(benchmark::State& state) {
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem el =
+      grpc_mdelem_create(&exec_ctx, grpc_slice_from_static_string("a"),
+                         grpc_slice_from_static_string("b"),
+                         reinterpret_cast<grpc_mdelem_data*>(backing_store));
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, el);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataRefUnrefExternal);
+
+static void BM_MetadataRefUnrefInterned(benchmark::State& state) {
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
+  grpc_mdelem el = grpc_mdelem_create(
+      &exec_ctx, k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store));
+  grpc_slice_unref(k);
+  grpc_slice_unref(v);
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, el);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataRefUnrefInterned);
+
+static void BM_MetadataRefUnrefAllocated(benchmark::State& state) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem el =
+      grpc_mdelem_create(&exec_ctx, grpc_slice_from_static_string("a"),
+                         grpc_slice_from_static_string("b"), NULL);
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, el);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataRefUnrefAllocated);
+
+static void BM_MetadataRefUnrefStatic(benchmark::State& state) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem el =
+      grpc_mdelem_create(&exec_ctx, GRPC_MDSTR_STATUS, GRPC_MDSTR_200, NULL);
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, el);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataRefUnrefStatic);
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/representative_server_initial_metadata.headers b/test/cpp/microbenchmarks/representative_server_initial_metadata.headers
new file mode 100644
index 0000000..d3e6933
--- /dev/null
+++ b/test/cpp/microbenchmarks/representative_server_initial_metadata.headers
@@ -0,0 +1,4 @@
+:status: 200
+content-type: application/grpc
+grpc-accept-encoding: identity,deflate,gzip
+
diff --git a/test/cpp/microbenchmarks/representative_server_trailing_metadata.headers b/test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
new file mode 100644
index 0000000..544d089
--- /dev/null
+++ b/test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
@@ -0,0 +1,3 @@
+grpc-status: 0
+grpc-message:
+
diff --git a/test/cpp/performance/writes_per_rpc_test.cc b/test/cpp/performance/writes_per_rpc_test.cc
new file mode 100644
index 0000000..7a914c1
--- /dev/null
+++ b/test/cpp/performance/writes_per_rpc_test.cc
@@ -0,0 +1,268 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc++/channel.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/impl/grpc_library.h>
+#include <grpc++/security/credentials.h>
+#include <grpc++/security/server_credentials.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc/support/log.h>
+#include <gtest/gtest.h>
+
+extern "C" {
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/endpoint_pair.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/tcp_posix.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/surface/server.h"
+#include "test/core/util/passthru_endpoint.h"
+#include "test/core/util/port.h"
+}
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc {
+namespace testing {
+
+static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
+
+static void ApplyCommonServerBuilderConfig(ServerBuilder* b) {
+  b->SetMaxReceiveMessageSize(INT_MAX);
+  b->SetMaxSendMessageSize(INT_MAX);
+}
+
+static void ApplyCommonChannelArguments(ChannelArguments* c) {
+  c->SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, INT_MAX);
+  c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
+}
+
+static class InitializeStuff {
+ public:
+  InitializeStuff() {
+    init_lib_.init();
+    rq_ = grpc_resource_quota_create("bm");
+  }
+
+  ~InitializeStuff() { init_lib_.shutdown(); }
+
+  grpc_resource_quota* rq() { return rq_; }
+
+ private:
+  internal::GrpcLibrary init_lib_;
+  grpc_resource_quota* rq_;
+} initialize_stuff;
+
+class EndpointPairFixture {
+ public:
+  EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints) {
+    ServerBuilder b;
+    cq_ = b.AddCompletionQueue(true);
+    b.RegisterService(service);
+    ApplyCommonServerBuilderConfig(&b);
+    server_ = b.BuildAndStart();
+
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+    /* add server endpoint to server_ */
+    {
+      const grpc_channel_args* server_args =
+          grpc_server_get_channel_args(server_->c_server());
+      grpc_transport* transport = grpc_create_chttp2_transport(
+          &exec_ctx, server_args, endpoints.server, 0 /* is_client */);
+
+      grpc_pollset** pollsets;
+      size_t num_pollsets = 0;
+      grpc_server_get_pollsets(server_->c_server(), &pollsets, &num_pollsets);
+
+      for (size_t i = 0; i < num_pollsets; i++) {
+        grpc_endpoint_add_to_pollset(&exec_ctx, endpoints.server, pollsets[i]);
+      }
+
+      grpc_server_setup_transport(&exec_ctx, server_->c_server(), transport,
+                                  NULL, server_args);
+      grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
+    }
+
+    /* create channel */
+    {
+      ChannelArguments args;
+      args.SetString(GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
+      ApplyCommonChannelArguments(&args);
+
+      grpc_channel_args c_args = args.c_channel_args();
+      grpc_transport* transport =
+          grpc_create_chttp2_transport(&exec_ctx, &c_args, endpoints.client, 1);
+      GPR_ASSERT(transport);
+      grpc_channel* channel = grpc_channel_create(
+          &exec_ctx, "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, transport);
+      grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
+
+      channel_ = CreateChannelInternal("", channel);
+    }
+
+    grpc_exec_ctx_finish(&exec_ctx);
+  }
+
+  virtual ~EndpointPairFixture() {
+    server_->Shutdown();
+    cq_->Shutdown();
+    void* tag;
+    bool ok;
+    while (cq_->Next(&tag, &ok)) {
+    }
+  }
+
+  ServerCompletionQueue* cq() { return cq_.get(); }
+  std::shared_ptr<Channel> channel() { return channel_; }
+
+ private:
+  std::unique_ptr<Server> server_;
+  std::unique_ptr<ServerCompletionQueue> cq_;
+  std::shared_ptr<Channel> channel_;
+};
+
+class InProcessCHTTP2 : public EndpointPairFixture {
+ public:
+  InProcessCHTTP2(Service* service)
+      : EndpointPairFixture(service, MakeEndpoints()) {}
+
+  int writes_performed() const { return stats_.num_writes; }
+
+ private:
+  grpc_passthru_endpoint_stats stats_;
+
+  grpc_endpoint_pair MakeEndpoints() {
+    grpc_endpoint_pair p;
+    grpc_passthru_endpoint_create(&p.client, &p.server, initialize_stuff.rq(),
+                                  &stats_);
+    return p;
+  }
+};
+
+static double UnaryPingPong(int request_size, int response_size) {
+  const int kIterations = 10000;
+
+  EchoTestService::AsyncService service;
+  std::unique_ptr<InProcessCHTTP2> fixture(new InProcessCHTTP2(&service));
+  EchoRequest send_request;
+  EchoResponse send_response;
+  EchoResponse recv_response;
+  if (request_size > 0) {
+    send_request.set_message(std::string(request_size, 'a'));
+  }
+  if (response_size > 0) {
+    send_response.set_message(std::string(response_size, 'a'));
+  }
+  Status recv_status;
+  struct ServerEnv {
+    ServerContext ctx;
+    EchoRequest recv_request;
+    grpc::ServerAsyncResponseWriter<EchoResponse> response_writer;
+    ServerEnv() : response_writer(&ctx) {}
+  };
+  uint8_t server_env_buffer[2 * sizeof(ServerEnv)];
+  ServerEnv* server_env[2] = {
+      reinterpret_cast<ServerEnv*>(server_env_buffer),
+      reinterpret_cast<ServerEnv*>(server_env_buffer + sizeof(ServerEnv))};
+  new (server_env[0]) ServerEnv;
+  new (server_env[1]) ServerEnv;
+  service.RequestEcho(&server_env[0]->ctx, &server_env[0]->recv_request,
+                      &server_env[0]->response_writer, fixture->cq(),
+                      fixture->cq(), tag(0));
+  service.RequestEcho(&server_env[1]->ctx, &server_env[1]->recv_request,
+                      &server_env[1]->response_writer, fixture->cq(),
+                      fixture->cq(), tag(1));
+  std::unique_ptr<EchoTestService::Stub> stub(
+      EchoTestService::NewStub(fixture->channel()));
+  for (int iteration = 0; iteration < kIterations; iteration++) {
+    recv_response.Clear();
+    ClientContext cli_ctx;
+    std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
+        stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
+    void* t;
+    bool ok;
+    GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+    GPR_ASSERT(ok);
+    GPR_ASSERT(t == tag(0) || t == tag(1));
+    intptr_t slot = reinterpret_cast<intptr_t>(t);
+    ServerEnv* senv = server_env[slot];
+    senv->response_writer.Finish(send_response, Status::OK, tag(3));
+    response_reader->Finish(&recv_response, &recv_status, tag(4));
+    for (int i = (1 << 3) | (1 << 4); i != 0;) {
+      GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+      GPR_ASSERT(ok);
+      int tagnum = (int)reinterpret_cast<intptr_t>(t);
+      GPR_ASSERT(i & (1 << tagnum));
+      i -= 1 << tagnum;
+    }
+    GPR_ASSERT(recv_status.ok());
+
+    senv->~ServerEnv();
+    senv = new (senv) ServerEnv();
+    service.RequestEcho(&senv->ctx, &senv->recv_request, &senv->response_writer,
+                        fixture->cq(), fixture->cq(), tag(slot));
+  }
+
+  double writes_per_iteration =
+      (double)fixture->writes_performed() / (double)kIterations;
+
+  fixture.reset();
+  server_env[0]->~ServerEnv();
+  server_env[1]->~ServerEnv();
+
+  return writes_per_iteration;
+}
+
+TEST(WritesPerRpcTest, UnaryPingPong) {
+  EXPECT_LT(UnaryPingPong(0, 0), 2.05);
+  EXPECT_LT(UnaryPingPong(1, 0), 2.05);
+  EXPECT_LT(UnaryPingPong(0, 1), 2.05);
+  EXPECT_LT(UnaryPingPong(4096, 0), 2.2);
+  EXPECT_LT(UnaryPingPong(0, 4096), 2.2);
+}
+
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  grpc_test_init(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index b1e6186..498416c 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -153,7 +153,6 @@
       if (*stream) {
         (*stream)->WritesDone();
         Status s = (*stream)->Finish();
-        EXPECT_TRUE(s.ok());
         if (!s.ok()) {
           gpr_log(GPR_ERROR, "Stream %zu received an error %s", i,
                   s.error_message().c_str());
@@ -173,7 +172,11 @@
       entry->set_value((UsageTimer::Now() - start) * 1e9);
       return true;
     }
-    return false;
+    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
+    context_[thread_idx].~ClientContext();
+    new (&context_[thread_idx]) ClientContext();
+    stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]);
+    return true;
   }
 
  private:
diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py
index 188d619..2f035ab 100755
--- a/test/cpp/qps/gen_build_yaml.py
+++ b/test/cpp/qps/gen_build_yaml.py
@@ -92,7 +92,8 @@
       'defaults': 'boringssl',
       'cpu_cost': guess_cpu(scenario_json, False),
       'exclude_configs': ['tsan', 'asan'],
-      'timeout_seconds': 6*60
+      'timeout_seconds': 6*60,
+      'excluded_poll_engines': scenario_json.get('EXCLUDED_POLL_ENGINES', [])
     }
     for scenario_json in scenario_config.CXXLanguage().scenarios()
     if 'scalable' in scenario_json.get('CATEGORIES', [])
@@ -109,8 +110,9 @@
       'defaults': 'boringssl',
       'cpu_cost': guess_cpu(scenario_json, True),
       'exclude_configs': sorted(c for c in configs_from_yaml if c not in ('tsan', 'asan')),
-      'timeout_seconds': 6*60
-    }
+      'timeout_seconds': 6*60,
+      'excluded_poll_engines': scenario_json.get('EXCLUDED_POLL_ENGINES', [])
+   }
     for scenario_json in scenario_config.CXXLanguage().scenarios()
     if 'scalable' in scenario_json.get('CATEGORIES', [])
   ]
diff --git a/test/cpp/qps/qps_openloop_test.cc b/test/cpp/qps/qps_openloop_test.cc
index 8dc50ac..70e2709 100644
--- a/test/cpp/qps/qps_openloop_test.cc
+++ b/test/cpp/qps/qps_openloop_test.cc
@@ -56,7 +56,7 @@
   client_config.set_async_client_threads(8);
   client_config.set_rpc_type(STREAMING);
   client_config.mutable_load_params()->mutable_poisson()->set_offered_load(
-      1000.0 / GRPC_TEST_SLOWDOWN_FACTOR);
+      1000.0 / grpc_test_slowdown_factor());
 
   ServerConfig server_config;
   server_config.set_server_type(ASYNC_SERVER);
diff --git a/test/cpp/qps/qps_test_with_poll.cc b/test/cpp/qps/qps_test_with_poll.cc
deleted file mode 100644
index c64e6c9..0000000
--- a/test/cpp/qps/qps_test_with_poll.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <set>
-
-#include <grpc/support/log.h>
-
-#include "test/cpp/qps/driver.h"
-#include "test/cpp/qps/report.h"
-#include "test/cpp/util/benchmark_config.h"
-
-extern "C" {
-#include "src/core/lib/iomgr/pollset_posix.h"
-}
-
-namespace grpc {
-namespace testing {
-
-static const int WARMUP = 5;
-static const int BENCHMARK = 5;
-
-static void RunQPS() {
-  gpr_log(GPR_INFO, "Running QPS test");
-
-  ClientConfig client_config;
-  client_config.set_client_type(ASYNC_CLIENT);
-  client_config.set_outstanding_rpcs_per_channel(1000);
-  client_config.set_client_channels(8);
-  client_config.set_async_client_threads(8);
-  client_config.set_rpc_type(UNARY);
-  client_config.mutable_load_params()->mutable_closed_loop();
-
-  ServerConfig server_config;
-  server_config.set_server_type(ASYNC_SERVER);
-  server_config.set_async_server_threads(4);
-
-  const auto result =
-      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
-
-  GetReporter()->ReportQPSPerCore(*result);
-  GetReporter()->ReportLatency(*result);
-}
-
-}  // namespace testing
-}  // namespace grpc
-
-int main(int argc, char** argv) {
-  grpc::testing::InitBenchmark(&argc, &argv, true);
-
-  grpc_platform_become_multipoller = grpc_poll_become_multipoller;
-
-  grpc::testing::RunQPS();
-
-  return 0;
-}
diff --git a/test/cpp/qps/usage_timer.cc b/test/cpp/qps/usage_timer.cc
index c6697fb..70ef26e 100644
--- a/test/cpp/qps/usage_timer.cc
+++ b/test/cpp/qps/usage_timer.cc
@@ -39,8 +39,15 @@
 
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
+#ifdef __linux__
 #include <sys/resource.h>
 #include <sys/time.h>
+
+static double time_double(struct timeval* tv) {
+  return tv->tv_sec + 1e-6 * tv->tv_usec;
+}
+#endif
+
 UsageTimer::UsageTimer() : start_(Sample()) {}
 
 double UsageTimer::Now() {
@@ -48,8 +55,16 @@
   return ts.tv_sec + 1e-9 * ts.tv_nsec;
 }
 
-static double time_double(struct timeval* tv) {
-  return tv->tv_sec + 1e-6 * tv->tv_usec;
+static void get_resource_usage(double* utime, double* stime) {
+#ifdef __linux__
+  struct rusage usage;
+  getrusage(RUSAGE_SELF, &usage);
+  *utime = time_double(&usage.ru_utime);
+  *stime = time_double(&usage.ru_stime);
+#else
+  *utime = 0;
+  *stime = 0;
+#endif
 }
 
 static void get_cpu_usage(unsigned long long* total_cpu_time,
@@ -74,15 +89,9 @@
 }
 
 UsageTimer::Result UsageTimer::Sample() {
-  struct rusage usage;
-  struct timeval tv;
-  gettimeofday(&tv, NULL);
-  getrusage(RUSAGE_SELF, &usage);
-
   Result r;
-  r.wall = time_double(&tv);
-  r.user = time_double(&usage.ru_utime);
-  r.system = time_double(&usage.ru_stime);
+  r.wall = Now();
+  get_resource_usage(&r.user, &r.system);
   r.total_cpu_time = 0;
   r.idle_cpu_time = 0;
   get_cpu_usage(&r.total_cpu_time, &r.idle_cpu_time);
diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc
index 2068b7c..e88d064 100644
--- a/test/cpp/qps/worker.cc
+++ b/test/cpp/qps/worker.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <sys/signal.h>
+#include <signal.h>
 
 #include <chrono>
 #include <thread>
diff --git a/test/cpp/test/server_context_test_spouse_test.cc b/test/cpp/test/server_context_test_spouse_test.cc
index e0d6a2f..eb279e2 100644
--- a/test/cpp/test/server_context_test_spouse_test.cc
+++ b/test/cpp/test/server_context_test_spouse_test.cc
@@ -36,11 +36,14 @@
 #include <cstring>
 #include <vector>
 
+#include <grpc++/impl/grpc_library.h>
 #include <gtest/gtest.h>
 
 namespace grpc {
 namespace testing {
 
+static internal::GrpcLibraryInitializer g_initializer;
+
 const char key1[] = "metadata-key1";
 const char key2[] = "metadata-key2";
 const char val1[] = "metadata-val1";
diff --git a/test/cpp/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc
index 284761c..35c8d5d 100644
--- a/test/cpp/thread_manager/thread_manager_test.cc
+++ b/test/cpp/thread_manager/thread_manager_test.cc
@@ -31,6 +31,7 @@
  *is % allowed in string
  */
 
+#include <ctime>
 #include <memory>
 #include <string>
 
diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD
new file mode 100644
index 0000000..dc90a4e
--- /dev/null
+++ b/test/cpp/util/BUILD
@@ -0,0 +1,85 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+licenses(["notice"])  # 3-clause BSD
+
+cc_library(
+    name = "test_config",
+    srcs = [
+        "test_config_cc.cc",
+    ],
+    hdrs = [
+        "test_config.h",
+    ],
+    visibility = ["//test:__subpackages__"],
+    deps = [
+        "//:gpr",
+        "//external:gflags",
+    ],
+)
+
+cc_library(
+    name = "grpc++_proto_reflection_desc_db",
+    srcs = [
+        "proto_reflection_descriptor_database.cc",
+    ],
+    hdrs = [
+        "proto_reflection_descriptor_database.h",
+    ],
+    visibility = ["//test:__subpackages__"],
+    deps = [
+        "//:grpc++_config_proto",
+        "//src/proto/grpc/reflection/v1alpha:reflection_proto",
+    ],
+)
+
+cc_library(
+    name = "test_util",
+    srcs = [
+        #        "test/cpp/end2end/test_service_impl.cc",
+        "byte_buffer_proto_helper.cc",
+        "create_test_channel.cc",
+        "string_ref_helper.cc",
+        "subprocess.cc",
+        "test_credentials_provider.cc",
+    ],
+    hdrs = [
+        "byte_buffer_proto_helper.h",
+        "create_test_channel.h",
+        "string_ref_helper.h",
+        "subprocess.h",
+        "test_credentials_provider.h",
+    ],
+    visibility = ["//test:__subpackages__"],
+    deps = [
+        "//:grpc++",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+    ],
+)
diff --git a/test/cpp/util/cli_call.cc b/test/cpp/util/cli_call.cc
index a02a8b2..041cc0e 100644
--- a/test/cpp/util/cli_call.cc
+++ b/test/cpp/util/cli_call.cc
@@ -37,8 +37,6 @@
 
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
-#include <grpc++/completion_queue.h>
-#include <grpc++/generic/generic_stub.h>
 #include <grpc++/support/byte_buffer.h>
 #include <grpc/grpc.h>
 #include <grpc/slice.h>
@@ -56,55 +54,172 @@
                      const OutgoingMetadataContainer& metadata,
                      IncomingMetadataContainer* server_initial_metadata,
                      IncomingMetadataContainer* server_trailing_metadata) {
-  std::unique_ptr<grpc::GenericStub> stub(new grpc::GenericStub(channel));
-  grpc::ClientContext ctx;
+  CliCall call(channel, method, metadata);
+  call.Write(request);
+  call.WritesDone();
+  if (!call.Read(response, server_initial_metadata)) {
+    fprintf(stderr, "Failed to read response.\n");
+  }
+  return call.Finish(server_trailing_metadata);
+}
+
+CliCall::CliCall(std::shared_ptr<grpc::Channel> channel,
+                 const grpc::string& method,
+                 const OutgoingMetadataContainer& metadata)
+    : stub_(new grpc::GenericStub(channel)) {
+  gpr_mu_init(&write_mu_);
+  gpr_cv_init(&write_cv_);
   if (!metadata.empty()) {
     for (OutgoingMetadataContainer::const_iterator iter = metadata.begin();
          iter != metadata.end(); ++iter) {
-      ctx.AddMetadata(iter->first, iter->second);
+      ctx_.AddMetadata(iter->first, iter->second);
     }
   }
-  grpc::CompletionQueue cq;
-  std::unique_ptr<grpc::GenericClientAsyncReaderWriter> call(
-      stub->Call(&ctx, method, &cq, tag(1)));
+  call_ = stub_->Call(&ctx_, method, &cq_, tag(1));
   void* got_tag;
   bool ok;
-  cq.Next(&got_tag, &ok);
+  cq_.Next(&got_tag, &ok);
   GPR_ASSERT(ok);
+}
+
+CliCall::~CliCall() {
+  gpr_cv_destroy(&write_cv_);
+  gpr_mu_destroy(&write_mu_);
+}
+
+void CliCall::Write(const grpc::string& request) {
+  void* got_tag;
+  bool ok;
 
   grpc_slice s = grpc_slice_from_copied_string(request.c_str());
   grpc::Slice req_slice(s, grpc::Slice::STEAL_REF);
   grpc::ByteBuffer send_buffer(&req_slice, 1);
-  call->Write(send_buffer, tag(2));
-  cq.Next(&got_tag, &ok);
+  call_->Write(send_buffer, tag(2));
+  cq_.Next(&got_tag, &ok);
   GPR_ASSERT(ok);
-  call->WritesDone(tag(3));
-  cq.Next(&got_tag, &ok);
-  GPR_ASSERT(ok);
+}
+
+bool CliCall::Read(grpc::string* response,
+                   IncomingMetadataContainer* server_initial_metadata) {
+  void* got_tag;
+  bool ok;
+
   grpc::ByteBuffer recv_buffer;
-  call->Read(&recv_buffer, tag(4));
-  cq.Next(&got_tag, &ok);
-  if (!ok) {
-    std::cout << "Failed to read response." << std::endl;
+  call_->Read(&recv_buffer, tag(3));
+
+  if (!cq_.Next(&got_tag, &ok) || !ok) {
+    return false;
   }
-  grpc::Status status;
-  call->Finish(&status, tag(5));
-  cq.Next(&got_tag, &ok);
+  std::vector<grpc::Slice> slices;
+  GPR_ASSERT(recv_buffer.Dump(&slices).ok());
+
+  response->clear();
+  for (size_t i = 0; i < slices.size(); i++) {
+    response->append(reinterpret_cast<const char*>(slices[i].begin()),
+                     slices[i].size());
+  }
+  if (server_initial_metadata) {
+    *server_initial_metadata = ctx_.GetServerInitialMetadata();
+  }
+  return true;
+}
+
+void CliCall::WritesDone() {
+  void* got_tag;
+  bool ok;
+
+  call_->WritesDone(tag(4));
+  cq_.Next(&got_tag, &ok);
   GPR_ASSERT(ok);
+}
 
-  if (status.ok()) {
-    std::vector<grpc::Slice> slices;
-    (void)recv_buffer.Dump(&slices);
+void CliCall::WriteAndWait(const grpc::string& request) {
+  grpc_slice s = grpc_slice_from_copied_string(request.c_str());
+  grpc::Slice req_slice(s, grpc::Slice::STEAL_REF);
+  grpc::ByteBuffer send_buffer(&req_slice, 1);
 
-    response->clear();
-    for (size_t i = 0; i < slices.size(); i++) {
-      response->append(reinterpret_cast<const char*>(slices[i].begin()),
-                       slices[i].size());
+  gpr_mu_lock(&write_mu_);
+  call_->Write(send_buffer, tag(2));
+  write_done_ = false;
+  while (!write_done_) {
+    gpr_cv_wait(&write_cv_, &write_mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
+  }
+  gpr_mu_unlock(&write_mu_);
+}
+
+void CliCall::WritesDoneAndWait() {
+  gpr_mu_lock(&write_mu_);
+  call_->WritesDone(tag(4));
+  write_done_ = false;
+  while (!write_done_) {
+    gpr_cv_wait(&write_cv_, &write_mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
+  }
+  gpr_mu_unlock(&write_mu_);
+}
+
+bool CliCall::ReadAndMaybeNotifyWrite(
+    grpc::string* response,
+    IncomingMetadataContainer* server_initial_metadata) {
+  void* got_tag;
+  bool ok;
+  grpc::ByteBuffer recv_buffer;
+
+  call_->Read(&recv_buffer, tag(3));
+  bool cq_result = cq_.Next(&got_tag, &ok);
+
+  while (got_tag != tag(3)) {
+    gpr_mu_lock(&write_mu_);
+    write_done_ = true;
+    gpr_cv_signal(&write_cv_);
+    gpr_mu_unlock(&write_mu_);
+
+    cq_result = cq_.Next(&got_tag, &ok);
+    if (got_tag == tag(2)) {
+      GPR_ASSERT(ok);
     }
   }
 
-  *server_initial_metadata = ctx.GetServerInitialMetadata();
-  *server_trailing_metadata = ctx.GetServerTrailingMetadata();
+  if (!cq_result || !ok) {
+    // If the RPC is ended on the server side, we should still wait for the
+    // pending write on the client side to be done.
+    if (!ok) {
+      gpr_mu_lock(&write_mu_);
+      if (!write_done_) {
+        cq_.Next(&got_tag, &ok);
+        GPR_ASSERT(got_tag != tag(2));
+        write_done_ = true;
+        gpr_cv_signal(&write_cv_);
+      }
+      gpr_mu_unlock(&write_mu_);
+    }
+    return false;
+  }
+
+  std::vector<grpc::Slice> slices;
+  GPR_ASSERT(recv_buffer.Dump(&slices).ok());
+  response->clear();
+  for (size_t i = 0; i < slices.size(); i++) {
+    response->append(reinterpret_cast<const char*>(slices[i].begin()),
+                     slices[i].size());
+  }
+  if (server_initial_metadata) {
+    *server_initial_metadata = ctx_.GetServerInitialMetadata();
+  }
+  return true;
+}
+
+Status CliCall::Finish(IncomingMetadataContainer* server_trailing_metadata) {
+  void* got_tag;
+  bool ok;
+  grpc::Status status;
+
+  call_->Finish(&status, tag(5));
+  cq_.Next(&got_tag, &ok);
+  GPR_ASSERT(ok);
+  if (server_trailing_metadata) {
+    *server_trailing_metadata = ctx_.GetServerTrailingMetadata();
+  }
+
   return status;
 }
 
diff --git a/test/cpp/util/cli_call.h b/test/cpp/util/cli_call.h
index 65da86b..91f0dbc 100644
--- a/test/cpp/util/cli_call.h
+++ b/test/cpp/util/cli_call.h
@@ -37,23 +37,74 @@
 #include <map>
 
 #include <grpc++/channel.h>
+#include <grpc++/completion_queue.h>
+#include <grpc++/generic/generic_stub.h>
 #include <grpc++/support/status.h>
 #include <grpc++/support/string_ref.h>
 
 namespace grpc {
+
+class ClientContext;
+
 namespace testing {
 
+// CliCall handles the sending and receiving of generic messages given the name
+// of the remote method. This class is only used by GrpcTool. Its thread-safe
+// and thread-unsafe methods should not be used together.
 class CliCall final {
  public:
   typedef std::multimap<grpc::string, grpc::string> OutgoingMetadataContainer;
   typedef std::multimap<grpc::string_ref, grpc::string_ref>
       IncomingMetadataContainer;
+
+  CliCall(std::shared_ptr<grpc::Channel> channel, const grpc::string& method,
+          const OutgoingMetadataContainer& metadata);
+  ~CliCall();
+
+  // Perform an unary generic RPC.
   static Status Call(std::shared_ptr<grpc::Channel> channel,
                      const grpc::string& method, const grpc::string& request,
                      grpc::string* response,
                      const OutgoingMetadataContainer& metadata,
                      IncomingMetadataContainer* server_initial_metadata,
                      IncomingMetadataContainer* server_trailing_metadata);
+
+  // Send a generic request message in a synchronous manner. NOT thread-safe.
+  void Write(const grpc::string& request);
+
+  // Send a generic request message in a synchronous manner. NOT thread-safe.
+  void WritesDone();
+
+  // Receive a generic response message in a synchronous manner.NOT thread-safe.
+  bool Read(grpc::string* response,
+            IncomingMetadataContainer* server_initial_metadata);
+
+  // Thread-safe write. Must be used with ReadAndMaybeNotifyWrite. Send out a
+  // generic request message and wait for ReadAndMaybeNotifyWrite to finish it.
+  void WriteAndWait(const grpc::string& request);
+
+  // Thread-safe WritesDone. Must be used with ReadAndMaybeNotifyWrite. Send out
+  // WritesDone for gereneric request messages and wait for
+  // ReadAndMaybeNotifyWrite to finish it.
+  void WritesDoneAndWait();
+
+  // Thread-safe Read. Blockingly receive a generic response message. Notify
+  // writes if they are finished when this read is waiting for a resposne.
+  bool ReadAndMaybeNotifyWrite(
+      grpc::string* response,
+      IncomingMetadataContainer* server_initial_metadata);
+
+  // Finish the RPC.
+  Status Finish(IncomingMetadataContainer* server_trailing_metadata);
+
+ private:
+  std::unique_ptr<grpc::GenericStub> stub_;
+  grpc::ClientContext ctx_;
+  std::unique_ptr<grpc::GenericClientAsyncReaderWriter> call_;
+  grpc::CompletionQueue cq_;
+  gpr_mu write_mu_;
+  gpr_cv write_cv_;  // Protected by write_mu_;
+  bool write_done_;  // Portected by write_mu_;
 };
 
 }  // namespace testing
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index fe24860..a78bed4 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -83,10 +83,10 @@
 static bool SimplePrint(const grpc::string& outfile,
                         const grpc::string& output) {
   if (outfile.empty()) {
-    std::cout << output;
+    std::cout << output << std::endl;
   } else {
-    std::ofstream output_file(outfile, std::ios::trunc | std::ios::binary);
-    output_file << output;
+    std::ofstream output_file(outfile, std::ios::app | std::ios::binary);
+    output_file << output << std::endl;
     output_file.close();
   }
   return true;
diff --git a/test/cpp/util/grpc_tool.cc b/test/cpp/util/grpc_tool.cc
index b9900ca..856cd32 100644
--- a/test/cpp/util/grpc_tool.cc
+++ b/test/cpp/util/grpc_tool.cc
@@ -33,12 +33,13 @@
 
 #include "test/cpp/util/grpc_tool.h"
 
-#include <unistd.h>
+#include <cstdio>
 #include <fstream>
 #include <iostream>
 #include <memory>
 #include <sstream>
 #include <string>
+#include <thread>
 
 #include <gflags/gflags.h>
 #include <grpc++/channel.h>
@@ -47,12 +48,19 @@
 #include <grpc++/security/credentials.h>
 #include <grpc++/support/string_ref.h>
 #include <grpc/grpc.h>
+#include <grpc/support/port_platform.h>
 
 #include "test/cpp/util/cli_call.h"
 #include "test/cpp/util/proto_file_parser.h"
 #include "test/cpp/util/proto_reflection_descriptor_database.h"
 #include "test/cpp/util/service_describer.h"
 
+#if GPR_WINDOWS
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
 namespace grpc {
 namespace testing {
 
@@ -159,6 +167,36 @@
   }
 }
 
+void ReadResponse(CliCall* call, const grpc::string& method_name,
+                  GrpcToolOutputCallback callback, ProtoFileParser* parser,
+                  gpr_mu* parser_mu, bool print_mode) {
+  grpc::string serialized_response_proto;
+  std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata;
+
+  for (bool receive_initial_metadata = true; call->ReadAndMaybeNotifyWrite(
+           &serialized_response_proto,
+           receive_initial_metadata ? &server_initial_metadata : nullptr);
+       receive_initial_metadata = false) {
+    fprintf(stderr, "got response.\n");
+    if (!FLAGS_binary_output) {
+      gpr_mu_lock(parser_mu);
+      serialized_response_proto = parser->GetTextFormatFromMethod(
+          method_name, serialized_response_proto, false /* is_request */);
+      if (parser->HasError() && print_mode) {
+        fprintf(stderr, "Failed to parse response.\n");
+      }
+      gpr_mu_unlock(parser_mu);
+    }
+    if (receive_initial_metadata) {
+      PrintMetadata(server_initial_metadata,
+                    "Received initial metadata from server:");
+    }
+    if (!callback(serialized_response_proto) && print_mode) {
+      fprintf(stderr, "Failed to output response.\n");
+    }
+  }
+}
+
 struct Command {
   const char* command;
   std::function<bool(GrpcTool*, int, const char**, const CliCredentials&,
@@ -416,85 +454,191 @@
   grpc::string server_address(argv[0]);
   grpc::string method_name(argv[1]);
   grpc::string formatted_method_name;
-  std::unique_ptr<grpc::testing::ProtoFileParser> parser;
+  std::unique_ptr<ProtoFileParser> parser;
   grpc::string serialized_request_proto;
-
-  if (argc == 3) {
-    request_text = argv[2];
-    if (!FLAGS_infile.empty()) {
-      fprintf(stderr, "warning: request given in argv, ignoring --infile\n");
-    }
-  } else {
-    std::stringstream input_stream;
-    if (FLAGS_infile.empty()) {
-      if (isatty(STDIN_FILENO)) {
-        fprintf(stderr, "reading request message from stdin...\n");
-      }
-      input_stream << std::cin.rdbuf();
-    } else {
-      std::ifstream input_file(FLAGS_infile, std::ios::in | std::ios::binary);
-      input_stream << input_file.rdbuf();
-      input_file.close();
-    }
-    request_text = input_stream.str();
-  }
+  bool print_mode = false;
 
   std::shared_ptr<grpc::Channel> channel =
-      grpc::CreateChannel(server_address, cred.GetCredentials());
-  if (!FLAGS_binary_input || !FLAGS_binary_output) {
-    parser.reset(
-        new grpc::testing::ProtoFileParser(FLAGS_remotedb ? channel : nullptr,
-                                           FLAGS_proto_path, FLAGS_protofiles));
-    if (parser->HasError()) {
-      return false;
-    }
-  }
+      FLAGS_remotedb
+          ? grpc::CreateChannel(server_address, cred.GetCredentials())
+          : nullptr;
+
+  parser.reset(new grpc::testing::ProtoFileParser(channel, FLAGS_proto_path,
+                                                  FLAGS_protofiles));
 
   if (FLAGS_binary_input) {
-    serialized_request_proto = request_text;
     formatted_method_name = method_name;
   } else {
     formatted_method_name = parser->GetFormattedMethodName(method_name);
-    serialized_request_proto = parser->GetSerializedProtoFromMethod(
-        method_name, request_text, true /* is_request */);
-    if (parser->HasError()) {
+  }
+
+  if (parser->HasError()) {
+    return false;
+  }
+
+  if (parser->IsStreaming(method_name, true /* is_request */)) {
+    std::istream* input_stream;
+    std::ifstream input_file;
+
+    if (argc == 3) {
+      request_text = argv[2];
+    }
+
+    std::multimap<grpc::string, grpc::string> client_metadata;
+    ParseMetadataFlag(&client_metadata);
+    PrintMetadata(client_metadata, "Sending client initial metadata:");
+
+    CliCall call(channel, formatted_method_name, client_metadata);
+
+    if (FLAGS_infile.empty()) {
+      if (isatty(fileno(stdin))) {
+        print_mode = true;
+        fprintf(stderr, "reading streaming request message from stdin...\n");
+      }
+      input_stream = &std::cin;
+    } else {
+      input_file.open(FLAGS_infile, std::ios::in | std::ios::binary);
+      input_stream = &input_file;
+    }
+
+    gpr_mu parser_mu;
+    gpr_mu_init(&parser_mu);
+    std::thread read_thread(ReadResponse, &call, method_name, callback,
+                            parser.get(), &parser_mu, print_mode);
+
+    std::stringstream request_ss;
+    grpc::string line;
+    while (!request_text.empty() ||
+           (!input_stream->eof() && getline(*input_stream, line))) {
+      if (!request_text.empty()) {
+        if (FLAGS_binary_input) {
+          serialized_request_proto = request_text;
+          request_text.clear();
+        } else {
+          gpr_mu_lock(&parser_mu);
+          serialized_request_proto = parser->GetSerializedProtoFromMethod(
+              method_name, request_text, true /* is_request */);
+          request_text.clear();
+          if (parser->HasError()) {
+            if (print_mode) {
+              fprintf(stderr, "Failed to parse request.\n");
+            }
+            gpr_mu_unlock(&parser_mu);
+            continue;
+          }
+          gpr_mu_unlock(&parser_mu);
+        }
+
+        call.WriteAndWait(serialized_request_proto);
+        if (print_mode) {
+          fprintf(stderr, "Request sent.\n");
+        }
+      } else {
+        if (line.length() == 0) {
+          request_text = request_ss.str();
+          request_ss.str(grpc::string());
+          request_ss.clear();
+        } else {
+          request_ss << line << ' ';
+        }
+      }
+    }
+    if (input_file.is_open()) {
+      input_file.close();
+    }
+
+    call.WritesDoneAndWait();
+    read_thread.join();
+
+    std::multimap<grpc::string_ref, grpc::string_ref> server_trailing_metadata;
+    Status status = call.Finish(&server_trailing_metadata);
+    PrintMetadata(server_trailing_metadata,
+                  "Received trailing metadata from server:");
+
+    if (status.ok()) {
+      fprintf(stderr, "Stream RPC succeeded with OK status\n");
+      return true;
+    } else {
+      fprintf(stderr, "Rpc failed with status code %d, error message: %s\n",
+              status.error_code(), status.error_message().c_str());
       return false;
     }
-  }
-  fprintf(stderr, "connecting to %s\n", server_address.c_str());
 
-  grpc::string serialized_response_proto;
-  std::multimap<grpc::string, grpc::string> client_metadata;
-  std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
-      server_trailing_metadata;
-  ParseMetadataFlag(&client_metadata);
-  PrintMetadata(client_metadata, "Sending client initial metadata:");
-  grpc::Status status = grpc::testing::CliCall::Call(
-      channel, formatted_method_name, serialized_request_proto,
-      &serialized_response_proto, client_metadata, &server_initial_metadata,
-      &server_trailing_metadata);
-  PrintMetadata(server_initial_metadata,
-                "Received initial metadata from server:");
-  PrintMetadata(server_trailing_metadata,
-                "Received trailing metadata from server:");
-  if (status.ok()) {
-    fprintf(stderr, "Rpc succeeded with OK status\n");
-    if (FLAGS_binary_output) {
-      output_ss << serialized_response_proto;
+  } else {  // parser->IsStreaming(method_name, true /* is_request */)
+    if (argc == 3) {
+      request_text = argv[2];
+      if (!FLAGS_infile.empty()) {
+        fprintf(stderr, "warning: request given in argv, ignoring --infile\n");
+      }
     } else {
-      grpc::string response_text = parser->GetTextFormatFromMethod(
-          method_name, serialized_response_proto, false /* is_request */);
+      std::stringstream input_stream;
+      if (FLAGS_infile.empty()) {
+        if (isatty(fileno(stdin))) {
+          fprintf(stderr, "reading request message from stdin...\n");
+        }
+        input_stream << std::cin.rdbuf();
+      } else {
+        std::ifstream input_file(FLAGS_infile, std::ios::in | std::ios::binary);
+        input_stream << input_file.rdbuf();
+        input_file.close();
+      }
+      request_text = input_stream.str();
+    }
+
+    if (FLAGS_binary_input) {
+      serialized_request_proto = request_text;
+      // formatted_method_name = method_name;
+    } else {
+      // formatted_method_name = parser->GetFormattedMethodName(method_name);
+      serialized_request_proto = parser->GetSerializedProtoFromMethod(
+          method_name, request_text, true /* is_request */);
       if (parser->HasError()) {
         return false;
       }
-      output_ss << "Response: \n " << response_text << std::endl;
     }
-  } else {
-    fprintf(stderr, "Rpc failed with status code %d, error message: %s\n",
-            status.error_code(), status.error_message().c_str());
-  }
+    fprintf(stderr, "connecting to %s\n", server_address.c_str());
 
-  return callback(output_ss.str());
+    grpc::string serialized_response_proto;
+    std::multimap<grpc::string, grpc::string> client_metadata;
+    std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
+        server_trailing_metadata;
+    ParseMetadataFlag(&client_metadata);
+    PrintMetadata(client_metadata, "Sending client initial metadata:");
+
+    CliCall call(channel, formatted_method_name, client_metadata);
+    call.Write(serialized_request_proto);
+    call.WritesDone();
+
+    for (bool receive_initial_metadata = true; call.Read(
+             &serialized_response_proto,
+             receive_initial_metadata ? &server_initial_metadata : nullptr);
+         receive_initial_metadata = false) {
+      if (!FLAGS_binary_output) {
+        serialized_response_proto = parser->GetTextFormatFromMethod(
+            method_name, serialized_response_proto, false /* is_request */);
+        if (parser->HasError()) {
+          return false;
+        }
+      }
+      if (receive_initial_metadata) {
+        PrintMetadata(server_initial_metadata,
+                      "Received initial metadata from server:");
+      }
+      if (!callback(serialized_response_proto)) {
+        return false;
+      }
+    }
+    Status status = call.Finish(&server_trailing_metadata);
+    if (status.ok()) {
+      fprintf(stderr, "Rpc succeeded with OK status\n");
+      return true;
+    } else {
+      fprintf(stderr, "Rpc failed with status code %d, error message: %s\n",
+              status.error_code(), status.error_message().c_str());
+      return false;
+    }
+  }
+  GPR_UNREACHABLE_CODE(return false);
 }
 
 bool GrpcTool::ParseMessage(int argc, const char** argv,
@@ -531,7 +675,7 @@
   } else {
     std::stringstream input_stream;
     if (FLAGS_infile.empty()) {
-      if (isatty(STDIN_FILENO)) {
+      if (isatty(fileno(stdin))) {
         fprintf(stderr, "reading request message from stdin...\n");
       }
       input_stream << std::cin.rdbuf();
diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc
index 33ce611..26e2b1f 100644
--- a/test/cpp/util/grpc_tool_test.cc
+++ b/test/cpp/util/grpc_tool_test.cc
@@ -102,6 +102,8 @@
 
 namespace {
 
+const int kNumResponseStreamsMsgs = 3;
+
 class TestCliCredentials final : public grpc::testing::CliCredentials {
  public:
   std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const override {
@@ -137,6 +139,71 @@
     response->set_message(request->message());
     return Status::OK;
   }
+
+  Status RequestStream(ServerContext* context,
+                       ServerReader<EchoRequest>* reader,
+                       EchoResponse* response) override {
+    EchoRequest request;
+    response->set_message("");
+    if (!context->client_metadata().empty()) {
+      for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
+               iter = context->client_metadata().begin();
+           iter != context->client_metadata().end(); ++iter) {
+        context->AddInitialMetadata(ToString(iter->first),
+                                    ToString(iter->second));
+      }
+    }
+    context->AddTrailingMetadata("trailing_key", "trailing_value");
+    while (reader->Read(&request)) {
+      response->mutable_message()->append(request.message());
+    }
+
+    return Status::OK;
+  }
+
+  Status ResponseStream(ServerContext* context, const EchoRequest* request,
+                        ServerWriter<EchoResponse>* writer) override {
+    if (!context->client_metadata().empty()) {
+      for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
+               iter = context->client_metadata().begin();
+           iter != context->client_metadata().end(); ++iter) {
+        context->AddInitialMetadata(ToString(iter->first),
+                                    ToString(iter->second));
+      }
+    }
+    context->AddTrailingMetadata("trailing_key", "trailing_value");
+
+    EchoResponse response;
+    for (int i = 0; i < kNumResponseStreamsMsgs; i++) {
+      response.set_message(request->message() + grpc::to_string(i));
+      writer->Write(response);
+    }
+
+    return Status::OK;
+  }
+
+  Status BidiStream(
+      ServerContext* context,
+      ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
+    EchoRequest request;
+    EchoResponse response;
+    if (!context->client_metadata().empty()) {
+      for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
+               iter = context->client_metadata().begin();
+           iter != context->client_metadata().end(); ++iter) {
+        context->AddInitialMetadata(ToString(iter->first),
+                                    ToString(iter->second));
+      }
+    }
+    context->AddTrailingMetadata("trailing_key", "trailing_value");
+
+    while (stream->Read(&request)) {
+      response.set_message(request.message());
+      stream->Write(response);
+    }
+
+    return Status::OK;
+  }
 };
 
 }  // namespace
@@ -347,6 +414,132 @@
   ShutdownServer();
 }
 
+TEST_F(GrpcToolTest, CallCommandRequestStream) {
+  // Test input: grpc_cli call localhost:<port> RequestStream "message:
+  // 'Hello0'"
+  std::stringstream output_stream;
+
+  const grpc::string server_address = SetUpServer();
+  const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
+                        "RequestStream", "message: 'Hello0'"};
+
+  // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
+  std::streambuf* orig = std::cin.rdbuf();
+  std::istringstream ss("message: 'Hello1'\n\n message: 'Hello2'\n\n");
+  std::cin.rdbuf(ss.rdbuf());
+
+  EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+                                   std::bind(PrintStream, &output_stream,
+                                             std::placeholders::_1)));
+
+  // Expected output: "message: \"Hello0Hello1Hello2\""
+  EXPECT_TRUE(NULL != strstr(output_stream.str().c_str(),
+                             "message: \"Hello0Hello1Hello2\""));
+  std::cin.rdbuf(orig);
+  ShutdownServer();
+}
+
+TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequest) {
+  // Test input: grpc_cli call localhost:<port> RequestStream "message:
+  // 'Hello0'"
+  std::stringstream output_stream;
+
+  const grpc::string server_address = SetUpServer();
+  const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
+                        "RequestStream", "message: 'Hello0'"};
+
+  // Mock std::cin input "bad_field: 'Hello1'\n\n message: 'Hello2'\n\n"
+  std::streambuf* orig = std::cin.rdbuf();
+  std::istringstream ss("bad_field: 'Hello1'\n\n message: 'Hello2'\n\n");
+  std::cin.rdbuf(ss.rdbuf());
+
+  EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+                                   std::bind(PrintStream, &output_stream,
+                                             std::placeholders::_1)));
+
+  // Expected output: "message: \"Hello0Hello2\""
+  EXPECT_TRUE(NULL !=
+              strstr(output_stream.str().c_str(), "message: \"Hello0Hello2\""));
+  std::cin.rdbuf(orig);
+  ShutdownServer();
+}
+
+TEST_F(GrpcToolTest, CallCommandResponseStream) {
+  // Test input: grpc_cli call localhost:<port> ResponseStream "message:
+  // 'Hello'"
+  std::stringstream output_stream;
+
+  const grpc::string server_address = SetUpServer();
+  const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
+                        "ResponseStream", "message: 'Hello'"};
+
+  EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+                                   std::bind(PrintStream, &output_stream,
+                                             std::placeholders::_1)));
+
+  // Expected output: "message: \"Hello{n}\""
+  for (int i = 0; i < kNumResponseStreamsMsgs; i++) {
+    grpc::string expected_response_text =
+        "message: \"Hello" + grpc::to_string(i) + "\"\n";
+    EXPECT_TRUE(NULL != strstr(output_stream.str().c_str(),
+                               expected_response_text.c_str()));
+  }
+
+  ShutdownServer();
+}
+
+TEST_F(GrpcToolTest, CallCommandBidiStream) {
+  // Test input: grpc_cli call localhost:<port> BidiStream "message: 'Hello0'"
+  std::stringstream output_stream;
+
+  const grpc::string server_address = SetUpServer();
+  const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
+                        "BidiStream", "message: 'Hello0'"};
+
+  // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
+  std::streambuf* orig = std::cin.rdbuf();
+  std::istringstream ss("message: 'Hello1'\n\n message: 'Hello2'\n\n");
+  std::cin.rdbuf(ss.rdbuf());
+
+  EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+                                   std::bind(PrintStream, &output_stream,
+                                             std::placeholders::_1)));
+
+  // Expected output: "message: \"Hello0\"\nmessage: \"Hello1\"\nmessage:
+  // \"Hello2\"\n\n"
+  EXPECT_TRUE(NULL != strstr(output_stream.str().c_str(),
+                             "message: \"Hello0\"\nmessage: "
+                             "\"Hello1\"\nmessage: \"Hello2\"\n"));
+  std::cin.rdbuf(orig);
+  ShutdownServer();
+}
+
+TEST_F(GrpcToolTest, CallCommandBidiStreamWithBadRequest) {
+  // Test input: grpc_cli call localhost:<port> BidiStream "message: 'Hello0'"
+  std::stringstream output_stream;
+
+  const grpc::string server_address = SetUpServer();
+  const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
+                        "BidiStream", "message: 'Hello0'"};
+
+  // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
+  std::streambuf* orig = std::cin.rdbuf();
+  std::istringstream ss("message: 1.0\n\n message: 'Hello2'\n\n");
+  std::cin.rdbuf(ss.rdbuf());
+
+  EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+                                   std::bind(PrintStream, &output_stream,
+                                             std::placeholders::_1)));
+
+  // Expected output: "message: \"Hello0\"\nmessage: \"Hello1\"\nmessage:
+  // \"Hello2\"\n\n"
+  EXPECT_TRUE(NULL != strstr(output_stream.str().c_str(),
+                             "message: \"Hello0\"\nmessage: \"Hello2\"\n"));
+  std::cin.rdbuf(orig);
+
+  ShutdownServer();
+}
+
 TEST_F(GrpcToolTest, ParseCommand) {
   // Test input "grpc_cli parse localhost:<port> grpc.testing.EchoResponse
   // ECHO_RESPONSE_MESSAGE"
diff --git a/test/cpp/util/proto_file_parser.cc b/test/cpp/util/proto_file_parser.cc
index bc8a608..5dd1b00 100644
--- a/test/cpp/util/proto_file_parser.cc
+++ b/test/cpp/util/proto_file_parser.cc
@@ -81,7 +81,8 @@
 ProtoFileParser::ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
                                  const grpc::string& proto_path,
                                  const grpc::string& protofiles)
-    : has_error_(false) {
+    : has_error_(false),
+      dynamic_factory_(new protobuf::DynamicMessageFactory()) {
   std::vector<grpc::string> service_list;
   if (channel) {
     reflection_db_.reset(new grpc::ProtoReflectionDescriptorDatabase(channel));
@@ -127,7 +128,6 @@
   }
 
   desc_pool_.reset(new protobuf::DescriptorPool(desc_db_.get()));
-  dynamic_factory_.reset(new protobuf::DynamicMessageFactory(desc_pool_.get()));
 
   for (auto it = service_list.begin(); it != service_list.end(); it++) {
     if (known_services.find(*it) == known_services.end()) {
@@ -144,6 +144,11 @@
 
 grpc::string ProtoFileParser::GetFullMethodName(const grpc::string& method) {
   has_error_ = false;
+
+  if (known_methods_.find(method) != known_methods_.end()) {
+    return known_methods_[method];
+  }
+
   const protobuf::MethodDescriptor* method_descriptor = nullptr;
   for (auto it = service_desc_list_.begin(); it != service_desc_list_.end();
        it++) {
@@ -169,6 +174,8 @@
     return "";
   }
 
+  known_methods_[method] = method_descriptor->full_name();
+
   return method_descriptor->full_name();
 }
 
@@ -205,6 +212,25 @@
                     : method_desc->output_type()->full_name();
 }
 
+bool ProtoFileParser::IsStreaming(const grpc::string& method, bool is_request) {
+  has_error_ = false;
+
+  grpc::string full_method_name = GetFullMethodName(method);
+  if (has_error_) {
+    return false;
+  }
+
+  const protobuf::MethodDescriptor* method_desc =
+      desc_pool_->FindMethodByName(full_method_name);
+  if (!method_desc) {
+    LogError("Method not found");
+    return false;
+  }
+
+  return is_request ? method_desc->client_streaming()
+                    : method_desc->server_streaming();
+}
+
 grpc::string ProtoFileParser::GetSerializedProtoFromMethod(
     const grpc::string& method, const grpc::string& text_format_proto,
     bool is_request) {
diff --git a/test/cpp/util/proto_file_parser.h b/test/cpp/util/proto_file_parser.h
index c1070a3..23d311e 100644
--- a/test/cpp/util/proto_file_parser.h
+++ b/test/cpp/util/proto_file_parser.h
@@ -84,6 +84,8 @@
       const grpc::string& message_type_name,
       const grpc::string& serialized_proto);
 
+  bool IsStreaming(const grpc::string& method, bool is_request);
+
   bool HasError() const { return has_error_; }
 
   void LogError(const grpc::string& error_msg);
@@ -104,6 +106,7 @@
   std::unique_ptr<protobuf::DynamicMessageFactory> dynamic_factory_;
   std::unique_ptr<grpc::protobuf::Message> request_prototype_;
   std::unique_ptr<grpc::protobuf::Message> response_prototype_;
+  std::unordered_map<grpc::string, grpc::string> known_methods_;
   std::vector<const protobuf::ServiceDescriptor*> service_desc_list_;
 };
 
diff --git a/third_party/gflags b/third_party/gflags
index f8a0efe..30dbc81 160000
--- a/third_party/gflags
+++ b/third_party/gflags
@@ -1 +1 @@
-Subproject commit f8a0efe03aa69b3336d8e228b37d4ccb17324b88
+Subproject commit 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e
diff --git a/third_party/gtest.BUILD b/third_party/gtest.BUILD
new file mode 100644
index 0000000..a07db65
--- /dev/null
+++ b/third_party/gtest.BUILD
@@ -0,0 +1,14 @@
+cc_library(
+    name = "gtest",
+    srcs = [
+        "src/gtest-all.cc",
+    ],
+    hdrs = glob(["include/**/*.h", "src/*.cc", "src/*.h"]),
+    includes = [
+        "include",
+    ],
+    linkstatic = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
diff --git a/third_party/nanopb/BUILD b/third_party/nanopb/BUILD
index 5709884..f9fc57f 100644
--- a/third_party/nanopb/BUILD
+++ b/third_party/nanopb/BUILD
@@ -1,4 +1,7 @@
 licenses(["notice"])
+
+exports_files(["LICENSE.txt"])
+
 package(default_visibility = ["//visibility:public"])
 
 cc_library(
diff --git a/third_party/Cronet/bidirectional_stream_c.h b/third_party/objective_c/Cronet/bidirectional_stream_c.h
similarity index 100%
rename from third_party/Cronet/bidirectional_stream_c.h
rename to third_party/objective_c/Cronet/bidirectional_stream_c.h
diff --git a/tools/buildgen/plugins/expand_filegroups.py b/tools/buildgen/plugins/expand_filegroups.py
index 477e69c..46739f8 100755
--- a/tools/buildgen/plugins/expand_filegroups.py
+++ b/tools/buildgen/plugins/expand_filegroups.py
@@ -85,7 +85,7 @@
   skips = 0
 
   while todo:
-    assert skips != len(todo), "infinite loop in filegroup uses clauses"
+    assert skips != len(todo), "infinite loop in filegroup uses clauses: %r" % [t['name'] for t in todo]
     # take the first element of the todo list
     cur = todo[0]
     todo = todo[1:]
diff --git a/tools/codegen/core/gen_header_frame.py b/tools/codegen/core/gen_header_frame.py
index ee47626..c92ff3c 100755
--- a/tools/codegen/core/gen_header_frame.py
+++ b/tools/codegen/core/gen_header_frame.py
@@ -37,8 +37,41 @@
 
 import json
 import sys
+import argparse
 
-set_end_stream = len(sys.argv) > 1 and sys.argv[1] == '--set_end_stream'
+def append_never_indexed(payload_line, n, count, key, value):
+  payload_line.append(0x10)
+  assert(len(key) <= 126)
+  payload_line.append(len(key))
+  payload_line.extend(ord(c) for c in key)
+  assert(len(value) <= 126)
+  payload_line.append(len(value))
+  payload_line.extend(ord(c) for c in value)
+
+def append_inc_indexed(payload_line, n, count, key, value):
+  payload_line.append(0x40)
+  assert(len(key) <= 126)
+  payload_line.append(len(key))
+  payload_line.extend(ord(c) for c in key)
+  assert(len(value) <= 126)
+  payload_line.append(len(value))
+  payload_line.extend(ord(c) for c in value)
+
+def append_pre_indexed(payload_line, n, count, key, value):
+  payload_line.append(0x80 + 61 + count - n)
+
+_COMPRESSORS = {
+  'never': append_never_indexed,
+  'inc': append_inc_indexed,
+  'pre': append_pre_indexed,
+}
+
+argp = argparse.ArgumentParser('Generate header frames')
+argp.add_argument('--set_end_stream', default=False, action='store_const', const=True)
+argp.add_argument('--no_framing', default=False, action='store_const', const=True)
+argp.add_argument('--compression', choices=sorted(_COMPRESSORS.keys()), default='never')
+argp.add_argument('--hex', default=False, action='store_const', const=True)
+args = argp.parse_args()
 
 # parse input, fill in vals
 vals = []
@@ -52,38 +85,37 @@
   vals.append((key, value))
 
 # generate frame payload binary data
-payload_bytes = [[]] # reserve space for header
+payload_bytes = []
+if not args.no_framing:
+  payload_bytes.append([]) # reserve space for header
 payload_len = 0
+n = 0
 for key, value in vals:
   payload_line = []
-  payload_line.append(0x10)
-  assert(len(key) <= 126)
-  payload_line.append(len(key))
-  payload_line.extend(ord(c) for c in key)
-  assert(len(value) <= 126)
-  payload_line.append(len(value))
-  payload_line.extend(ord(c) for c in value)
+  _COMPRESSORS[args.compression](payload_line, n, len(vals), key, value)
+  n += 1
   payload_len += len(payload_line)
   payload_bytes.append(payload_line)
 
 # fill in header
-flags = 0x04  # END_HEADERS
-if set_end_stream:
-  flags |= 0x01  # END_STREAM
-payload_bytes[0].extend([
-    (payload_len >> 16) & 0xff,
-    (payload_len >> 8) & 0xff,
-    (payload_len) & 0xff,
-    # header frame
-    0x01,
-    # flags
-    flags,
-    # stream id
-    0x00,
-    0x00,
-    0x00,
-    0x01
-])
+if not args.no_framing:
+  flags = 0x04  # END_HEADERS
+  if args.set_end_stream:
+    flags |= 0x01  # END_STREAM
+  payload_bytes[0].extend([
+      (payload_len >> 16) & 0xff,
+      (payload_len >> 8) & 0xff,
+      (payload_len) & 0xff,
+      # header frame
+      0x01,
+      # flags
+      flags,
+      # stream id
+      0x00,
+      0x00,
+      0x00,
+      0x01
+  ])
 
 hex_bytes = [ord(c) for c in "abcdefABCDEF0123456789"]
 
@@ -105,6 +137,11 @@
   return out + "\""
 
 # dump bytes
-for line in payload_bytes:
-  print esc_c(line)
-
+if args.hex:
+  all_bytes = []
+  for line in payload_bytes:
+    all_bytes.extend(line)
+  print '{%s}' % ', '.join('0x%02x' % c for c in all_bytes)
+else:
+  for line in payload_bytes:
+    print esc_c(line)
diff --git a/tools/codegen/core/gen_nano_proto.sh b/tools/codegen/core/gen_nano_proto.sh
index 99e4981..8600573 100755
--- a/tools/codegen/core/gen_nano_proto.sh
+++ b/tools/codegen/core/gen_nano_proto.sh
@@ -83,7 +83,7 @@
 
 # this should be the same version as the submodule we compile against
 # ideally we'd update this as a template to ensure that
-pip install protobuf==3.0.0
+pip install protobuf==3.2.0
 
 pushd "$(dirname $INPUT_PROTO)" > /dev/null
 
diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py
index cf3762d..109701f 100755
--- a/tools/codegen/core/gen_static_metadata.py
+++ b/tools/codegen/core/gen_static_metadata.py
@@ -31,8 +31,12 @@
 
 import hashlib
 import itertools
+import collections
 import os
 import sys
+import subprocess
+import re
+import perfection
 
 # configuration: a list of either strings or 2-tuples of strings
 # a single string represents a static grpc_mdstr
@@ -40,6 +44,8 @@
 # also be created)
 
 CONFIG = [
+    # metadata strings
+    'host',
     'grpc-timeout',
     'grpc-internal-encoding-request',
     'grpc-payload-bin',
@@ -48,12 +54,19 @@
     'grpc-accept-encoding',
     'user-agent',
     ':authority',
-    'host',
     'grpc-message',
     'grpc-status',
     'grpc-tracing-bin',
     'grpc-stats-bin',
     '',
+    # channel arg keys
+    'grpc.wait_for_ready',
+    'grpc.timeout',
+    'grpc.max_request_message_bytes',
+    'grpc.max_response_message_bytes',
+    # well known method names
+    '/grpc.lb.v1.LoadBalancer/BalanceLoad',
+    # metadata elements
     ('grpc-status', '0'),
     ('grpc-status', '1'),
     ('grpc-status', '2'),
@@ -110,7 +123,6 @@
     ('if-unmodified-since', ''),
     ('last-modified', ''),
     ('lb-token', ''),
-    ('lb-cost-bin', ''),
     ('link', ''),
     ('location', ''),
     ('max-forwards', ''),
@@ -130,6 +142,25 @@
     ('www-authenticate', ''),
 ]
 
+METADATA_BATCH_CALLOUTS = [
+    ':path',
+    ':method',
+    ':status',
+    ':authority',
+    ':scheme',
+    'te',
+    'grpc-message',
+    'grpc-status',
+    'grpc-payload-bin',
+    'grpc-encoding',
+    'grpc-accept-encoding',
+    'content-type',
+    'grpc-internal-encoding-request',
+    'user-agent',
+    'host',
+    'lb-token',
+]
+
 COMPRESSION_ALGORITHMS = [
     'identity',
     'deflate',
@@ -137,7 +168,7 @@
 ]
 
 # utility: mangle the name of a config
-def mangle(elem):
+def mangle(elem, name=None):
   xl = {
       '-': '_',
       ':': '',
@@ -162,10 +193,14 @@
         r += put
     if r[-1] == '_': r = r[:-1]
     return r
+  def n(default, name=name):
+    if name is None: return 'grpc_%s_' % default
+    if name == '': return ''
+    return 'grpc_%s_' % name
   if isinstance(elem, tuple):
-    return 'grpc_mdelem_%s_%s' % (m0(elem[0]), m0(elem[1]))
+    return '%s%s_%s' % (n('mdelem'), m0(elem[0]), m0(elem[1]))
   else:
-    return 'grpc_mdstr_%s' % (m0(elem))
+    return '%s%s' % (n('mdstr'), m0(elem))
 
 # utility: generate some hash value for a string
 def fake_hash(elem):
@@ -181,28 +216,37 @@
     print >>f
 
 # build a list of all the strings we need
-all_strs = set()
-all_elems = set()
+all_strs = list()
+all_elems = list()
 static_userdata = {}
+# put metadata batch callouts first, to make the check of if a static metadata
+# string is a callout trivial
+for elem in METADATA_BATCH_CALLOUTS:
+  if elem not in all_strs:
+    all_strs.append(elem)
 for elem in CONFIG:
   if isinstance(elem, tuple):
-    all_strs.add(elem[0])
-    all_strs.add(elem[1])
-    all_elems.add(elem)
+    if elem[0] not in all_strs:
+      all_strs.append(elem[0])
+    if elem[1] not in all_strs:
+      all_strs.append(elem[1])
+    if elem not in all_elems:
+      all_elems.append(elem)
   else:
-    all_strs.add(elem)
+    if elem not in all_strs:
+      all_strs.append(elem)
 compression_elems = []
 for mask in range(1, 1<<len(COMPRESSION_ALGORITHMS)):
   val = ','.join(COMPRESSION_ALGORITHMS[alg]
                  for alg in range(0, len(COMPRESSION_ALGORITHMS))
                  if (1 << alg) & mask)
   elem = ('grpc-accept-encoding', val)
-  all_strs.add(val)
-  all_elems.add(elem)
+  if val not in all_strs:
+    all_strs.append(val)
+  if elem not in all_elems:
+    all_elems.append(elem)
   compression_elems.append(elem)
   static_userdata[elem] = 1 + (mask | 1)
-all_strs = sorted(list(all_strs), key=mangle)
-all_elems = sorted(list(all_elems), key=mangle)
 
 # output configuration
 args = sys.argv[1:]
@@ -279,15 +323,52 @@
 
 print >>C, '#include "src/core/lib/transport/static_metadata.h"'
 print >>C
+print >>C, '#include "src/core/lib/slice/slice_internal.h"'
+print >>C
+
+str_ofs = 0
+id2strofs = {}
+for i, elem in enumerate(all_strs):
+  id2strofs[i] = str_ofs
+  str_ofs += len(elem);
+def slice_def(i):
+  return '{.refcount = &grpc_static_metadata_refcounts[%d], .data.refcounted = {g_bytes+%d, %d}}' % (i, id2strofs[i], len(all_strs[i]))
+
+# validate configuration
+for elem in METADATA_BATCH_CALLOUTS:
+  assert elem in all_strs
 
 print >>H, '#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs)
-print >>H, 'extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];'
+print >>H, 'extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];'
 for i, elem in enumerate(all_strs):
   print >>H, '/* "%s" */' % elem
-  print >>H, '#define %s (&grpc_static_mdstr_table[%d])' % (mangle(elem).upper(), i)
+  print >>H, '#define %s (grpc_static_slice_table[%d])' % (mangle(elem).upper(), i)
 print >>H
-print >>C, 'grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT];'
+print >>C, 'static uint8_t g_bytes[] = {%s};' % (','.join('%d' % ord(c) for c in ''.join(all_strs)))
 print >>C
+print >>C, 'static void static_ref(void *unused) {}'
+print >>C, 'static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}'
+print >>C, 'static const grpc_slice_refcount_vtable static_sub_vtable = {static_ref, static_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl};';
+print >>H, 'extern const grpc_slice_refcount_vtable grpc_static_metadata_vtable;';
+print >>C, 'const grpc_slice_refcount_vtable grpc_static_metadata_vtable = {static_ref, static_unref, grpc_static_slice_eq, grpc_static_slice_hash};';
+print >>C, 'static grpc_slice_refcount static_sub_refcnt = {&static_sub_vtable, &static_sub_refcnt};';
+print >>H, 'extern grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT];'
+print >>C, 'grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = {'
+for i, elem in enumerate(all_strs):
+  print >>C, '  {&grpc_static_metadata_vtable, &static_sub_refcnt},'
+print >>C, '};'
+print >>C
+print >>H, '#define GRPC_IS_STATIC_METADATA_STRING(slice) \\'
+print >>H, '  ((slice).refcount != NULL && (slice).refcount->vtable == &grpc_static_metadata_vtable)'
+print >>H
+print >>C, 'const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {'
+for i, elem in enumerate(all_strs):
+  print >>C, slice_def(i) + ','
+print >>C, '};'
+print >>C
+print >>H, '#define GRPC_STATIC_METADATA_INDEX(static_slice) \\'
+print >>H, '  ((int)((static_slice).refcount - grpc_static_metadata_refcounts))'
+print >>H
 
 print >>D, '# hpack fuzzing dictionary'
 for i, elem in enumerate(all_strs):
@@ -297,13 +378,12 @@
                               [len(elem[1])] + [ord(c) for c in elem[1]]))
 
 print >>H, '#define GRPC_STATIC_MDELEM_COUNT %d' % len(all_elems)
-print >>H, 'extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];'
+print >>H, 'extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];'
 print >>H, 'extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];'
 for i, elem in enumerate(all_elems):
   print >>H, '/* "%s": "%s" */' % elem
-  print >>H, '#define %s (&grpc_static_mdelem_table[%d])' % (mangle(elem).upper(), i)
+  print >>H, '#define %s (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[%d], GRPC_MDELEM_STORAGE_STATIC))' % (mangle(elem).upper(), i)
 print >>H
-print >>C, 'grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];'
 print >>C, 'uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {'
 print >>C, '  %s' % ','.join('%d' % static_userdata.get(elem, 0) for elem in all_elems)
 print >>C, '};'
@@ -319,25 +399,100 @@
     if m == m2:
       return i
 
-print >>H, 'extern const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT*2];'
-print >>C, 'const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT*2] = {'
-print >>C, ','.join('%d' % str_idx(x) for x in itertools.chain.from_iterable([a,b] for a, b in all_elems))
-print >>C, '};'
+def offset_trials(mink):
+  yield 0
+  for i in range(1, 100):
+    for mul in [-1, 1]:
+      yield mul * i
+
+def perfect_hash(keys, name):
+  p = perfection.hash_parameters(keys)
+  def f(i, p=p):
+    i += p.offset
+    x = i % p.t
+    y = i / p.t
+    return x + p.r[y]
+  return {
+    'PHASHRANGE': p.t - 1 + max(p.r),
+    'PHASHNKEYS': len(p.slots),
+    'pyfunc': f,
+    'code': """
+static const int8_t %(name)s_r[] = {%(r)s};
+static uint32_t %(name)s_phash(uint32_t i) {
+  i %(offset_sign)s= %(offset)d;
+  uint32_t x = i %% %(t)d;
+  uint32_t y = i / %(t)d;
+  uint32_t h = x;
+  if (y < GPR_ARRAY_SIZE(%(name)s_r)) {
+    uint32_t delta = (uint32_t)%(name)s_r[y];
+    h += delta;
+  }
+  return h;
+}
+    """ % {
+      'name': name,
+      'r': ','.join('%d' % (r if r is not None else 0) for r in p.r),
+      't': p.t,
+      'offset': abs(p.offset),
+      'offset_sign': '+' if p.offset > 0 else '-'
+    }
+  }
+
+
+elem_keys = [str_idx(elem[0]) * len(all_strs) + str_idx(elem[1]) for elem in all_elems]
+elem_hash = perfect_hash(elem_keys, "elems")
+print >>C, elem_hash['code']
+
+keys = [0] * int(elem_hash['PHASHRANGE'])
+idxs = [255] * int(elem_hash['PHASHNKEYS'])
+for i, k in enumerate(elem_keys):
+    h = elem_hash['pyfunc'](k)
+    assert keys[h] == 0
+    keys[h] = k
+    idxs[h] = i
+print >>C, 'static const uint16_t elem_keys[] = {%s};' % ','.join('%d' % k for k in keys)
+print >>C, 'static const uint8_t elem_idxs[] = {%s};' % ','.join('%d' % i for i in idxs)
 print >>C
 
-print >>H, 'extern const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT];'
-print >>C, 'const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = {'
-print >>C, '%s' % ',\n'.join('  "%s"' % s for s in all_strs)
-print >>C, '};'
+print >>H, 'grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b);'
+print >>C, 'grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) {'
+print >>C, '  if (a == -1 || b == -1) return GRPC_MDNULL;'
+print >>C, '  uint32_t k = (uint32_t)(a * %d + b);' % len(all_strs)
+print >>C, '  uint32_t h = elems_phash(k);'
+print >>C, '  return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k ? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[elem_idxs[h]], GRPC_MDELEM_STORAGE_STATIC) : GRPC_MDNULL;'
+print >>C, '}'
 print >>C
 
+print >>C, 'grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {'
+for a, b in all_elems:
+  print >>C, '{%s,%s},' % (slice_def(str_idx(a)), slice_def(str_idx(b)))
+print >>C, '};'
+
+print >>H, 'typedef enum {'
+for elem in METADATA_BATCH_CALLOUTS:
+  print >>H, '  %s,' % mangle(elem, 'batch').upper()
+print >>H, '  GRPC_BATCH_CALLOUTS_COUNT'
+print >>H, '} grpc_metadata_batch_callouts_index;'
+print >>H
+print >>H, 'typedef union {'
+print >>H, '  struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT];'
+print >>H, '  struct {'
+for elem in METADATA_BATCH_CALLOUTS:
+  print >>H, '  struct grpc_linked_mdelem *%s;' % mangle(elem, '').lower()
+print >>H, '  } named;'
+print >>H, '} grpc_metadata_batch_callouts;'
+print >>H
+print >>H, '#define GRPC_BATCH_INDEX_OF(slice) \\'
+print >>H, '  (GRPC_IS_STATIC_METADATA_STRING((slice)) ? (grpc_metadata_batch_callouts_index)GPR_CLAMP(GRPC_STATIC_METADATA_INDEX((slice)), 0, GRPC_BATCH_CALLOUTS_COUNT) : GRPC_BATCH_CALLOUTS_COUNT)'
+print >>H
+
 print >>H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (1 << len(COMPRESSION_ALGORITHMS))
 print >>C, 'const uint8_t grpc_static_accept_encoding_metadata[%d] = {' % (1 << len(COMPRESSION_ALGORITHMS))
 print >>C, '0,%s' % ','.join('%d' % md_idx(elem) for elem in compression_elems)
 print >>C, '};'
 print >>C
 
-print >>H, '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) (&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]])'
+print >>H, '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]], GRPC_MDELEM_STORAGE_STATIC))'
 
 print >>H, '#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */'
 
diff --git a/tools/distrib/check_copyright.py b/tools/distrib/check_copyright.py
index c993407..611a9f4 100755
--- a/tools/distrib/check_copyright.py
+++ b/tools/distrib/check_copyright.py
@@ -106,6 +106,8 @@
 
   'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
   'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
+  'src/cpp/server/health/health.pb.h',
+  'src/cpp/server/health/health.pb.c',
 
   # An older file originally from outside gRPC.
   'src/php/tests/bootstrap.php',
diff --git a/tools/distrib/pylint_code.sh b/tools/distrib/pylint_code.sh
new file mode 100755
index 0000000..6369e60
--- /dev/null
+++ b/tools/distrib/pylint_code.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+# change to root directory
+cd $(dirname $0)/../..
+
+DIRS=src/python/grpcio/grpc
+
+VIRTUALENV=python_pylint_venv
+
+virtualenv $VIRTUALENV
+PYTHON=`realpath $VIRTUALENV/bin/python`
+$PYTHON -m pip install pylint==1.6.5
+
+for dir in $DIRS; do
+  $PYTHON -m pylint --rcfile=.pylintrc -rn $dir || exit $?
+done
+
+exit 0
diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py
index d0ee8a0..263785b 100644
--- a/tools/distrib/python/grpcio_tools/grpc_version.py
+++ b/tools/distrib/python/grpcio_tools/grpc_version.py
@@ -29,4 +29,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!!
 
-VERSION='1.1.2'
+VERSION='1.2.0.dev0'
diff --git a/tools/distrib/yapf_code.sh b/tools/distrib/yapf_code.sh
index 030412e..007b148 100755
--- a/tools/distrib/yapf_code.sh
+++ b/tools/distrib/yapf_code.sh
@@ -53,7 +53,7 @@
   tempdir=`mktemp -d`
   cp -RT $dir $tempdir
   $PYTHON -m yapf -i -r -p $exclusion_args $dir
-  if ! diff -rq $dir $tempdir; then
+  if ! diff -r $dir $tempdir; then
     script_result=1
   fi
   rm -rf $tempdir
diff --git a/tools/dockerfile/push_testing_images.sh b/tools/dockerfile/push_testing_images.sh
index f1ee8d5..9dceb29 100755
--- a/tools/dockerfile/push_testing_images.sh
+++ b/tools/dockerfile/push_testing_images.sh
@@ -44,7 +44,7 @@
 
 DOCKERHUB_ORGANIZATION=grpctesting
 
-for DOCKERFILE_DIR in tools/dockerfile/test/fuzzer
+for DOCKERFILE_DIR in tools/dockerfile/test/fuzzer tools/dockerfile/test/sanity
 do
   # Generate image name based on Dockerfile checksum. That works well as long
   # as can count on dockerfiles being written in a way that changing the logical 
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index bb7da0a..551ba46 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -40,7 +40,7 @@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.1.2
+PROJECT_NUMBER         = 1.2.0-dev
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -795,9 +795,11 @@
 include/grpc++/completion_queue.h \
 include/grpc++/create_channel.h \
 include/grpc++/create_channel_posix.h \
+include/grpc++/ext/health_check_service_server_builder_option.h \
 include/grpc++/generic/async_generic_service.h \
 include/grpc++/generic/generic_stub.h \
 include/grpc++/grpc++.h \
+include/grpc++/health_check_service_interface.h \
 include/grpc++/impl/call.h \
 include/grpc++/impl/client_unary_call.h \
 include/grpc++/impl/codegen/async_stream.h \
@@ -810,11 +812,14 @@
 include/grpc++/impl/codegen/completion_queue.h \
 include/grpc++/impl/codegen/completion_queue_tag.h \
 include/grpc++/impl/codegen/config.h \
+include/grpc++/impl/codegen/config_protobuf.h \
 include/grpc++/impl/codegen/core_codegen.h \
 include/grpc++/impl/codegen/core_codegen_interface.h \
 include/grpc++/impl/codegen/create_auth_context.h \
 include/grpc++/impl/codegen/grpc_library.h \
+include/grpc++/impl/codegen/metadata_map.h \
 include/grpc++/impl/codegen/method_handler_impl.h \
+include/grpc++/impl/codegen/proto_utils.h \
 include/grpc++/impl/codegen/rpc_method.h \
 include/grpc++/impl/codegen/rpc_service_method.h \
 include/grpc++/impl/codegen/security/auth_context.h \
@@ -822,6 +827,7 @@
 include/grpc++/impl/codegen/server_context.h \
 include/grpc++/impl/codegen/server_interface.h \
 include/grpc++/impl/codegen/service_type.h \
+include/grpc++/impl/codegen/slice.h \
 include/grpc++/impl/codegen/status.h \
 include/grpc++/impl/codegen/status_code_enum.h \
 include/grpc++/impl/codegen/status_helper.h \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index caba0b2..0d7ddfc 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -40,7 +40,7 @@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.1.2
+PROJECT_NUMBER         = 1.2.0-dev
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -795,9 +795,11 @@
 include/grpc++/completion_queue.h \
 include/grpc++/create_channel.h \
 include/grpc++/create_channel_posix.h \
+include/grpc++/ext/health_check_service_server_builder_option.h \
 include/grpc++/generic/async_generic_service.h \
 include/grpc++/generic/generic_stub.h \
 include/grpc++/grpc++.h \
+include/grpc++/health_check_service_interface.h \
 include/grpc++/impl/call.h \
 include/grpc++/impl/client_unary_call.h \
 include/grpc++/impl/codegen/async_stream.h \
@@ -810,12 +812,15 @@
 include/grpc++/impl/codegen/completion_queue.h \
 include/grpc++/impl/codegen/completion_queue_tag.h \
 include/grpc++/impl/codegen/config.h \
+include/grpc++/impl/codegen/config_protobuf.h \
 include/grpc++/impl/codegen/core_codegen.h \
 include/grpc++/impl/codegen/core_codegen.h \
 include/grpc++/impl/codegen/core_codegen_interface.h \
 include/grpc++/impl/codegen/create_auth_context.h \
 include/grpc++/impl/codegen/grpc_library.h \
+include/grpc++/impl/codegen/metadata_map.h \
 include/grpc++/impl/codegen/method_handler_impl.h \
+include/grpc++/impl/codegen/proto_utils.h \
 include/grpc++/impl/codegen/rpc_method.h \
 include/grpc++/impl/codegen/rpc_service_method.h \
 include/grpc++/impl/codegen/security/auth_context.h \
@@ -823,6 +828,7 @@
 include/grpc++/impl/codegen/server_context.h \
 include/grpc++/impl/codegen/server_interface.h \
 include/grpc++/impl/codegen/service_type.h \
+include/grpc++/impl/codegen/slice.h \
 include/grpc++/impl/codegen/status.h \
 include/grpc++/impl/codegen/status_code_enum.h \
 include/grpc++/impl/codegen/status_helper.h \
@@ -909,6 +915,12 @@
 src/cpp/server/create_default_thread_pool.cc \
 src/cpp/server/dynamic_thread_pool.cc \
 src/cpp/server/dynamic_thread_pool.h \
+src/cpp/server/health/default_health_check_service.cc \
+src/cpp/server/health/default_health_check_service.h \
+src/cpp/server/health/health.pb.c \
+src/cpp/server/health/health.pb.h \
+src/cpp/server/health/health_check_service.cc \
+src/cpp/server/health/health_check_service_server_builder_option.cc \
 src/cpp/server/insecure_server_credentials.cc \
 src/cpp/server/secure_server_credentials.cc \
 src/cpp/server/secure_server_credentials.h \
diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core
index 7770f84..896ee02 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -40,7 +40,7 @@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 2.0.0
+PROJECT_NUMBER         = 3.0.0-dev
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -827,6 +827,7 @@
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
+include/grpc/load_reporting.h \
 include/grpc/slice.h \
 include/grpc/slice_buffer.h \
 include/grpc/status.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 6e2eed8..04fd7be 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -40,7 +40,7 @@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 2.0.0
+PROJECT_NUMBER         = 3.0.0-dev
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -827,6 +827,7 @@
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.h \
+include/grpc/load_reporting.h \
 include/grpc/slice.h \
 include/grpc/slice_buffer.h \
 include/grpc/status.h \
@@ -884,7 +885,12 @@
 src/core/ext/census/rpc_metric_id.h \
 src/core/ext/census/trace_context.c \
 src/core/ext/census/trace_context.h \
+src/core/ext/census/trace_label.h \
+src/core/ext/census/trace_propagation.h \
+src/core/ext/census/trace_status.h \
+src/core/ext/census/trace_string.h \
 src/core/ext/census/tracing.c \
+src/core/ext/census/tracing.h \
 src/core/ext/client_channel/README.md \
 src/core/ext/client_channel/channel_connectivity.c \
 src/core/ext/client_channel/client_channel.c \
@@ -897,6 +903,8 @@
 src/core/ext/client_channel/default_initial_connect_string.c \
 src/core/ext/client_channel/http_connect_handshaker.c \
 src/core/ext/client_channel/http_connect_handshaker.h \
+src/core/ext/client_channel/http_proxy.c \
+src/core/ext/client_channel/http_proxy.h \
 src/core/ext/client_channel/initial_connect_string.c \
 src/core/ext/client_channel/initial_connect_string.h \
 src/core/ext/client_channel/lb_policy.c \
@@ -907,6 +915,10 @@
 src/core/ext/client_channel/lb_policy_registry.h \
 src/core/ext/client_channel/parse_address.c \
 src/core/ext/client_channel/parse_address.h \
+src/core/ext/client_channel/proxy_mapper.c \
+src/core/ext/client_channel/proxy_mapper.h \
+src/core/ext/client_channel/proxy_mapper_registry.c \
+src/core/ext/client_channel/proxy_mapper_registry.h \
 src/core/ext/client_channel/resolver.c \
 src/core/ext/client_channel/resolver.h \
 src/core/ext/client_channel/resolver_factory.c \
@@ -921,6 +933,8 @@
 src/core/ext/client_channel/uri_parser.h \
 src/core/ext/lb_policy/grpclb/grpclb.c \
 src/core/ext/lb_policy/grpclb/grpclb.h \
+src/core/ext/lb_policy/grpclb/grpclb_channel.h \
+src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c \
 src/core/ext/lb_policy/grpclb/load_balancer_api.c \
 src/core/ext/lb_policy/grpclb/load_balancer_api.h \
 src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
@@ -981,15 +995,12 @@
 src/core/ext/transport/chttp2/transport/hpack_parser.h \
 src/core/ext/transport/chttp2/transport/hpack_table.c \
 src/core/ext/transport/chttp2/transport/hpack_table.h \
-src/core/ext/transport/chttp2/transport/http2_errors.h \
 src/core/ext/transport/chttp2/transport/huffsyms.c \
 src/core/ext/transport/chttp2/transport/huffsyms.h \
 src/core/ext/transport/chttp2/transport/incoming_metadata.c \
 src/core/ext/transport/chttp2/transport/incoming_metadata.h \
 src/core/ext/transport/chttp2/transport/internal.h \
 src/core/ext/transport/chttp2/transport/parsing.c \
-src/core/ext/transport/chttp2/transport/status_conversion.c \
-src/core/ext/transport/chttp2/transport/status_conversion.h \
 src/core/ext/transport/chttp2/transport/stream_lists.c \
 src/core/ext/transport/chttp2/transport/stream_map.c \
 src/core/ext/transport/chttp2/transport/stream_map.h \
@@ -1049,6 +1060,7 @@
 src/core/lib/iomgr/endpoint_pair_windows.c \
 src/core/lib/iomgr/error.c \
 src/core/lib/iomgr/error.h \
+src/core/lib/iomgr/error_internal.h \
 src/core/lib/iomgr/ev_epoll_linux.c \
 src/core/lib/iomgr/ev_epoll_linux.h \
 src/core/lib/iomgr/ev_poll_posix.c \
@@ -1187,6 +1199,8 @@
 src/core/lib/security/credentials/ssl/ssl_credentials.h \
 src/core/lib/security/transport/auth_filters.h \
 src/core/lib/security/transport/client_auth_filter.c \
+src/core/lib/security/transport/lb_targets_info.c \
+src/core/lib/security/transport/lb_targets_info.h \
 src/core/lib/security/transport/secure_endpoint.c \
 src/core/lib/security/transport/secure_endpoint.h \
 src/core/lib/security/transport/security_connector.c \
@@ -1204,6 +1218,9 @@
 src/core/lib/slice/percent_encoding.h \
 src/core/lib/slice/slice.c \
 src/core/lib/slice/slice_buffer.c \
+src/core/lib/slice/slice_hash_table.c \
+src/core/lib/slice/slice_hash_table.h \
+src/core/lib/slice/slice_intern.c \
 src/core/lib/slice/slice_internal.h \
 src/core/lib/slice/slice_string_helpers.c \
 src/core/lib/slice/slice_string_helpers.h \
@@ -1232,6 +1249,7 @@
 src/core/lib/support/mpscq.h \
 src/core/lib/support/murmur_hash.c \
 src/core/lib/support/murmur_hash.h \
+src/core/lib/support/spinlock.h \
 src/core/lib/support/stack_lockfree.c \
 src/core/lib/support/stack_lockfree.h \
 src/core/lib/support/string.c \
@@ -1291,14 +1309,18 @@
 src/core/lib/surface/server.c \
 src/core/lib/surface/server.h \
 src/core/lib/surface/validate_metadata.c \
+src/core/lib/surface/validate_metadata.h \
 src/core/lib/surface/version.c \
 src/core/lib/transport/README.md \
+src/core/lib/transport/bdp_estimator.c \
+src/core/lib/transport/bdp_estimator.h \
 src/core/lib/transport/byte_stream.c \
 src/core/lib/transport/byte_stream.h \
 src/core/lib/transport/connectivity_state.c \
 src/core/lib/transport/connectivity_state.h \
-src/core/lib/transport/mdstr_hash_table.c \
-src/core/lib/transport/mdstr_hash_table.h \
+src/core/lib/transport/error_utils.c \
+src/core/lib/transport/error_utils.h \
+src/core/lib/transport/http2_errors.h \
 src/core/lib/transport/metadata.c \
 src/core/lib/transport/metadata.h \
 src/core/lib/transport/metadata_batch.c \
@@ -1309,6 +1331,8 @@
 src/core/lib/transport/service_config.h \
 src/core/lib/transport/static_metadata.c \
 src/core/lib/transport/static_metadata.h \
+src/core/lib/transport/status_conversion.c \
+src/core/lib/transport/status_conversion.h \
 src/core/lib/transport/timeout_encoding.c \
 src/core/lib/transport/timeout_encoding.h \
 src/core/lib/transport/transport.c \
diff --git a/tools/internal_ci/linux/grpc_fuzzer_api.cfg b/tools/internal_ci/linux/grpc_fuzzer_api.cfg
index a34fb9d..5c2592e 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_api.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_api.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_api.sh b/tools/internal_ci/linux/grpc_fuzzer_api.sh
index c3cf110..edf8843 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_api.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_api.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -38,4 +38,4 @@
 # download fuzzer docker image from dockerhub
 export DOCKERHUB_ORGANIZATION=grpctesting
 # runtime 23 * 60 mins
-config=asan-trace-cmp runtime=86400 tools/jenkins/run_fuzzer.sh api_fuzzer
+config=asan-trace-cmp runtime=82800 tools/jenkins/run_fuzzer.sh api_fuzzer
diff --git a/tools/internal_ci/linux/grpc_fuzzer_client.cfg b/tools/internal_ci/linux/grpc_fuzzer_client.cfg
index b1bce02..1e8f688 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_client.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_client.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_client.sh b/tools/internal_ci/linux/grpc_fuzzer_client.sh
index f9ff13d..c03f925 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_client.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_client.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg
index 215ce2b..72482b6 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh
index d9a73a6..43933e6 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,5 @@
 
 # download fuzzer docker image from dockerhub
 export DOCKERHUB_ORGANIZATION=grpctesting
-# runtime 23 * 60 mins
 config=asan-trace-cmp tools/jenkins/run_fuzzer.sh hpack_parser_fuzzer_test
 
diff --git a/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg b/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg
index 120e8f8..a4a0e89 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_http_request.sh b/tools/internal_ci/linux/grpc_fuzzer_http_request.sh
index d412d92..ef975d3 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_http_request.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_http_request.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,5 @@
 
 # download fuzzer docker image from dockerhub
 export DOCKERHUB_ORGANIZATION=grpctesting
-# runtime 23 * 60 mins
 config=asan-trace-cmp tools/jenkins/run_fuzzer.sh http_request_fuzzer_test
 
diff --git a/tools/internal_ci/linux/grpc_fuzzer_json.cfg b/tools/internal_ci/linux/grpc_fuzzer_json.cfg
index cab4f29..d22da2d 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_json.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_json.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_json.sh b/tools/internal_ci/linux/grpc_fuzzer_json.sh
index d9869f6..1e64a02 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_json.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_json.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,5 @@
 
 # download fuzzer docker image from dockerhub
 export DOCKERHUB_ORGANIZATION=grpctesting
-# runtime 23 * 60 mins
 config=asan-trace-cmp tools/jenkins/run_fuzzer.sh json_fuzzer_test
 
diff --git a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg
index c73aa81..cbf44ba 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
index 0a7187f..6e7f4b7 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -37,5 +37,4 @@
 
 # download fuzzer docker image from dockerhub
 export DOCKERHUB_ORGANIZATION=grpctesting
-# runtime 23 * 60 mins
 config=asan-trace-cmp tools/jenkins/run_fuzzer.sh nanopb_fuzzer_response_test
diff --git a/tools/internal_ci/linux/grpc_fuzzer_server.cfg b/tools/internal_ci/linux/grpc_fuzzer_server.cfg
index a1931cb..7877d51 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_server.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_server.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_server.sh b/tools/internal_ci/linux/grpc_fuzzer_server.sh
index e00e940..82b24b0 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_server.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_server.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -38,4 +38,4 @@
 # download fuzzer docker image from dockerhub
 export DOCKERHUB_ORGANIZATION=grpctesting
 # runtime 23 * 60 mins
-config=asan-trace-cmp runtime=86400 tools/jenkins/run_fuzzer.sh server_fuzzer
+config=asan-trace-cmp runtime=82800 tools/jenkins/run_fuzzer.sh server_fuzzer
diff --git a/tools/internal_ci/linux/grpc_fuzzer_uri.cfg b/tools/internal_ci/linux/grpc_fuzzer_uri.cfg
index c312ae0..134b3d0 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_uri.cfg
+++ b/tools/internal_ci/linux/grpc_fuzzer_uri.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/tools/internal_ci/linux/grpc_fuzzer_uri.sh b/tools/internal_ci/linux/grpc_fuzzer_uri.sh
index 4137f80..67039f3 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_uri.sh
+++ b/tools/internal_ci/linux/grpc_fuzzer_uri.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -37,5 +37,4 @@
 
 # download fuzzer docker image from dockerhub
 export DOCKERHUB_ORGANIZATION=grpctesting
-# runtime 23 * 60 mins
 config=asan-trace-cmp tools/jenkins/run_fuzzer.sh uri_fuzzer_test
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg b/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
new file mode 100644
index 0000000..e521b08
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
@@ -0,0 +1,40 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_interop_badserver_java.sh"
+# grpc_interop tests can take 6+ hours to complete.
+timeout_mins: 480
+action {
+  define_artifacts {
+    regex: "**/report.xml"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.sh b/tools/internal_ci/linux/grpc_interop_badserver_java.sh
new file mode 100755
index 0000000..0985e65
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_badserver_java.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+export LANG=en_US.UTF-8
+
+# Enter the gRPC repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+tools/run_tests/run_interop_tests.py -l java --use_docker --http2_badserver_interop $@
+
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.cfg b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
new file mode 100644
index 0000000..940f760
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
@@ -0,0 +1,40 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_interop_badserver_python.sh"
+# grpc_interop tests can take 6+ hours to complete.
+timeout_mins: 480
+action {
+  define_artifacts {
+    regex: "**/report.xml"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.sh b/tools/internal_ci/linux/grpc_interop_badserver_python.sh
new file mode 100755
index 0000000..3fff537
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_badserver_python.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+export LANG=en_US.UTF-8
+
+# Enter the gRPC repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+tools/run_tests/run_interop_tests.py -l python --use_docker --http2_badserver_interop $@
+
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.cfg b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
new file mode 100644
index 0000000..2b53644
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
@@ -0,0 +1,40 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_interop_tocloud.sh"
+# grpc_interop tests can take 6+ hours to complete.
+timeout_mins: 480
+action {
+  define_artifacts {
+    regex: "**/report.xml"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.sh b/tools/internal_ci/linux/grpc_interop_tocloud.sh
new file mode 100755
index 0000000..572001d
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_interop_tocloud.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+export LANG=en_US.UTF-8
+
+# Enter the gRPC repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+tools/run_tests/run_interop_tests.py -l all -s all --use_docker --http2_interop -t -j 12 $@
diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/grpc_master.cfg
index 8ce2ef1..7536a91 100644
--- a/tools/internal_ci/linux/grpc_master.cfg
+++ b/tools/internal_ci/linux/grpc_master.cfg
@@ -1,5 +1,4 @@
-#!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -32,7 +31,7 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/linux/grpc_master.sh"
-timeout_mins: 60
+timeout_mins: 240
 action {
   define_artifacts {
     regex: "**/sponge_log.xml"
diff --git a/tools/internal_ci/linux/grpc_master.sh b/tools/internal_ci/linux/grpc_master.sh
index ea77d11..d01d637 100755
--- a/tools/internal_ci/linux/grpc_master.sh
+++ b/tools/internal_ci/linux/grpc_master.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright 2016, Google Inc.
+# Copyright 2017, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,9 @@
 clang --version || true
 docker --version || true
 
+# Need to increase open files limit for c tests
+ulimit -n 2000
+
 git submodule update --init
 
 tools/run_tests/run_tests.py -l c -t -x sponge_log.xml || FAILED="true"
diff --git a/tools/internal_ci/linux/grpc_portability_build_only.cfg b/tools/internal_ci/linux/grpc_portability_build_only.cfg
new file mode 100644
index 0000000..ce5be5a
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_portability_build_only.cfg
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_portability_build_only.sh"
+timeout_mins: 180
+action {
+  define_artifacts {
+    regex: "**report**.xml"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_portability_build_only.sh b/tools/internal_ci/linux/grpc_portability_build_only.sh
new file mode 100644
index 0000000..ebdc0e8
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_portability_build_only.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+# download docker images from dockerhub
+export DOCKERHUB_ORGANIZATION=grpctesting
+
+tools/jenkins/run_jenkins_matrix.sh -f portability linux --build_only
diff --git a/tools/internal_ci/linux/grpc_pull_request_sanity.cfg b/tools/internal_ci/linux/grpc_pull_request_sanity.cfg
new file mode 100644
index 0000000..511f2d6
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_pull_request_sanity.cfg
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/grpc_sanity.sh"
+timeout_mins: 30
+action {
+  define_artifacts {
+    regex: "**/sponge_log.xml"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_sanity.sh b/tools/internal_ci/linux/grpc_sanity.sh
new file mode 100755
index 0000000..fac25c7
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_sanity.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+# download base docker image from dockerhub
+export DOCKERHUB_ORGANIZATION=grpctesting
+tools/run_tests/run_tests.py -l sanity -c opt -t -x sponge_log.xml --use_docker --report_suite_name sanity_linux_opt
diff --git a/tools/internal_ci/windows/grpc_master.bat b/tools/internal_ci/windows/grpc_master.bat
new file mode 100644
index 0000000..4041c50
--- /dev/null
+++ b/tools/internal_ci/windows/grpc_master.bat
@@ -0,0 +1,44 @@
+@rem Copyright 2017, Google Inc.
+@rem All rights reserved.
+@rem
+@rem Redistribution and use in source and binary forms, with or without
+@rem modification, are permitted provided that the following conditions are
+@rem met:
+@rem
+@rem     * Redistributions of source code must retain the above copyright
+@rem notice, this list of conditions and the following disclaimer.
+@rem     * Redistributions in binary form must reproduce the above
+@rem copyright notice, this list of conditions and the following disclaimer
+@rem in the documentation and/or other materials provided with the
+@rem distribution.
+@rem     * Neither the name of Google Inc. nor the names of its
+@rem contributors may be used to endorse or promote products derived from
+@rem this software without specific prior written permission.
+@rem
+@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+setlocal
+
+@rem enter repo root
+cd /d %~dp0\..\..\..
+
+git submodule update --init
+
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x c_windows_dbg_sponge_log.xml --report_suite_name c_windows_dbg -l c -c dbg
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x c_windows_opt_sponge_log.xml --report_suite_name c_windows_opt -l c -c opt
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x csharp_windows_dbg_sponge_log.xml --report_suite_name csharp_windows_dbg -l csharp -c dbg
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x csharp_windows_opt_sponge_log.xml --report_suite_name csharp_windows_opt -l csharp -c opt
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x node_windows_dbg_sponge_log.xml --report_suite_name node_windows_dbg -l node -c dbg
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x node_windows_opt_sponge_log.xml --report_suite_name node_windows_opt -l node -c opt
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x python_windows_dbg_sponge_log.xml --report_suite_name python_windows_dbg -l python -c dbg
+sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x python_windows_opt_sponge_log.xml --report_suite_name python_windows_opt -l python -c opt
diff --git a/tools/internal_ci/windows/grpc_master.cfg b/tools/internal_ci/windows/grpc_master.cfg
new file mode 100644
index 0000000..f90af11
--- /dev/null
+++ b/tools/internal_ci/windows/grpc_master.cfg
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/windows/grpc_master.bat"
+timeout_mins: 360
+action {
+  define_artifacts {
+    regex: "**sponge_log.xml"
+  }
+}
diff --git a/tools/jenkins/run_interop.sh b/tools/jenkins/run_interop.sh
index 4a7bff3..2a9fc66 100755
--- a/tools/jenkins/run_interop.sh
+++ b/tools/jenkins/run_interop.sh
@@ -36,4 +36,4 @@
 # Enter the gRPC repo root
 cd $(dirname $0)/../..
 
-tools/run_tests/run_interop_tests.py -l all -s all --cloud_to_prod --cloud_to_prod_auth --use_docker --http2_interop -t -j 12 $@ || true
+tools/run_tests/run_interop_tests.py -l all -s all --cloud_to_prod --cloud_to_prod_auth --use_docker --http2_interop --http2_badserver_interop -t -j 12 $@ || true
diff --git a/tools/profiling/latency_profile/profile_analyzer.py b/tools/profiling/latency_profile/profile_analyzer.py
index 48b8e9b..2087cd2 100755
--- a/tools/profiling/latency_profile/profile_analyzer.py
+++ b/tools/profiling/latency_profile/profile_analyzer.py
@@ -34,6 +34,7 @@
 import itertools
 import json
 import math
+import sys
 import tabulate
 import time
 
@@ -49,6 +50,7 @@
 argp = argparse.ArgumentParser(description='Process output of basic_prof builds')
 argp.add_argument('--source', default='latency_trace.txt', type=str)
 argp.add_argument('--fmt', choices=tabulate.tabulate_formats, default='simple')
+argp.add_argument('--out', default='-', type=str)
 args = argp.parse_args()
 
 class LineItem(object):
@@ -246,16 +248,20 @@
   ('TO_SCOPE_END', time_format(TIME_TO_SCOPE_END)),
 ]
 
+out = sys.stdout
+if args.out != '-':
+  out = open(args.out, 'w')
+
 if args.fmt == 'html':
-  print '<html>'
-  print '<head>'
-  print '<title>Profile Report</title>'
-  print '</head>'
+  print >>out, '<html>'
+  print >>out, '<head>'
+  print >>out, '<title>Profile Report</title>'
+  print >>out, '</head>'
 
 accounted_for = 0
 for cs in call_stacks:
   if args.fmt in BANNER:
-    print BANNER[args.fmt] % {
+    print >>out, BANNER[args.fmt] % {
         'count': cs.count,
     }
   header, _ = zip(*FORMAT)
@@ -265,7 +271,7 @@
     for _, fn in FORMAT:
       fields.append(fn(line))
     table.append(fields)
-  print tabulate.tabulate(table, header, tablefmt=args.fmt)
+  print >>out, tabulate.tabulate(table, header, tablefmt=args.fmt)
   accounted_for += cs.count
   if accounted_for > .99 * total_stacks:
     break
diff --git a/tools/profiling/latency_profile/run_latency_profile.sh b/tools/profiling/latency_profile/run_latency_profile.sh
index 618db20..e9baee0 100755
--- a/tools/profiling/latency_profile/run_latency_profile.sh
+++ b/tools/profiling/latency_profile/run_latency_profile.sh
@@ -28,55 +28,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-# format argument via
-# $ echo '{...}' | python -mjson.tool
-read -r -d '' SCENARIOS_JSON_ARG <<'EOF'
-{
-    "scenarios": [
-        {
-            "benchmark_seconds": 5,
-            "client_config": {
-                "client_channels": 1,
-                "client_type": "SYNC_CLIENT",
-                "histogram_params": {
-                    "max_possible": 60000000000.0,
-                    "resolution": 0.01
-                },
-                "load_params": {
-                    "closed_loop": {}
-                },
-                "outstanding_rpcs_per_channel": 1,
-                "payload_config": {
-                    "simple_params": {
-                        "req_size": 0,
-                        "resp_size": 0
-                    }
-                },
-                "rpc_type": "UNARY",
-                "security_params": {
-                    "server_host_override": "foo.test.google.fr",
-                    "use_test_ca": true
-                }
-            },
-            "name": "cpp_protobuf_sync_unary_ping_pong_secure",
-            "num_clients": 1,
-            "num_servers": 1,
-            "server_config": {
-                "core_limit": 1,
-                "security_params": {
-                    "server_host_override": "foo.test.google.fr",
-                    "use_test_ca": true
-                },
-                "server_type": "SYNC_SERVER"
-            },
-            "spawn_local_worker_count": 2,
-            "warmup_seconds": 5
-        }
-    ]
-}
-
-EOF
-
 set -ex
 
 cd $(dirname $0)/../../..
@@ -93,14 +44,4 @@
   PYTHON=python2.7
 fi
 
-make CONFIG=basicprof -j$CPUS qps_json_driver
-
-mkdir -p reports
-bins/basicprof/qps_json_driver --scenarios_json="$SCENARIOS_JSON_ARG"
-
-echo '<html><head></head><body>Latency profile for:<br/>' > reports/index.html
-echo "<p><pre>${SCENARIOS_JSON_ARG}</pre></p>" >> reports/index.html
-echo '<p><pre>' >> reports/index.html
-$PYTHON tools/profiling/latency_profile/profile_analyzer.py \
-    --source=latency_trace.txt --fmt=simple >> reports/index.html
-echo '</pre></p></body></html>' >> reports/index.html
+$PYTHON tools/run_tests/run_microbenchmark.py --collect summary perf latency --bigquery_upload
diff --git a/tools/profiling/microbenchmarks/bm2bq.py b/tools/profiling/microbenchmarks/bm2bq.py
new file mode 100755
index 0000000..280f217
--- /dev/null
+++ b/tools/profiling/microbenchmarks/bm2bq.py
@@ -0,0 +1,218 @@
+#!/usr/bin/env python2.7
+#
+# Convert google-benchmark json output to something that can be uploaded to
+# BigQuery
+#
+#
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import sys
+import json
+import csv
+import os
+
+columns = [
+  ('jenkins_build', 'integer'),
+  ('jenkins_job', 'string'),
+  ('date', 'timestamp'),
+  ('cpu_scaling_enabled', 'boolean'),
+  ('num_cpus', 'integer'),
+  ('mhz_per_cpu', 'integer'),
+  ('library_build_type', 'string'),
+  ('name', 'string'),
+  ('fixture', 'string'),
+  ('client_mutator', 'string'),
+  ('server_mutator', 'string'),
+  ('request_size', 'integer'),
+  ('response_size', 'integer'),
+  ('request_count', 'integer'),
+  ('iterations', 'integer'),
+  ('time_unit', 'string'),
+  ('real_time', 'integer'),
+  ('cpu_time', 'integer'),
+  ('bytes_per_second', 'float'),
+  ('allocs_per_iteration', 'float'),
+  ('locks_per_iteration', 'float'),
+  ('writes_per_iteration', 'float'),
+  ('bandwidth_kilobits', 'integer'),
+  ('cli_transport_stalls_per_iteration', 'float'),
+  ('cli_stream_stalls_per_iteration', 'float'),
+  ('svr_transport_stalls_per_iteration', 'float'),
+  ('svr_stream_stalls_per_iteration', 'float'),
+  ('atm_cas_per_iteration', 'float'),
+  ('atm_add_per_iteration', 'float'),
+  ('end_of_stream', 'boolean'),
+  ('header_bytes_per_iteration', 'float'),
+  ('framing_bytes_per_iteration', 'float'),
+]
+
+if sys.argv[1] == '--schema':
+  print ',\n'.join('%s:%s' % (k, t.upper()) for k, t in columns)
+  sys.exit(0)
+
+with open(sys.argv[1]) as f:
+  js = json.loads(f.read())
+
+writer = csv.DictWriter(sys.stdout, [c for c,t in columns])
+
+bm_specs = {
+  'BM_UnaryPingPong': {
+    'tpl': ['fixture', 'client_mutator', 'server_mutator'],
+    'dyn': ['request_size', 'response_size'],
+  },
+  'BM_PumpStreamClientToServer': {
+    'tpl': ['fixture'],
+    'dyn': ['request_size'],
+  },
+  'BM_PumpStreamServerToClient': {
+    'tpl': ['fixture'],
+    'dyn': ['request_size'],
+  },
+  'BM_StreamingPingPong': {
+    'tpl': ['fixture', 'client_mutator', 'server_mutator'],
+    'dyn': ['request_size', 'request_count'],
+  },
+  'BM_StreamingPingPongMsgs': {
+    'tpl': ['fixture', 'client_mutator', 'server_mutator'],
+    'dyn': ['request_size'],
+  },
+  'BM_PumpStreamServerToClient_Trickle': {
+    'tpl': [],
+    'dyn': ['request_size', 'bandwidth_kilobits'],
+  },
+  'BM_ErrorStringOnNewError': {
+    'tpl': ['fixture'],
+    'dyn': [],
+  },
+  'BM_ErrorStringRepeatedly': {
+    'tpl': ['fixture'],
+    'dyn': [],
+  },
+  'BM_ErrorGetStatus': {
+    'tpl': ['fixture'],
+    'dyn': [],
+  },
+  'BM_ErrorGetStatusCode': {
+    'tpl': ['fixture'],
+    'dyn': [],
+  },
+  'BM_ErrorHttpError': {
+    'tpl': ['fixture'],
+    'dyn': [],
+  },
+  'BM_HasClearGrpcStatus': {
+    'tpl': ['fixture'],
+    'dyn': [],
+  },
+  'BM_IsolatedFilter' : {
+    'tpl': ['fixture', 'client_mutator'],
+    'dyn': [],
+  },
+  'BM_HpackEncoderEncodeHeader' : {
+    'tpl': ['fixture'],
+    'dyn': ['end_of_stream', 'request_size'],
+  },
+  'BM_HpackParserParseHeader' : {
+    'tpl': ['fixture'],
+    'dyn': [],
+  },
+}
+
+def numericalize(s):
+  if not s: return ''
+  if s[-1] == 'k':
+    return int(s[:-1]) * 1024
+  if s[-1] == 'M':
+    return int(s[:-1]) * 1024 * 1024
+  if 0 <= (ord(s[-1]) - ord('0')) <= 9:
+    return int(s)
+  assert 'not a number: %s' % s
+
+def parse_name(name):
+  if '<' not in name and '/' not in name and name not in bm_specs:
+    return {'name': name}
+  rest = name
+  out = {}
+  tpl_args = []
+  dyn_args = []
+  if '<' in rest:
+    tpl_bit = rest[rest.find('<') + 1 : rest.rfind('>')]
+    arg = ''
+    nesting = 0
+    for c in tpl_bit:
+      if c == '<':
+        nesting += 1
+        arg += c
+      elif c == '>':
+        nesting -= 1
+        arg += c
+      elif c == ',':
+        if nesting == 0:
+          tpl_args.append(arg.strip())
+          arg = ''
+        else:
+          arg += c
+      else:
+        arg += c
+    tpl_args.append(arg.strip())
+    rest = rest[:rest.find('<')] + rest[rest.rfind('>') + 1:]
+  if '/' in rest:
+    s = rest.split('/')
+    rest = s[0]
+    dyn_args = s[1:]
+  name = rest
+  assert name in bm_specs, 'bm_specs needs to be expanded for %s' % name
+  assert len(dyn_args) == len(bm_specs[name]['dyn'])
+  assert len(tpl_args) == len(bm_specs[name]['tpl'])
+  out['name'] = name
+  out.update(dict((k, numericalize(v)) for k, v in zip(bm_specs[name]['dyn'], dyn_args)))
+  out.update(dict(zip(bm_specs[name]['tpl'], tpl_args)))
+  return out
+
+for bm in js['benchmarks']:
+  context = js['context']
+  if 'label' in bm:
+    labels_list = [s.split(':') for s in bm['label'].strip().split(' ') if len(s) and s[0] != '#']
+    for el in labels_list:
+      el[0] = el[0].replace('/iter', '_per_iteration')
+    labels = dict(labels_list)
+  else:
+    labels = {}
+  row = {
+    'jenkins_build': os.environ.get('BUILD_NUMBER', ''),
+    'jenkins_job': os.environ.get('JOB_NAME', ''),
+  }
+  row.update(context)
+  row.update(bm)
+  row.update(parse_name(row['name']))
+  row.update(labels)
+  if 'label' in row:
+    del row['label']
+  writer.writerow(row)
diff --git a/tools/run_tests/artifacts/artifact_targets.py b/tools/run_tests/artifacts/artifact_targets.py
index 8648ceb..e0658f4 100644
--- a/tools/run_tests/artifacts/artifact_targets.py
+++ b/tools/run_tests/artifacts/artifact_targets.py
@@ -188,24 +188,14 @@
     self.labels = ['artifact', 'csharp', platform, arch]
 
   def pre_build_jobspecs(self):
-    if self.platform == 'windows':
-      return [create_jobspec('prebuild_%s' % self.name,
-                             ['tools\\run_tests\\helper_scripts\\pre_build_c.bat'],
-                             shell=True,
-                             flake_retries=5,
-                             timeout_retries=2)]
-    else:
-      return []
+    return []
 
   def build_jobspec(self):
     if self.platform == 'windows':
-      msbuild_platform = 'Win32' if self.arch == 'x86' else self.arch
+      cmake_arch_option = 'Win32' if self.arch == 'x86' else self.arch
       return create_jobspec(self.name,
                             ['tools\\run_tests\\artifacts\\build_artifact_csharp.bat',
-                             'vsprojects\\grpc_csharp_ext.sln',
-                             '/p:Configuration=Release',
-                             '/p:PlatformToolset=v120',
-                             '/p:Platform=%s' % msbuild_platform],
+                             cmake_arch_option],
                             shell=True)
     else:
       environ = {'CONFIG': 'opt',
diff --git a/tools/run_tests/artifacts/build_artifact_csharp.bat b/tools/run_tests/artifacts/build_artifact_csharp.bat
index 24c8d48..f84ebc5 100644
--- a/tools/run_tests/artifacts/build_artifact_csharp.bat
+++ b/tools/run_tests/artifacts/build_artifact_csharp.bat
@@ -29,10 +29,16 @@
 
 @rem Builds C# artifacts on Windows
 
-@call vsprojects\build_vs2013.bat %* || goto :error
+set ARCHITECTURE=%1
+
+@call tools\run_tests\helper_scripts\pre_build_csharp.bat %ARCHITECTURE% || goto :error
+
+cd cmake\build\%ARCHITECTURE%
+cmake --build . --target grpc_csharp_ext --config Release
+cd ..\..\..
 
 mkdir artifacts
-copy /Y vsprojects\Release\grpc_csharp_ext.dll artifacts || copy /Y vsprojects\x64\Release\grpc_csharp_ext.dll artifacts || goto :error
+copy /Y cmake\build\Win32\Release\grpc_csharp_ext.dll artifacts || copy /Y cmake\build\x64\Release\grpc_csharp_ext.dll artifacts || goto :error
 
 goto :EOF
 
diff --git a/tools/run_tests/dockerize/build_docker_and_run_tests.sh b/tools/run_tests/dockerize/build_docker_and_run_tests.sh
index b68ac89..f10916d 100755
--- a/tools/run_tests/dockerize/build_docker_and_run_tests.sh
+++ b/tools/run_tests/dockerize/build_docker_and_run_tests.sh
@@ -47,12 +47,19 @@
 # Inputs
 # DOCKERFILE_DIR - Directory in which Dockerfile file is located.
 # DOCKER_RUN_SCRIPT - Script to run under docker (relative to grpc repo root)
+# DOCKERHUB_ORGANIZATION - If set, pull a prebuilt image from given dockerhub org.
 
 # Use image name based on Dockerfile location checksum
 DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
 
-# Make sure docker image has been built. Should be instantaneous if so.
-docker build -t $DOCKER_IMAGE_NAME $DOCKERFILE_DIR
+if [ "$DOCKERHUB_ORGANIZATION" != "" ]
+then
+  DOCKER_IMAGE_NAME=$DOCKERHUB_ORGANIZATION/$DOCKER_IMAGE_NAME
+  docker pull $DOCKER_IMAGE_NAME
+else
+  # Make sure docker image has been built. Should be instantaneous if so.
+  docker build -t $DOCKER_IMAGE_NAME $DOCKERFILE_DIR
+fi
 
 # Choose random name for docker container
 CONTAINER_NAME="run_tests_$(uuidgen)"
diff --git a/tools/run_tests/dockerize/build_interop_stress_image.sh b/tools/run_tests/dockerize/build_interop_stress_image.sh
index 4407c8d..772eab0 100755
--- a/tools/run_tests/dockerize/build_interop_stress_image.sh
+++ b/tools/run_tests/dockerize/build_interop_stress_image.sh
@@ -98,7 +98,7 @@
   $BASE_IMAGE \
   bash -l /var/local/jenkins/grpc/tools/dockerfile/stress_test/$BASE_NAME/build_interop_stress.sh \
   && docker commit $CONTAINER_NAME $INTEROP_IMAGE \
-  && ( if [ -n "$INTEROP_IMAGE_REPOSITORY_TAG" ]; then docker tag -f $INTEROP_IMAGE $INTEROP_IMAGE_REPOSITORY_TAG ; fi ) \
+  && ( if [ -n "$INTEROP_IMAGE_REPOSITORY_TAG" ]; then docker tag $INTEROP_IMAGE $INTEROP_IMAGE_REPOSITORY_TAG ; fi ) \
   && echo "Successfully built image $INTEROP_IMAGE")
 EXITCODE=$?
 
diff --git a/tools/run_tests/dockerize/docker_run_tests.sh b/tools/run_tests/dockerize/docker_run_tests.sh
index eb220ae..0d260ff 100755
--- a/tools/run_tests/dockerize/docker_run_tests.sh
+++ b/tools/run_tests/dockerize/docker_run_tests.sh
@@ -68,6 +68,7 @@
 
 zip -r reports.zip reports
 find . -name report.xml | xargs -r zip reports.zip
+find . -name sponge_log.xml | xargs -r zip reports.zip
 find . -name 'report_*.xml' | xargs -r zip reports.zip
 
 exit $exit_code
diff --git a/tools/run_tests/generated/configs.json b/tools/run_tests/generated/configs.json
index b0839ef..9173bd7 100644
--- a/tools/run_tests/generated/configs.json
+++ b/tools/run_tests/generated/configs.json
@@ -3,42 +3,10 @@
     "config": "opt"
   }, 
   {
-    "config": "asan-trace-cmp", 
-    "environ": {
-      "ASAN_OPTIONS": "detect_leaks=1:color=always", 
-      "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
-    }, 
-    "timeout_multiplier": 3
-  }, 
-  {
-    "config": "dbg"
-  }, 
-  {
-    "config": "easan", 
-    "environ": {
-      "ASAN_OPTIONS": "detect_leaks=1:color=always", 
-      "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
-    }, 
-    "timeout_multiplier": 3
-  }, 
-  {
-    "config": "asan", 
-    "environ": {
-      "ASAN_OPTIONS": "detect_leaks=1:color=always", 
-      "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
-    }, 
-    "timeout_multiplier": 3
-  }, 
-  {
-    "config": "msan", 
-    "timeout_multiplier": 4
-  }, 
-  {
     "config": "basicprof"
   }, 
   {
     "config": "helgrind", 
-    "timeout_multiplier": 20, 
     "tool_prefix": [
       "valgrind", 
       "--tool=helgrind"
@@ -48,35 +16,26 @@
     "config": "asan-noleaks", 
     "environ": {
       "ASAN_OPTIONS": "detect_leaks=0:color=always"
-    }, 
-    "timeout_multiplier": 3
+    }
   }, 
   {
-    "config": "edbg"
-  }, 
-  {
-    "config": "ubsan", 
+    "config": "asan-trace-cmp", 
     "environ": {
-      "UBSAN_OPTIONS": "halt_on_error=1:print_stacktrace=1"
-    }, 
-    "timeout_multiplier": 1.5
+      "ASAN_OPTIONS": "detect_leaks=1:color=always", 
+      "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
+    }
   }, 
   {
-    "config": "tsan", 
-    "environ": {
-      "TSAN_OPTIONS": "suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1"
-    }, 
-    "timeout_multiplier": 5
+    "config": "dbg"
   }, 
   {
     "config": "stapprof"
   }, 
   {
-    "config": "mutrace"
+    "config": "gcov"
   }, 
   {
     "config": "memcheck", 
-    "timeout_multiplier": 10, 
     "tool_prefix": [
       "valgrind", 
       "--tool=memcheck", 
@@ -84,13 +43,31 @@
     ]
   }, 
   {
-    "config": "etsan", 
+    "config": "asan", 
     "environ": {
-      "TSAN_OPTIONS": "suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1"
-    }, 
-    "timeout_multiplier": 5
+      "ASAN_OPTIONS": "detect_leaks=1:color=always", 
+      "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
+    }
   }, 
   {
-    "config": "gcov"
+    "config": "tsan", 
+    "environ": {
+      "TSAN_OPTIONS": "suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1"
+    }
+  }, 
+  {
+    "config": "ubsan", 
+    "environ": {
+      "UBSAN_OPTIONS": "halt_on_error=1:print_stacktrace=1"
+    }
+  }, 
+  {
+    "config": "msan"
+  }, 
+  {
+    "config": "mutrace"
+  }, 
+  {
+    "config": "counters"
   }
 ]
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 5763532..15bcf56 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -104,6 +104,23 @@
   }, 
   {
     "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
+    "name": "bdp_estimator_test", 
+    "src": [
+      "test/core/transport/bdp_estimator_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "grpc", 
       "grpc_test_util"
     ], 
@@ -227,23 +244,6 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
-    "name": "chttp2_status_conversion_test", 
-    "src": [
-      "test/core/transport/chttp2/status_conversion_test.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
     "name": "chttp2_stream_map_test", 
     "src": [
       "test/core/transport/chttp2/stream_map_test.c"
@@ -739,6 +739,21 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
+    "name": "gpr_spinlock_test", 
+    "src": [
+      "test/core/support/spinlock_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
     "name": "gpr_stack_lockfree_test", 
     "src": [
       "test/core/support/stack_lockfree_test.c"
@@ -1316,57 +1331,6 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
-    "name": "internal_api_canary_iomgr_test", 
-    "src": [
-      "test/core/internal_api_canaries/iomgr.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
-    "name": "internal_api_canary_support_test", 
-    "src": [
-      "test/core/internal_api_canaries/iomgr.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
-    "name": "internal_api_canary_transport_test", 
-    "src": [
-      "test/core/internal_api_canaries/iomgr.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
     "name": "invalid_call_argument_test", 
     "src": [
       "test/core/end2end/invalid_call_argument_test.c"
@@ -1754,6 +1718,40 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
+    "name": "pollset_set_test", 
+    "src": [
+      "test/core/iomgr/pollset_set_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
+    "name": "resolve_address_posix_test", 
+    "src": [
+      "test/core/iomgr/resolve_address_posix_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
     "name": "resolve_address_test", 
     "src": [
       "test/core/iomgr/resolve_address_test.c"
@@ -2027,6 +2025,23 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
+    "name": "status_conversion_test", 
+    "src": [
+      "test/core/transport/status_conversion_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
     "name": "tcp_client_posix_test", 
     "src": [
       "test/core/iomgr/tcp_client_posix_test.c"
@@ -2376,6 +2391,106 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c++", 
+    "name": "bm_call_create", 
+    "src": [
+      "test/cpp/microbenchmarks/bm_call_create.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "benchmark", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "bm_chttp2_hpack", 
+    "src": [
+      "test/cpp/microbenchmarks/bm_chttp2_hpack.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "benchmark", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "bm_closure", 
+    "src": [
+      "test/cpp/microbenchmarks/bm_closure.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "benchmark", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "bm_cq", 
+    "src": [
+      "test/cpp/microbenchmarks/bm_cq.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "benchmark", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "bm_error", 
+    "src": [
+      "test/cpp/microbenchmarks/bm_error.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "benchmark", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
     "name": "bm_fullstack", 
     "src": [
       "test/cpp/microbenchmarks/bm_fullstack.cc"
@@ -2385,6 +2500,24 @@
   }, 
   {
     "deps": [
+      "benchmark", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "bm_metadata", 
+    "src": [
+      "test/cpp/microbenchmarks/bm_metadata.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "gpr", 
       "grpc", 
       "grpc++"
@@ -2876,6 +3009,25 @@
   }, 
   {
     "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "health_service_end2end_test", 
+    "src": [
+      "test/cpp/end2end/health_service_end2end_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "grpc", 
       "grpc++", 
       "grpc++_test_config", 
@@ -3067,6 +3219,23 @@
   }, 
   {
     "deps": [
+      "grpc", 
+      "grpc++", 
+      "grpc++_codegen_base", 
+      "grpc++_codegen_proto"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "proto_utils_test", 
+    "src": [
+      "test/cpp/codegen/proto_utils_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "gpr", 
       "gpr_test_util", 
       "grpc", 
@@ -3481,6 +3650,25 @@
   {
     "deps": [
       "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "writes_per_rpc_test", 
+    "src": [
+      "test/cpp/performance/writes_per_rpc_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
       "grpc"
     ], 
     "headers": [], 
@@ -5178,7 +5366,7 @@
       "census", 
       "gpr", 
       "grpc_base", 
-      "grpc_lb_policy_grpclb", 
+      "grpc_lb_policy_grpclb_secure", 
       "grpc_lb_policy_pick_first", 
       "grpc_lb_policy_round_robin", 
       "grpc_load_reporting", 
@@ -5204,6 +5392,7 @@
     "deps": [
       "gpr", 
       "grpc_base", 
+      "grpc_load_reporting", 
       "grpc_transport_chttp2_client_secure", 
       "grpc_transport_cronet_client_secure"
     ], 
@@ -5344,7 +5533,8 @@
       "grpc", 
       "grpc++_base", 
       "grpc++_codegen_base", 
-      "grpc++_codegen_base_src"
+      "grpc++_codegen_base_src", 
+      "grpc++_codegen_proto"
     ], 
     "headers": [
       "include/grpc++/impl/codegen/core_codegen.h", 
@@ -5437,23 +5627,6 @@
     "type": "lib"
   }, 
   {
-    "deps": [
-      "grpc++"
-    ], 
-    "headers": [
-      "include/grpc++/test/server_context_test_spouse.h"
-    ], 
-    "is_filegroup": false, 
-    "language": "c++", 
-    "name": "grpc++_test", 
-    "src": [
-      "include/grpc++/test/server_context_test_spouse.h", 
-      "src/cpp/test/server_context_test_spouse.cc"
-    ], 
-    "third_party": false, 
-    "type": "lib"
-  }, 
-  {
     "deps": [], 
     "headers": [
       "test/cpp/util/test_config.h"
@@ -5479,6 +5652,8 @@
       "thrift_util"
     ], 
     "headers": [
+      "src/proto/grpc/health/v1/health.grpc.pb.h", 
+      "src/proto/grpc/health/v1/health.pb.h", 
       "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h", 
       "src/proto/grpc/testing/duplicate/echo_duplicate.pb.h", 
       "src/proto/grpc/testing/echo.grpc.pb.h", 
@@ -6698,6 +6873,7 @@
       "test/core/end2end/tests/hpack_size.c", 
       "test/core/end2end/tests/idempotent_request.c", 
       "test/core/end2end/tests/invoke_large_request.c", 
+      "test/core/end2end/tests/keepalive_timeout.c", 
       "test/core/end2end/tests/large_metadata.c", 
       "test/core/end2end/tests/load_reporting_hook.c", 
       "test/core/end2end/tests/max_concurrent_streams.c", 
@@ -6769,6 +6945,7 @@
       "test/core/end2end/tests/hpack_size.c", 
       "test/core/end2end/tests/idempotent_request.c", 
       "test/core/end2end/tests/invoke_large_request.c", 
+      "test/core/end2end/tests/keepalive_timeout.c", 
       "test/core/end2end/tests/large_metadata.c", 
       "test/core/end2end/tests/load_reporting_hook.c", 
       "test/core/end2end/tests/max_concurrent_streams.c", 
@@ -6817,7 +6994,12 @@
       "src/core/ext/census/mlog.h", 
       "src/core/ext/census/resource.h", 
       "src/core/ext/census/rpc_metric_id.h", 
-      "src/core/ext/census/trace_context.h"
+      "src/core/ext/census/trace_context.h", 
+      "src/core/ext/census/trace_label.h", 
+      "src/core/ext/census/trace_propagation.h", 
+      "src/core/ext/census/trace_status.h", 
+      "src/core/ext/census/trace_string.h", 
+      "src/core/ext/census/tracing.h"
     ], 
     "is_filegroup": true, 
     "language": "c", 
@@ -6848,7 +7030,12 @@
       "src/core/ext/census/rpc_metric_id.h", 
       "src/core/ext/census/trace_context.c", 
       "src/core/ext/census/trace_context.h", 
-      "src/core/ext/census/tracing.c"
+      "src/core/ext/census/trace_label.h", 
+      "src/core/ext/census/trace_propagation.h", 
+      "src/core/ext/census/trace_status.h", 
+      "src/core/ext/census/trace_string.h", 
+      "src/core/ext/census/tracing.c", 
+      "src/core/ext/census/tracing.h"
     ], 
     "third_party": false, 
     "type": "filegroup"
@@ -6890,6 +7077,7 @@
       "src/core/lib/support/env.h", 
       "src/core/lib/support/mpscq.h", 
       "src/core/lib/support/murmur_hash.h", 
+      "src/core/lib/support/spinlock.h", 
       "src/core/lib/support/stack_lockfree.h", 
       "src/core/lib/support/string.h", 
       "src/core/lib/support/string_windows.h", 
@@ -6955,6 +7143,7 @@
       "src/core/lib/support/mpscq.h", 
       "src/core/lib/support/murmur_hash.c", 
       "src/core/lib/support/murmur_hash.h", 
+      "src/core/lib/support/spinlock.h", 
       "src/core/lib/support/stack_lockfree.c", 
       "src/core/lib/support/stack_lockfree.h", 
       "src/core/lib/support/string.c", 
@@ -7035,6 +7224,7 @@
       "include/grpc/grpc.h", 
       "include/grpc/grpc_posix.h", 
       "include/grpc/grpc_security_constants.h", 
+      "include/grpc/load_reporting.h", 
       "include/grpc/slice.h", 
       "include/grpc/slice_buffer.h", 
       "include/grpc/status.h", 
@@ -7062,6 +7252,7 @@
       "src/core/lib/iomgr/endpoint.h", 
       "src/core/lib/iomgr/endpoint_pair.h", 
       "src/core/lib/iomgr/error.h", 
+      "src/core/lib/iomgr/error_internal.h", 
       "src/core/lib/iomgr/ev_epoll_linux.h", 
       "src/core/lib/iomgr/ev_poll_posix.h", 
       "src/core/lib/iomgr/ev_posix.h", 
@@ -7114,6 +7305,7 @@
       "src/core/lib/json/json_reader.h", 
       "src/core/lib/json/json_writer.h", 
       "src/core/lib/slice/percent_encoding.h", 
+      "src/core/lib/slice/slice_hash_table.h", 
       "src/core/lib/slice/slice_internal.h", 
       "src/core/lib/slice/slice_string_helpers.h", 
       "src/core/lib/surface/api_trace.h", 
@@ -7127,14 +7319,18 @@
       "src/core/lib/surface/init.h", 
       "src/core/lib/surface/lame_client.h", 
       "src/core/lib/surface/server.h", 
+      "src/core/lib/surface/validate_metadata.h", 
+      "src/core/lib/transport/bdp_estimator.h", 
       "src/core/lib/transport/byte_stream.h", 
       "src/core/lib/transport/connectivity_state.h", 
-      "src/core/lib/transport/mdstr_hash_table.h", 
+      "src/core/lib/transport/error_utils.h", 
+      "src/core/lib/transport/http2_errors.h", 
       "src/core/lib/transport/metadata.h", 
       "src/core/lib/transport/metadata_batch.h", 
       "src/core/lib/transport/pid_controller.h", 
       "src/core/lib/transport/service_config.h", 
       "src/core/lib/transport/static_metadata.h", 
+      "src/core/lib/transport/status_conversion.h", 
       "src/core/lib/transport/timeout_encoding.h", 
       "src/core/lib/transport/transport.h", 
       "src/core/lib/transport/transport_impl.h"
@@ -7149,6 +7345,7 @@
       "include/grpc/grpc.h", 
       "include/grpc/grpc_posix.h", 
       "include/grpc/grpc_security_constants.h", 
+      "include/grpc/load_reporting.h", 
       "include/grpc/slice.h", 
       "include/grpc/slice_buffer.h", 
       "include/grpc/status.h", 
@@ -7201,6 +7398,7 @@
       "src/core/lib/iomgr/endpoint_pair_windows.c", 
       "src/core/lib/iomgr/error.c", 
       "src/core/lib/iomgr/error.h", 
+      "src/core/lib/iomgr/error_internal.h", 
       "src/core/lib/iomgr/ev_epoll_linux.c", 
       "src/core/lib/iomgr/ev_epoll_linux.h", 
       "src/core/lib/iomgr/ev_poll_posix.c", 
@@ -7312,6 +7510,9 @@
       "src/core/lib/slice/percent_encoding.h", 
       "src/core/lib/slice/slice.c", 
       "src/core/lib/slice/slice_buffer.c", 
+      "src/core/lib/slice/slice_hash_table.c", 
+      "src/core/lib/slice/slice_hash_table.h", 
+      "src/core/lib/slice/slice_intern.c", 
       "src/core/lib/slice/slice_internal.h", 
       "src/core/lib/slice/slice_string_helpers.c", 
       "src/core/lib/slice/slice_string_helpers.h", 
@@ -7343,13 +7544,17 @@
       "src/core/lib/surface/server.c", 
       "src/core/lib/surface/server.h", 
       "src/core/lib/surface/validate_metadata.c", 
+      "src/core/lib/surface/validate_metadata.h", 
       "src/core/lib/surface/version.c", 
+      "src/core/lib/transport/bdp_estimator.c", 
+      "src/core/lib/transport/bdp_estimator.h", 
       "src/core/lib/transport/byte_stream.c", 
       "src/core/lib/transport/byte_stream.h", 
       "src/core/lib/transport/connectivity_state.c", 
       "src/core/lib/transport/connectivity_state.h", 
-      "src/core/lib/transport/mdstr_hash_table.c", 
-      "src/core/lib/transport/mdstr_hash_table.h", 
+      "src/core/lib/transport/error_utils.c", 
+      "src/core/lib/transport/error_utils.h", 
+      "src/core/lib/transport/http2_errors.h", 
       "src/core/lib/transport/metadata.c", 
       "src/core/lib/transport/metadata.h", 
       "src/core/lib/transport/metadata_batch.c", 
@@ -7360,6 +7565,8 @@
       "src/core/lib/transport/service_config.h", 
       "src/core/lib/transport/static_metadata.c", 
       "src/core/lib/transport/static_metadata.h", 
+      "src/core/lib/transport/status_conversion.c", 
+      "src/core/lib/transport/status_conversion.h", 
       "src/core/lib/transport/timeout_encoding.c", 
       "src/core/lib/transport/timeout_encoding.h", 
       "src/core/lib/transport/transport.c", 
@@ -7380,11 +7587,14 @@
       "src/core/ext/client_channel/client_channel_factory.h", 
       "src/core/ext/client_channel/connector.h", 
       "src/core/ext/client_channel/http_connect_handshaker.h", 
+      "src/core/ext/client_channel/http_proxy.h", 
       "src/core/ext/client_channel/initial_connect_string.h", 
       "src/core/ext/client_channel/lb_policy.h", 
       "src/core/ext/client_channel/lb_policy_factory.h", 
       "src/core/ext/client_channel/lb_policy_registry.h", 
       "src/core/ext/client_channel/parse_address.h", 
+      "src/core/ext/client_channel/proxy_mapper.h", 
+      "src/core/ext/client_channel/proxy_mapper_registry.h", 
       "src/core/ext/client_channel/resolver.h", 
       "src/core/ext/client_channel/resolver_factory.h", 
       "src/core/ext/client_channel/resolver_registry.h", 
@@ -7407,6 +7617,8 @@
       "src/core/ext/client_channel/default_initial_connect_string.c", 
       "src/core/ext/client_channel/http_connect_handshaker.c", 
       "src/core/ext/client_channel/http_connect_handshaker.h", 
+      "src/core/ext/client_channel/http_proxy.c", 
+      "src/core/ext/client_channel/http_proxy.h", 
       "src/core/ext/client_channel/initial_connect_string.c", 
       "src/core/ext/client_channel/initial_connect_string.h", 
       "src/core/ext/client_channel/lb_policy.c", 
@@ -7417,6 +7629,10 @@
       "src/core/ext/client_channel/lb_policy_registry.h", 
       "src/core/ext/client_channel/parse_address.c", 
       "src/core/ext/client_channel/parse_address.h", 
+      "src/core/ext/client_channel/proxy_mapper.c", 
+      "src/core/ext/client_channel/proxy_mapper.h", 
+      "src/core/ext/client_channel/proxy_mapper_registry.c", 
+      "src/core/ext/client_channel/proxy_mapper_registry.h", 
       "src/core/ext/client_channel/resolver.c", 
       "src/core/ext/client_channel/resolver.h", 
       "src/core/ext/client_channel/resolver_factory.c", 
@@ -7470,6 +7686,7 @@
     ], 
     "headers": [
       "src/core/ext/lb_policy/grpclb/grpclb.h", 
+      "src/core/ext/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/lb_policy/grpclb/load_balancer_api.h", 
       "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
     ], 
@@ -7479,6 +7696,37 @@
     "src": [
       "src/core/ext/lb_policy/grpclb/grpclb.c", 
       "src/core/ext/lb_policy/grpclb/grpclb.h", 
+      "src/core/ext/lb_policy/grpclb/grpclb_channel.c", 
+      "src/core/ext/lb_policy/grpclb/grpclb_channel.h", 
+      "src/core/ext/lb_policy/grpclb/load_balancer_api.c", 
+      "src/core/ext/lb_policy/grpclb/load_balancer_api.h", 
+      "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", 
+      "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base", 
+      "grpc_client_channel", 
+      "nanopb"
+    ], 
+    "headers": [
+      "src/core/ext/lb_policy/grpclb/grpclb.h", 
+      "src/core/ext/lb_policy/grpclb/grpclb_channel.h", 
+      "src/core/ext/lb_policy/grpclb/load_balancer_api.h", 
+      "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
+    ], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc_lb_policy_grpclb_secure", 
+    "src": [
+      "src/core/ext/lb_policy/grpclb/grpclb.c", 
+      "src/core/ext/lb_policy/grpclb/grpclb.h", 
+      "src/core/ext/lb_policy/grpclb/grpclb_channel.h", 
+      "src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c", 
       "src/core/ext/lb_policy/grpclb/load_balancer_api.c", 
       "src/core/ext/lb_policy/grpclb/load_balancer_api.h", 
       "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", 
@@ -7594,6 +7842,7 @@
       "src/core/lib/security/credentials/plugin/plugin_credentials.h", 
       "src/core/lib/security/credentials/ssl/ssl_credentials.h", 
       "src/core/lib/security/transport/auth_filters.h", 
+      "src/core/lib/security/transport/lb_targets_info.h", 
       "src/core/lib/security/transport/secure_endpoint.h", 
       "src/core/lib/security/transport/security_connector.h", 
       "src/core/lib/security/transport/security_handshaker.h", 
@@ -7635,6 +7884,8 @@
       "src/core/lib/security/credentials/ssl/ssl_credentials.h", 
       "src/core/lib/security/transport/auth_filters.h", 
       "src/core/lib/security/transport/client_auth_filter.c", 
+      "src/core/lib/security/transport/lb_targets_info.c", 
+      "src/core/lib/security/transport/lb_targets_info.h", 
       "src/core/lib/security/transport/secure_endpoint.c", 
       "src/core/lib/security/transport/secure_endpoint.h", 
       "src/core/lib/security/transport/security_connector.c", 
@@ -7664,6 +7915,7 @@
       "test/core/end2end/fixtures/http_proxy.h", 
       "test/core/end2end/fixtures/proxy.h", 
       "test/core/iomgr/endpoint_tests.h", 
+      "test/core/util/debugger_macros.h", 
       "test/core/util/grpc_profiler.h", 
       "test/core/util/memory_counters.h", 
       "test/core/util/mock_endpoint.h", 
@@ -7671,7 +7923,8 @@
       "test/core/util/passthru_endpoint.h", 
       "test/core/util/port.h", 
       "test/core/util/port_server_client.h", 
-      "test/core/util/slice_splitter.h"
+      "test/core/util/slice_splitter.h", 
+      "test/core/util/trickle_endpoint.h"
     ], 
     "is_filegroup": true, 
     "language": "c", 
@@ -7687,6 +7940,8 @@
       "test/core/end2end/fixtures/proxy.h", 
       "test/core/iomgr/endpoint_tests.c", 
       "test/core/iomgr/endpoint_tests.h", 
+      "test/core/util/debugger_macros.c", 
+      "test/core/util/debugger_macros.h", 
       "test/core/util/grpc_profiler.c", 
       "test/core/util/grpc_profiler.h", 
       "test/core/util/memory_counters.c", 
@@ -7704,7 +7959,9 @@
       "test/core/util/port_uv.c", 
       "test/core/util/port_windows.c", 
       "test/core/util/slice_splitter.c", 
-      "test/core/util/slice_splitter.h"
+      "test/core/util/slice_splitter.h", 
+      "test/core/util/trickle_endpoint.c", 
+      "test/core/util/trickle_endpoint.h"
     ], 
     "third_party": false, 
     "type": "filegroup"
@@ -7729,11 +7986,9 @@
       "src/core/ext/transport/chttp2/transport/hpack_encoder.h", 
       "src/core/ext/transport/chttp2/transport/hpack_parser.h", 
       "src/core/ext/transport/chttp2/transport/hpack_table.h", 
-      "src/core/ext/transport/chttp2/transport/http2_errors.h", 
       "src/core/ext/transport/chttp2/transport/huffsyms.h", 
       "src/core/ext/transport/chttp2/transport/incoming_metadata.h", 
       "src/core/ext/transport/chttp2/transport/internal.h", 
-      "src/core/ext/transport/chttp2/transport/status_conversion.h", 
       "src/core/ext/transport/chttp2/transport/stream_map.h", 
       "src/core/ext/transport/chttp2/transport/varint.h"
     ], 
@@ -7767,15 +8022,12 @@
       "src/core/ext/transport/chttp2/transport/hpack_parser.h", 
       "src/core/ext/transport/chttp2/transport/hpack_table.c", 
       "src/core/ext/transport/chttp2/transport/hpack_table.h", 
-      "src/core/ext/transport/chttp2/transport/http2_errors.h", 
       "src/core/ext/transport/chttp2/transport/huffsyms.c", 
       "src/core/ext/transport/chttp2/transport/huffsyms.h", 
       "src/core/ext/transport/chttp2/transport/incoming_metadata.c", 
       "src/core/ext/transport/chttp2/transport/incoming_metadata.h", 
       "src/core/ext/transport/chttp2/transport/internal.h", 
       "src/core/ext/transport/chttp2/transport/parsing.c", 
-      "src/core/ext/transport/chttp2/transport/status_conversion.c", 
-      "src/core/ext/transport/chttp2/transport/status_conversion.h", 
       "src/core/ext/transport/chttp2/transport/stream_lists.c", 
       "src/core/ext/transport/chttp2/transport/stream_map.c", 
       "src/core/ext/transport/chttp2/transport/stream_map.h", 
@@ -7924,7 +8176,8 @@
       "include/grpc/grpc_cronet.h", 
       "include/grpc/grpc_security.h", 
       "include/grpc/grpc_security_constants.h", 
-      "third_party/Cronet/bidirectional_stream_c.h"
+      "src/core/ext/transport/cronet/transport/cronet_transport.h", 
+      "third_party/objective_c/Cronet/bidirectional_stream_c.h"
     ], 
     "is_filegroup": true, 
     "language": "c", 
@@ -7935,7 +8188,8 @@
       "include/grpc/grpc_security_constants.h", 
       "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", 
       "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", 
-      "src/core/ext/transport/cronet/transport/cronet_transport.c"
+      "src/core/ext/transport/cronet/transport/cronet_transport.c", 
+      "src/core/ext/transport/cronet/transport/cronet_transport.h"
     ], 
     "third_party": false, 
     "type": "filegroup"
@@ -7993,9 +8247,11 @@
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
       "include/grpc++/create_channel_posix.h", 
+      "include/grpc++/ext/health_check_service_server_builder_option.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/grpc++.h", 
+      "include/grpc++/health_check_service_interface.h", 
       "include/grpc++/impl/call.h", 
       "include/grpc++/impl/client_unary_call.h", 
       "include/grpc++/impl/codegen/core_codegen.h", 
@@ -8032,6 +8288,8 @@
       "src/cpp/client/create_channel_internal.h", 
       "src/cpp/common/channel_filter.h", 
       "src/cpp/server/dynamic_thread_pool.h", 
+      "src/cpp/server/health/default_health_check_service.h", 
+      "src/cpp/server/health/health.pb.h", 
       "src/cpp/server/thread_pool_interface.h", 
       "src/cpp/thread_manager/thread_manager.h"
     ], 
@@ -8045,9 +8303,11 @@
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
       "include/grpc++/create_channel_posix.h", 
+      "include/grpc++/ext/health_check_service_server_builder_option.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/grpc++.h", 
+      "include/grpc++/health_check_service_interface.h", 
       "include/grpc++/impl/call.h", 
       "include/grpc++/impl/client_unary_call.h", 
       "include/grpc++/impl/codegen/core_codegen.h", 
@@ -8101,6 +8361,12 @@
       "src/cpp/server/create_default_thread_pool.cc", 
       "src/cpp/server/dynamic_thread_pool.cc", 
       "src/cpp/server/dynamic_thread_pool.h", 
+      "src/cpp/server/health/default_health_check_service.cc", 
+      "src/cpp/server/health/default_health_check_service.h", 
+      "src/cpp/server/health/health.pb.c", 
+      "src/cpp/server/health/health.pb.h", 
+      "src/cpp/server/health/health_check_service.cc", 
+      "src/cpp/server/health/health_check_service_server_builder_option.cc", 
       "src/cpp/server/server_builder.cc", 
       "src/cpp/server/server_cc.cc", 
       "src/cpp/server/server_context.cc", 
@@ -8136,6 +8402,7 @@
       "include/grpc++/impl/codegen/core_codegen_interface.h", 
       "include/grpc++/impl/codegen/create_auth_context.h", 
       "include/grpc++/impl/codegen/grpc_library.h", 
+      "include/grpc++/impl/codegen/metadata_map.h", 
       "include/grpc++/impl/codegen/method_handler_impl.h", 
       "include/grpc++/impl/codegen/rpc_method.h", 
       "include/grpc++/impl/codegen/rpc_service_method.h", 
@@ -8144,6 +8411,7 @@
       "include/grpc++/impl/codegen/server_context.h", 
       "include/grpc++/impl/codegen/server_interface.h", 
       "include/grpc++/impl/codegen/service_type.h", 
+      "include/grpc++/impl/codegen/slice.h", 
       "include/grpc++/impl/codegen/status.h", 
       "include/grpc++/impl/codegen/status_code_enum.h", 
       "include/grpc++/impl/codegen/status_helper.h", 
@@ -8169,6 +8437,7 @@
       "include/grpc++/impl/codegen/core_codegen_interface.h", 
       "include/grpc++/impl/codegen/create_auth_context.h", 
       "include/grpc++/impl/codegen/grpc_library.h", 
+      "include/grpc++/impl/codegen/metadata_map.h", 
       "include/grpc++/impl/codegen/method_handler_impl.h", 
       "include/grpc++/impl/codegen/rpc_method.h", 
       "include/grpc++/impl/codegen/rpc_service_method.h", 
@@ -8177,6 +8446,7 @@
       "include/grpc++/impl/codegen/server_context.h", 
       "include/grpc++/impl/codegen/server_interface.h", 
       "include/grpc++/impl/codegen/service_type.h", 
+      "include/grpc++/impl/codegen/slice.h", 
       "include/grpc++/impl/codegen/status.h", 
       "include/grpc++/impl/codegen/status_code_enum.h", 
       "include/grpc++/impl/codegen/status_helper.h", 
@@ -8248,6 +8518,22 @@
   }, 
   {
     "deps": [
+      "grpc++"
+    ], 
+    "headers": [
+      "include/grpc++/test/server_context_test_spouse.h"
+    ], 
+    "is_filegroup": true, 
+    "language": "c++", 
+    "name": "grpc++_test", 
+    "src": [
+      "include/grpc++/test/server_context_test_spouse.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
       "grpc++_codegen_base"
     ], 
     "headers": [
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index a273e3f..ab7938d 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -127,6 +127,28 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
+    "name": "bdp_estimator_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
     "name": "bin_decoder_test", 
     "platforms": [
       "linux", 
@@ -281,28 +303,6 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
-    "name": "chttp2_status_conversion_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c", 
     "name": "chttp2_stream_map_test", 
     "platforms": [
       "linux", 
@@ -845,6 +845,28 @@
       "posix", 
       "windows"
     ], 
+    "cpu_cost": 10, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "gpr_spinlock_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
     "cpu_cost": 7, 
     "exclude_configs": [], 
     "exclude_iomgrs": [], 
@@ -1553,28 +1575,6 @@
       "posix", 
       "windows"
     ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": true, 
-    "gtest": false, 
-    "language": "c", 
-    "name": "lb_policies_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "exclude_iomgrs": [], 
@@ -1744,6 +1744,44 @@
   {
     "args": [], 
     "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "pollset_set_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "resolve_address_posix_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
       "linux", 
       "mac", 
       "posix", 
@@ -2060,6 +2098,28 @@
     "ci_platforms": [
       "linux", 
       "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "status_conversion_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
       "posix"
     ], 
     "cpu_cost": 0.5, 
@@ -2480,12 +2540,13 @@
     ]
   }, 
   {
-    "args": [], 
+    "args": [
+      "--benchmark_min_time=0"
+    ], 
     "ci_platforms": [
       "linux", 
       "mac", 
-      "posix", 
-      "windows"
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
@@ -2493,12 +2554,148 @@
     "flaky": false, 
     "gtest": false, 
     "language": "c++", 
+    "name": "bm_call_create", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "--benchmark_min_time=0"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "bm_chttp2_hpack", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "--benchmark_min_time=0"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "bm_closure", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "--benchmark_min_time=0"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "bm_cq", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "--benchmark_min_time=0"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "bm_error", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
+      "--benchmark_min_time=0"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "excluded_poll_engines": [
+      "poll", 
+      "poll-cv"
+    ], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
     "name": "bm_fullstack", 
     "platforms": [
       "linux", 
       "mac", 
-      "posix", 
-      "windows"
+      "posix"
+    ], 
+    "timeout_seconds": 1200
+  }, 
+  {
+    "args": [
+      "--benchmark_min_time=0"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "bm_metadata", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
@@ -2808,7 +3005,9 @@
     ]
   }, 
   {
-    "args": [], 
+    "args": [
+      "--generated_file_path=gens/src/proto/grpc/testing/compiler_test.grpc.pb.h"
+    ], 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2909,6 +3108,28 @@
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
+    "name": "health_service_end2end_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": true, 
+    "gtest": false, 
+    "language": "c++", 
     "name": "hybrid_end2end_test", 
     "platforms": [
       "linux", 
@@ -3008,6 +3229,28 @@
     "ci_platforms": [
       "linux", 
       "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
+    "name": "proto_utils_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
       "posix"
     ], 
     "cpu_cost": 0.5, 
@@ -3264,6 +3507,26 @@
     "ci_platforms": [
       "linux", 
       "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.5, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
+    "name": "writes_per_rpc_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
       "posix", 
       "windows"
     ], 
@@ -5714,6 +5977,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -6843,6 +7129,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -7949,6 +8258,28 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fakesec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -8981,6 +9312,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fd_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -10064,6 +10418,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -11099,6 +11476,25 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -12101,6 +12497,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -13228,6 +13647,30 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -14383,6 +14826,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -15533,6 +15999,30 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -17645,6 +18135,30 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -18677,6 +19191,30 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -19725,6 +20263,32 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [
+      "msan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -20854,6 +21418,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -21983,6 +22570,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_cert_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -24095,6 +24705,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -25201,6 +25834,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -26307,6 +26963,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -27342,6 +28021,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fd_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -28402,6 +29104,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -29418,6 +30143,25 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -30397,6 +31141,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -31500,6 +32267,30 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -32632,6 +33423,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -34670,6 +35484,30 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -35678,6 +36516,30 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -36700,6 +37562,32 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [
+      "msan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -37781,6 +38669,29 @@
   }, 
   {
     "args": [
+      "keepalive_timeout"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "large_metadata"
     ], 
     "ci_platforms": [
@@ -38392,6 +39303,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38416,6 +39328,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38440,6 +39353,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38452,7 +39366,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -38464,6 +39378,9 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38476,7 +39393,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -38488,6 +39405,9 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38512,6 +39432,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38536,6 +39457,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38560,6 +39482,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38584,6 +39507,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38608,6 +39532,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38632,6 +39557,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38656,6 +39582,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38680,6 +39607,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38704,6 +39632,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38728,6 +39657,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38752,6 +39682,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38776,6 +39707,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38800,6 +39732,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38824,6 +39757,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38848,6 +39782,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38860,7 +39795,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -38872,6 +39807,9 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38884,7 +39822,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -38896,6 +39834,9 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38920,6 +39861,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38944,6 +39886,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38968,6 +39911,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -38992,6 +39936,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39016,6 +39961,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39040,6 +39986,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39064,6 +40011,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39088,6 +40036,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39112,6 +40061,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39136,6 +40086,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39160,6 +40111,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39184,6 +40136,7 @@
       "tsan", 
       "asan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39208,10 +40161,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39221,6 +40172,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39245,10 +40197,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39258,6 +40208,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39282,10 +40233,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39295,6 +40244,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39307,7 +40257,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -39319,10 +40269,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39332,6 +40280,9 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39344,7 +40295,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -39356,10 +40307,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39369,6 +40318,9 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39393,10 +40345,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39406,6 +40356,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39430,10 +40381,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39443,6 +40392,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39467,10 +40417,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39480,6 +40428,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39504,10 +40453,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39517,6 +40464,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39541,10 +40489,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39554,6 +40500,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39578,10 +40525,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39591,6 +40536,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39615,10 +40561,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39628,6 +40572,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39652,10 +40597,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39665,6 +40608,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39689,10 +40633,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39702,6 +40644,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39726,10 +40669,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39739,6 +40680,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39763,10 +40705,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39776,6 +40716,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39800,10 +40741,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39813,6 +40752,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39837,10 +40777,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39850,6 +40788,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39874,10 +40813,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39887,6 +40824,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39911,10 +40849,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39924,6 +40860,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39936,7 +40873,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -39948,10 +40885,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39961,6 +40896,9 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -39973,7 +40911,7 @@
   {
     "args": [
       "--scenarios_json", 
-      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
     "ci_platforms": [
@@ -39985,10 +40923,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -39998,6 +40934,9 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40022,10 +40961,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40035,6 +40972,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40059,10 +40997,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40072,6 +41008,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40096,10 +41033,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40109,6 +41044,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40133,10 +41069,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40146,6 +41080,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40170,10 +41105,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40183,6 +41116,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40207,10 +41141,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40220,6 +41152,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40244,10 +41177,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40257,6 +41188,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40281,10 +41213,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40294,6 +41224,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40318,10 +41249,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40331,6 +41260,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40355,10 +41285,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40368,6 +41296,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40392,10 +41321,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40405,6 +41332,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40429,10 +41357,8 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
-      "easan", 
-      "edbg", 
-      "etsan", 
       "gcov", 
       "helgrind", 
       "memcheck", 
@@ -40442,6 +41368,7 @@
       "stapprof", 
       "ubsan"
     ], 
+    "excluded_poll_engines": [], 
     "flaky": false, 
     "language": "c++", 
     "name": "json_run_localhost", 
@@ -40519,6 +41446,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/008d276f01f9371a5956cccf2eeeadb790728a84"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/00a1b8e686014202baacdc052a38d392dff11432"
     ], 
     "ci_platforms": [
@@ -40541,6 +41490,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/00ba96baafa4595f2d41c2fcf0a27f4e9be5c44d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/00c7c2cc7f90842e766645310e4a439e7b188473"
     ], 
     "ci_platforms": [
@@ -40629,6 +41600,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0163bae995fe67a902eabf9f2644726d4767184c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0170e921ff5d052b228a26529116ea47fe9d3f0b"
     ], 
     "ci_platforms": [
@@ -40827,6 +41820,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0242a9f4d4fafc96ee9ed762b610e3c68d6efdec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/02434dcdaca96b9eacee76eb351e99f015eaa05e"
     ], 
     "ci_platforms": [
@@ -40959,6 +41974,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/039c25bc070936901fc95f63ce9cc3058158fb6d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/03eb66a763e065772bbb09e9a55baf081814ff25"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/04.bin"
     ], 
     "ci_platforms": [
@@ -41157,6 +42216,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/053b47093c2145d00b8d53ea58b80afcc876109b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0542a0e5aeb1658cc965724bfced56770569263b"
     ], 
     "ci_platforms": [
@@ -41355,6 +42436,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/06a298ad14533924c9fcb2df0d462c44a206f64b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/06b63ac01c261518e291461fb4707cb29d74e9c5"
     ], 
     "ci_platforms": [
@@ -41399,6 +42502,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/06d20c59bcbeb0deff39619455a713691191bccd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/06eced19ea6819d7b0855c62da49a193b50067ab"
     ], 
     "ci_platforms": [
@@ -41465,6 +42590,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/070aca38b5cd06626dfc98126ef1225595800427"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/070c7005e63abba72c6bc1a0ee6d44e340f2d2be"
     ], 
     "ci_platforms": [
@@ -41619,6 +42766,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/07867ad24a27ff8675dc36a1d8da833f9ee9434b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/07aa7d6c71878eb78b25ca12d79082f70ae7f64c"
     ], 
     "ci_platforms": [
@@ -41795,6 +42964,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/08398518b9b4e98d4625dfb063ab0b6d9399a239"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/08455b3ef9d516deb8155d8db7d51c43ce0ff07a"
     ], 
     "ci_platforms": [
@@ -41905,6 +43096,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0914e4f6ee18c9d15b8df1858a7745b86d875970"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/091f02cc858a89253748b7d1051b8728d0e34015"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/092575ab527ffb459d2e1eed593902820bb462c0"
     ], 
     "ci_platforms": [
@@ -41949,6 +43184,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/095e3fa32a271ef9326d4dcd59fbd003977fdcfa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0963f5f7578c64e9c17d0ad9e4a99ced875cf813"
     ], 
     "ci_platforms": [
@@ -41971,6 +43228,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/096f9413b1bf712e092cf8bd70754014d6242f12"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0976de1461fb037c6987d77d088416440b524dde"
     ], 
     "ci_platforms": [
@@ -41993,6 +43272,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/097f758de0f31691fac6637bf8ac5ac946d5b079"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/09923e3ef02243b1902406c637f9516cbe99d7cb"
     ], 
     "ci_platforms": [
@@ -42037,6 +43338,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/099cc7faaaa2620df22c9bcd6e6d49730e4788b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/099d967555bfc237238c93f9d884c004c773b33b"
     ], 
     "ci_platforms": [
@@ -42081,6 +43404,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0a3f1f614446ded112775bbbc5c61513ad78e12e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0a4b84c2a50ba66f06c99e945912972cdcfc96be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0a71ae781345f9ee2b08008a81f9055e6c1d5256"
     ], 
     "ci_platforms": [
@@ -42125,6 +43492,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0a85889229b729883f4c0420d1a13d9f0a2ca7c2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0a90826e3173642be15ea005c2cbe8ca36ac1c3d"
     ], 
     "ci_platforms": [
@@ -42147,6 +43536,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0ab436006cb2ecd8ecb2400fed982886e4589360"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0adaf5f559e1fb9cd8cd5b29911e13bca315c606"
     ], 
     "ci_platforms": [
@@ -42411,6 +43822,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0c26c7da58087406c491efb8f8f721eb934e6a5a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0c531e03e56a5cf48bdd531a8c11a19e4a3b0aeb"
     ], 
     "ci_platforms": [
@@ -42499,6 +43932,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0cd9696699bd190463ecef91968624601b64cd8b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0d.bin"
     ], 
     "ci_platforms": [
@@ -42565,6 +44020,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0d25b57b2ac671377f8042015896619c09a2f9b5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0d604693a9d3e76f54d28a26142abd729b0a9acd"
     ], 
     "ci_platforms": [
@@ -42719,6 +44196,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0dfc84a6703bdbe9a6acb72e178353d5d69f5814"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0dfd0ea582476b3861106c143c70d7af0f3d1357"
     ], 
     "ci_platforms": [
@@ -42873,6 +44372,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0e7a05178db60007ff4a8dea0e22b60825976c51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0e91ce40cf8882adc75b8b532556d48a2b605ced"
     ], 
     "ci_platforms": [
@@ -42917,6 +44438,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0ec11a92c1830b4c2f56a0979dd9e3c7162bd624"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0f.bin"
     ], 
     "ci_platforms": [
@@ -42939,6 +44482,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0f01df12331467c4eed400465254eda05eaeb110"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/0f10d36e818e41f1737245c2bb8cb83a69421cb1"
     ], 
     "ci_platforms": [
@@ -43049,6 +44614,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/0feaff8d6ad28109f35d6c6080504456b242c8ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/10302aa7598eb36d0ac22d0478eb0f2a6b010ea6"
     ], 
     "ci_platforms": [
@@ -43093,6 +44680,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/10b47823e11c988222f5f778146f9cf922b286bf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/10ee46dc1973472ead36ec4b8a1ea90200637c73"
     ], 
     "ci_platforms": [
@@ -43291,6 +44900,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/122b6fc72956541812dd653b726b073b77ca33be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1239eef13562df4ff59856900eee2f871a2fd0f3"
     ], 
     "ci_platforms": [
@@ -43335,6 +44966,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/128a7ef7f9b87c4f299d3cafe2dfdb9b161756bd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/12a97827d0f817e3ffd8d9cf1bdba0f945b6fda4"
     ], 
     "ci_platforms": [
@@ -43687,6 +45340,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/14ee9fbfe5284650e3a3de83ecc3e09abdc48c16"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1560af88445d6c1e8b1300047f33056dce198e02"
     ], 
     "ci_platforms": [
@@ -43841,6 +45516,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/163cf93cebfb32d617830aa4e69e8b5f59bd3a08"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1661d0799cbf2015fd64e9f648ebb49281d41c6d"
     ], 
     "ci_platforms": [
@@ -44105,6 +45802,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/174ea33060bccea880dfdcfa12c5349e8eb4cb2a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/17582452219fc4a27058a789f416a56631461296"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/17647336806cf94a0224516f3d8caa22367c7c5a"
     ], 
     "ci_platforms": [
@@ -44127,6 +45868,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1776f4c32c11490c65b81d0b7ae2ece4a3d1e9a7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/179817dab786637b3621ace60a9ab4c7c79432a4"
     ], 
     "ci_platforms": [
@@ -44149,6 +45912,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/17a1354d2bfe982e9db1bac550fe01dd105f81c3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/17bc3a2ae619ef05ad35b147f4916c0453ebacf1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/17c7024889cc97a8afd3133b55a147ba75d17188"
     ], 
     "ci_platforms": [
@@ -44193,6 +46000,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/17e562d437fd283e58a5621c33b13191333b279f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/17ec0503991dc248d2b188edfa3d28573a1c2154"
     ], 
     "ci_platforms": [
@@ -44281,6 +46110,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1847f224b543fd0592e9cf365b8eddb61c140d82"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1870298c7042983e7716097018a031d105e397fd"
     ], 
     "ci_platforms": [
@@ -44567,6 +46418,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/19fdd6cdeee7a5cbc991d0e3242c23d5aaff2fbf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1a16a4b32cb0cb3a759ec20edf332cdfc5d1717e"
     ], 
     "ci_platforms": [
@@ -44699,6 +46572,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1b331dfc1d9d535063f0cc6f7a709499a5f8cb59"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1b50ba2e44a359f37205ae476682495cff96838d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1b699132724acab3d42fb5210c07b74343449873"
     ], 
     "ci_platforms": [
@@ -44809,6 +46726,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1c0dc85faed94bb89bc90f87799d7383cf9907cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1c1a1980a1959423766c5a26ac79d07264224278"
     ], 
     "ci_platforms": [
@@ -44919,6 +46858,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1c968074e9dcd8e9922e6c01ecfedcaf7b2fe5a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1c98433d827ea4aae2ba8a68c4d11bc2527cb15d"
     ], 
     "ci_platforms": [
@@ -44941,6 +46902,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1ca16103f5175b0607b579e0c3734b59843e27b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1cae148c387cd20a1742d902543c2c8396589479"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1cbbae18babaa20229b42b4633ef812bd3b40ad4"
     ], 
     "ci_platforms": [
@@ -45007,6 +47012,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1cfd4875b6708b439f1db655abfdd57c1141348a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1d10780f4cb83cb9f6762548ae133d2115c4354f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1d259d9c908db8a0a7012c054bfde7f86474dab7"
     ], 
     "ci_platforms": [
@@ -45139,6 +47188,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1dba0d6c34b03b19e648e2fc9cb3aa7a13e713a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1dd9698ad85c7ab577bbc9b36180ef2641d8525c"
     ], 
     "ci_platforms": [
@@ -45161,6 +47232,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1de191d81c4c7bf0e026bff0a040165c084fd630"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1e1f1e0230004479b502603a1b60552192559679"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1e4a2a6998218ea8f475aa2ee27869207b33b612"
     ], 
     "ci_platforms": [
@@ -45249,6 +47364,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/1f3f61bbe6ea0c7e9b447f134742b3e7909b9198"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/1f4d0adab39a988792cca201626c28293e247226"
     ], 
     "ci_platforms": [
@@ -45645,6 +47782,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/224b2255a1bd250102481abc3e823090650e231e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/226b0315f87b08521c9a2d3e2b50c01ec421be14"
     ], 
     "ci_platforms": [
@@ -45689,6 +47848,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/22c7bfb3460529c77255e9cb82ef8f7d8381f8f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/22c9ed2979d9963bce6500997f1e0433988e7e37"
     ], 
     "ci_platforms": [
@@ -45777,6 +47958,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/23746fe5e477430aec8b12e9d7de0f86f6a6e191"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2378c3f1206f20711468391ce739116ffe58374b"
     ], 
     "ci_platforms": [
@@ -45865,6 +48068,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/247a7d3e0061dd0f32c3f6b2fc43a08e2cc8cf72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/247d0d09deeeb76422cd1d06305a63378a498656"
     ], 
     "ci_platforms": [
@@ -46195,6 +48420,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/25c05b84c4b4f1a93f0f72d368c3c3644b564881"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/25c8a5f8fbaf47c8a398a284008d90d088c652b2"
     ], 
     "ci_platforms": [
@@ -46217,6 +48464,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/26794761df5dc7f093d2395b81a32af5e6b54392"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/26865cd90c1461694d94d96232436372df2a91fb"
     ], 
     "ci_platforms": [
@@ -46239,6 +48508,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/268d8763bb7846f4c9ebb4fbea476a5bc8fcc389"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/26930c35fbe83e4d165b8b7f218ac8ea231c87dd"
     ], 
     "ci_platforms": [
@@ -46569,6 +48860,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/289c2b6211858aa4a46b5b489bc4c9dd47828d21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/28c56acb0f9b47ead49f34c0d92a661fa04952c2"
     ], 
     "ci_platforms": [
@@ -46591,6 +48904,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/28cbfc7c1b760d216cc592a273088b31833ee707"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/28f73943647c3bfbd96e8d1a6188c428b15fdf12"
     ], 
     "ci_platforms": [
@@ -46635,6 +48970,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/28fc3136371b5bcac84045ab6cc93e77298760e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2923d9c864597016358f37ce4014c61648b7290a"
     ], 
     "ci_platforms": [
@@ -46855,6 +49212,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2a4fc709f61977f0f6c75760af2b33007ecd5941"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2a600cae342e8e9e23406bb1e76133f48d936766"
     ], 
     "ci_platforms": [
@@ -47119,6 +49498,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2bb76eff88c5af98c4b8828047837fe97b50cfeb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2bbe5b2c12a964b53a5e6f78cdd5f595d95082a9"
     ], 
     "ci_platforms": [
@@ -47295,6 +49696,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2ce3268455c461a30eb30f4792087df411548c13"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2d03c424dd0677a68f28bb94536f49844d79d00a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2d5613b7bc0f5060eb1fa0449face6a9c503b589"
     ], 
     "ci_platforms": [
@@ -47361,6 +49806,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2d743ec0a0826177cfa7ffb335c0034f482e70e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2d7f42d3df4a206d09a9fa3126333a61f5e678ec"
     ], 
     "ci_platforms": [
@@ -47471,6 +49938,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2dbe958ef23ade1b8bbb9669e590fa99454970b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2dd76fc710e3e78eaf4e5069fa227de678d0830d"
     ], 
     "ci_platforms": [
@@ -47515,6 +50004,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2df7ea9c0c488fc8f79d33b6bce5667a2f051a65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2e21a2f9bff2514667aaec75629c82daa067ff57"
     ], 
     "ci_platforms": [
@@ -47845,6 +50356,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/2feac28b1f508d6086f4cb0972800a77e1d01201"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/2fece42b158854855dd42eac3fc7b8f1eb61fb04"
     ], 
     "ci_platforms": [
@@ -47999,6 +50532,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/30738789e20323323196dd3e6435fa278e73279e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/307a91e344b94923837e01a1657ff277f44db07d"
     ], 
     "ci_platforms": [
@@ -48021,6 +50576,72 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/307aaef3b3982cf8d4780a1f896d5392037c5db2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3082fa77cc2942ae425a6577d1f9c0dddd2949be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/308fbf16b3f3747423b2ff69ef5930b01ca9b728"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/30948ba77c2e56903a9ad5190cc74e59d42f67fe"
     ], 
     "ci_platforms": [
@@ -48065,6 +50686,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/30d2e4b3cac45cbcfe76459c90c49e085914c154"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/30d6ca02d96fe1d1b91b7fa5180789a6cc9d0d45"
     ], 
     "ci_platforms": [
@@ -48263,6 +50906,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/315d27e12f2214a56fb9901dacff14852ff2ac0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/31d8226b1d767fc895e87d7feede0e2d7c6c0b66"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/31ef9c4ed85ae1b4e8a027fc5a1d3037dbbf3b3a"
     ], 
     "ci_platforms": [
@@ -48461,6 +51148,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/33252c0d4edb12370235c0179abd87a5efb59d29"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/33306900f08f0b618c2bf4ba6f6144be9d19cb97"
     ], 
     "ci_platforms": [
@@ -48593,6 +51302,72 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/33d926a04c1868c3393b3129968ffd32049a1c64"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/33e01fe9738c887b159ca5add342b22c13e526cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/33f0e1b78dd158df720604cbb4c9a0c90eece435"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/33ff864434b4f0c0e08c00ec2442cb521e9f79ed"
     ], 
     "ci_platforms": [
@@ -48703,6 +51478,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/34e2445f42fd82c5ce229782a93764def3aae0e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/350a1f6d0fe784667d7ae78e1ed783cdf2263bfd"
     ], 
     "ci_platforms": [
@@ -48747,6 +51544,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/352599b2850ac5a96ec656788c897c4b36114cc4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/35623259c0d5d73d23ea52efc3e4bd808c119440"
     ], 
     "ci_platforms": [
@@ -48835,6 +51654,72 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/35d6503b48b5acc5486a158696ae98a98f46e1a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/35ea066b0fc90521bd8401ef4c52cdc9897d35d4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/35f172b0168cd0b2da4509c3463c2502274e01a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3606c0748089f53e252b577ff7ab2df203d098ff"
     ], 
     "ci_platforms": [
@@ -48967,6 +51852,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3698d88414f52b7c4759bfdadb53161b226faf8c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/36dd4f4239b63b9cf379b354de0dc72e6356fba5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/36dea0ab5bc764c2eb2f428bcbe2786e64da8bd3"
     ], 
     "ci_platforms": [
@@ -49143,6 +52072,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/38259d219a41c1bc60e3867dc60e3473f98cef64"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/383043f6c05edc5a18f5c8e7b9d0314db63eab5e"
     ], 
     "ci_platforms": [
@@ -49275,6 +52226,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/390daee799863cdd0533f35b15b5c0a4f5d79a79"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/39160bc99597105d50cf7a15698090399a2482ea"
     ], 
     "ci_platforms": [
@@ -49429,6 +52402,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3a3346314bb9ddaf14877b653cfd506b6ad34fab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3a4fa4e81b78cae093b2d53b0a6f272a398a7cda"
     ], 
     "ci_platforms": [
@@ -49803,6 +52798,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3c942f9491b1e8b5bb9761a4dbb1bc7165850dfc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3c94ad60589b22d99dd03f98b37c609c180a755d"
     ], 
     "ci_platforms": [
@@ -49825,6 +52842,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3c9a414ad8fcc53c3271bbc8375086d8d1fa450c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3cac139b58decec7c0d1f1318e8f1f28f9650c19"
     ], 
     "ci_platforms": [
@@ -49847,6 +52886,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3cac506501825fadf2e4adf7619d16f72cfd8832"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3cc56c99c6046f0d66c50c4062d90608064fd742"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3cd19f8138a81f242cb92212df2b4812cde8385a"
     ], 
     "ci_platforms": [
@@ -49957,6 +53040,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3d929a8f8e77e038ddaecf9d149189cfeeec30fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3d9534f373e79edd704cc9529600efd62451fb78"
     ], 
     "ci_platforms": [
@@ -50023,6 +53128,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3de19989758b5b68b29af3dfc6c0e55d414dca32"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3dedcaf501bc9718e5d372862b081fc9fdfb3959"
     ], 
     "ci_platforms": [
@@ -50133,6 +53260,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3e82319f1a44ea9224d65feb07ee0ef622709dac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3e8bef87bb89525914b5e7964969a66eabc78eee"
     ], 
     "ci_platforms": [
@@ -50199,6 +53348,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/3f2429e3255ae36fecb57559b57d2b0cb88f5dd1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/3f2e5f90e1a93df61a1c9c09b8c9116149eec526"
     ], 
     "ci_platforms": [
@@ -50397,6 +53568,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4004d9ccc668572796770fb3401376844e1574ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/40640a91fda4e4e42d3063a28b9ffbba1b8c3701"
     ], 
     "ci_platforms": [
@@ -50419,6 +53612,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/409d7e2c0173b5a00a475f79e2fbdbe596d8368a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/40b4b92460c4e76a39af9042fb3d86d491a98e16"
     ], 
     "ci_platforms": [
@@ -50529,6 +53744,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/41bda7ff09175f821992adf4314a8ec3007ffe55"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/41de80653b78b98f5caa7f6d00a96d72bc245068"
     ], 
     "ci_platforms": [
@@ -50573,6 +53810,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/421feb3fe383541082a65a447a51b4af991ceb7e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/42231300ca5cf30d18f55b66020926882c64248c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/42324d3d9e013cd43d4feeed1b48fbe1ea18a732"
     ], 
     "ci_platforms": [
@@ -50617,6 +53898,72 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4239c3636053665277d07bafda37ee84c114b13a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/424b6a20be32318d920d83aa2a292a0aba013a1b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/426b7f180ab26cf276a223246d4d6bd972ccf55a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/427392659bf3a945097c6c754a17d8c15e23816f"
     ], 
     "ci_platforms": [
@@ -50661,6 +54008,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/428cce92c42645f4cc4060a8cb9cef3a803c0341"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/42a8e7c267f66a0747f30b4053ec79325074dc97"
     ], 
     "ci_platforms": [
@@ -50969,6 +54338,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/43cdc82b082bbdc4d7d23437a7f761f1ca32ca73"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/43d52b36766d71176a2fc9f2a4be385bd2638570"
     ], 
     "ci_platforms": [
@@ -51035,6 +54426,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/43f8e0abe3f647350ab1d8d368cca9af6ca47729"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/43ff758aba2eca1e355f0062ca8fa2dcc8edc69c"
     ], 
     "ci_platforms": [
@@ -51189,6 +54602,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/448fc1dc939aa7f398f1577e418630abecc0a1d7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/449ece0109a8543f26311f3ddc23525a2f288b64"
     ], 
     "ci_platforms": [
@@ -51299,6 +54734,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4523e89844538d8de502907f143c35624182f76c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/453861de5ab948236f13ebff66c8e82e4e789db6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/454fb5eab23aacdba559ed9a9a36941732eb3276"
     ], 
     "ci_platforms": [
@@ -51343,6 +54822,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/46171f477d11338f4cc948915350772d54319200"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/461949a48f4f2234cce6bfc1476bc9fd96552c0e"
     ], 
     "ci_platforms": [
@@ -51519,6 +55020,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/46e1492e19d0cffdadc1050cc22d505b4e057759"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/46efabc911aab09a5e7a34a19ef97ce710594a77"
     ], 
     "ci_platforms": [
@@ -51585,6 +55108,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4725b858491e1517af1032efba6bb198f39fd62d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/472adcbc2a1970f2392e596c28bd44087b8f3431"
     ], 
     "ci_platforms": [
@@ -51695,6 +55240,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/48062d4824e8ba697cdd16a46b85d82ff445e649"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/484ab9d070fffe7e3d1a1704c9fa2ce01e192450"
     ], 
     "ci_platforms": [
@@ -51761,6 +55328,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4857011f92ceaed4fee4d7612e1c46930903c95b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/48b3180434c4a21b334d7032ded763ef62b501bc"
     ], 
     "ci_platforms": [
@@ -51783,6 +55372,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/48c1691a919f1055f748e43cd799770f00c1c38a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/48ca1abe666bbf83a81d5c3be2d72017131ca4bf"
     ], 
     "ci_platforms": [
@@ -51893,6 +55504,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/49254390bbc7e7b9eb58ddb1ac54a1e7eacee168"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/494f747fe7c326002c3fb676c35d5dca2e28fd89"
     ], 
     "ci_platforms": [
@@ -51915,6 +55548,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/49d0085058d7fa81247f51b802c0f4206854b4dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/49d816ae44b329820f47979c5790eebc8eadafd7"
     ], 
     "ci_platforms": [
@@ -52069,6 +55724,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4a5a1abe7b402338c625013caa9bc8464a3d0bf2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4a6c8938a8a30567a481599eddfc137fa5454b21"
     ], 
     "ci_platforms": [
@@ -52157,6 +55834,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4ad1a61051d0db46638b774c61392b9d1c360410"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4aecde7ffaea881f42e693858b25c334df711b27"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4b011706723e645407b871241c2c11004103d628"
     ], 
     "ci_platforms": [
@@ -52201,6 +55922,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4b0e9a84edc3eb0e6c377e860f5ecfca1bf64baa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/4b303d7f245a569f507013af0b3afb2f033b6741"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/4b538eda0a7ad5d38b9d95867b7c181cbe84589b"
     ], 
     "ci_platforms": [
@@ -52773,6 +56538,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5035db01a56a34061837c4d0214f6e5112d81ff3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/503649137cea18ced8a57e7c644162bee8885ed1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/507865c4a5ce880b80400d93fa85def2682581cb"
     ], 
     "ci_platforms": [
@@ -52949,6 +56758,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/51716d5683d5c762298fdfa6b57ecf17d6892fe6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/51a2c3035dc5359f9887b588b922faa6789c7ea7"
     ], 
     "ci_platforms": [
@@ -52971,6 +56802,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/51adadd4662ab165a203afdbdbc470b62ac24d36"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/51be7e2267e32f2eb8079349882f8247dc397d0f"
     ], 
     "ci_platforms": [
@@ -53015,6 +56868,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/51ea84d5a790d3d2495be453f5341c41b6153644"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/51ed796a5f8d8fccebe013ccccdc1ed5d8b8b4c0"
     ], 
     "ci_platforms": [
@@ -53147,6 +57022,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/52ac4e5a6c433b7e135e817b797f9bc85d4c619a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/52b5c86f262d46624b2211151a38cbd69c705734"
     ], 
     "ci_platforms": [
@@ -53257,6 +57154,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/536b5c0bf942c03bf9d4a4cc27c97c1230128ede"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5394ae134e9023432ac137789815e2b24d1bab3b"
     ], 
     "ci_platforms": [
@@ -53323,6 +57242,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/53e7030d5de06dcf80e1a60aa467e6e31bec6515"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/53e9f9a4b0347651b3833c3e153e743a1194e0fa"
     ], 
     "ci_platforms": [
@@ -53345,6 +57286,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/54168e5030c8a7cdd58162dee7c2583bb4caaf64"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/541e87b9d3dc75ad40cb47935ed4de83b25af5b9"
     ], 
     "ci_platforms": [
@@ -53499,6 +57462,94 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5547a3544fc5c634024d546366704547dd72cc2b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5559428fa9a1f1701e81eec11a3571be403bf627"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/559d537675dd3fc5e0c6d40e94133e9016014f6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/55a71f74f233ea8ce88967c5660aaa532fbc985c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/55c1b1bd6e532928ad47cadd8e5c5363849d7df5"
     ], 
     "ci_platforms": [
@@ -53521,6 +57572,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/55da9fe903905e9852dedf6b664a4a589efeeec5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/55ed466781b547db5957233bd8db0ce1f189183f"
     ], 
     "ci_platforms": [
@@ -53587,6 +57660,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/567026bafbad3be6a7bd430577e7d39ec3d56af6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5677b3500e9353856c8d87fbe1476a22df4231f8"
     ], 
     "ci_platforms": [
@@ -53697,6 +57792,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/56f240463ef197b49c7e271e74412f62909974dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/56f3ca8174d263240113de88e7547e7b1c5cb2cf"
     ], 
     "ci_platforms": [
@@ -53851,6 +57968,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/57b087d753a6af79c0b58ca2c9aa5c92bc18a6a5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/57bc1a4501ceb31b4ead1c2428798be073eb9db3"
     ], 
     "ci_platforms": [
@@ -54181,6 +58320,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/59b547627a6b1aef96f6c5e3b7dc08c3e1244368"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/59db3f98b38747d4a35524c1b3d31b5e90f53775"
     ], 
     "ci_platforms": [
@@ -54401,6 +58562,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5ac0e42338f7b064f5c23697f1174a10b42e7ed8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5ac8cb08604c86b9e8ca24482ca963eddac2efbe"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5ad89e10b538191d22187503233223d2e520d80f"
     ], 
     "ci_platforms": [
@@ -54511,6 +58716,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5bc4eddc2a2881d4b6b4f9532f4fb381e4cc9529"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5bcde4a99b8ad54a5b8ba9b5131842c6c7c0ef19"
     ], 
     "ci_platforms": [
@@ -54533,6 +58760,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5be0001be32d9e619769c7cc6cb9f541efe4996c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5be956066b72ea1799e333a7bd17fb0b8fc2b91c"
     ], 
     "ci_platforms": [
@@ -54643,6 +58892,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5c6debdb92eb9089773cc8d092d7f62d521ae029"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5cce719931cf1f07536401134de4325b942be87d"
     ], 
     "ci_platforms": [
@@ -54731,6 +59002,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5cfdc00a568d97b09e720a72eac7e5fbbf76247b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5d0137a19ae57cfdf5172a8b51e8ea0a0a893690"
     ], 
     "ci_platforms": [
@@ -54885,6 +59178,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5da1a1a4ee88d2a2b6e9470dd7be9e2dd9eecc4d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5da437d4fd58607deeed34bcb21accece71a056b"
     ], 
     "ci_platforms": [
@@ -54951,6 +59266,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5e0c4179d297f5bafe86b9e256bf75d54cfd1fb0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5e1391f44f904fa54e66ec174e4c8879921e842a"
     ], 
     "ci_platforms": [
@@ -55105,6 +59442,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5eeb786fa5735ef9b98c40e205f2eba24223acfd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5f07e5246d765494ee26c689072ab3ced452f30e"
     ], 
     "ci_platforms": [
@@ -55149,6 +59508,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5f3a4ed52525d1db60b45d79057a6e276395e562"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5f52309deaa1b641fe199889d18f921d6909fc14"
     ], 
     "ci_platforms": [
@@ -55215,6 +59596,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/5fbffd9d324ad078bf6f5fdd39e5e4a27afd5965"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/5fe822a742cf2f5328cec86c0972b0c7b4bd4460"
     ], 
     "ci_platforms": [
@@ -55281,6 +59684,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6042b1bbaf3ceac51c11a472ea07a75e822b7bc5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/60ad6847b1fe72ee81decf28dcffa30ce372af6a"
     ], 
     "ci_platforms": [
@@ -55303,6 +59728,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/60b4c79213b97204d1e4f6819ad1ed5f6e191789"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/60e8618c075ec5fd47a1699271c6da1b5befd579"
     ], 
     "ci_platforms": [
@@ -55325,6 +59772,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/60eec02f3b3aa23b12261ed00163d122b24ab5af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6108ac96de85e973db42982eff9d2f877a36699d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6123f6116f3cacb4aabdbe26aed24ed0981d6c1c"
     ], 
     "ci_platforms": [
@@ -55347,6 +59838,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/614dbc86b17270ef1d5ab705ecbe88c742815ce7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/61614f406af22aa805e6a2cfb24519ffd058d575"
     ], 
     "ci_platforms": [
@@ -55633,6 +60146,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/62515c0e559e40838126e5be6ede5440875a3f70"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/629eac0e7443a273b5c351757c03fe15a0b87c1c"
     ], 
     "ci_platforms": [
@@ -55875,6 +60410,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/63f1e7c7eb4d0ee635c3794993d2e2132cba72d4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/641739453f7d4d3b55a1c7b79bed7da6dfd62ae0"
     ], 
     "ci_platforms": [
@@ -55941,6 +60498,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/64656ddf81738f914ead8003c19d0148c54f34d6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/646c501021c79bf6eb1a39a9bcc82e018f31bca2"
     ], 
     "ci_platforms": [
@@ -56029,6 +60608,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/64d1666dc1b1126bb99e3792040dff64b336ae36"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/64d410e245db26eb7996c20bee1e3dfd77c43ebc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/64d55e872c2148eefb0d7c3df101fd955b709f24"
     ], 
     "ci_platforms": [
@@ -56381,6 +61004,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/671d63b9968444308d4908eb6a26bccdf32e5e29"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6722929b4924f4d50ccfb999460e9a31ca104b4c"
     ], 
     "ci_platforms": [
@@ -56425,6 +61070,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6757865ccfef9bf8f1ba4302be9767758390fa92"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6810347353fd417add645af90476310bbf572788"
     ], 
     "ci_platforms": [
@@ -56447,6 +61114,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/681b758cad3bbce4bde2d1a78a2ec4600c59b05c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/682cb8ad9fe4641e7a140ae3d3ee27c841ba397f"
     ], 
     "ci_platforms": [
@@ -56491,6 +61180,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/68359027351be494040cc9ae6d4ccfc248fe6fcd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6839920a4e7e998a8f30e6679934b91a819bebc9"
     ], 
     "ci_platforms": [
@@ -56645,6 +61356,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6951632faa6eee58b6480b7cae00ee8ea1223658"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/696ea30e2e1490f2f31b153641b2c29152ded5c2"
     ], 
     "ci_platforms": [
@@ -56667,6 +61400,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/69c6c28a67fe1b5ea32cab0f06564c59ec3fcbab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/69d0f8b4a9452d11620c7d3c1fa532a618d65858"
     ], 
     "ci_platforms": [
@@ -56755,6 +61510,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6a2b1a1222017169ff83695bb42bf760c8126a2d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6a3dee1cefadc15954dafe424c73b78a3b5c1b22"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6ac88da4119df5e1592a05bac7ecb92af59dc1d1"
     ], 
     "ci_platforms": [
@@ -56777,6 +61576,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ad3a1170ef884a884a6f340101549df624bf5a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6ad7afcf2d12025faf0e1812ee7a0a5d754620c6"
     ], 
     "ci_platforms": [
@@ -56799,6 +61620,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ae25d59c9f771291edddc6c71d01c855883b99b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6ae8b3afc4f6e3a26fec5eaeb2bf64727927552b"
     ], 
     "ci_platforms": [
@@ -57129,6 +61972,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6cb17148d52be437332b6fd6f2fc8328bfb63fb0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6cb9930369caf7584015d3a17c37e144d23b79ce"
     ], 
     "ci_platforms": [
@@ -57371,6 +62236,72 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ea192b1d4c4577ca7511f8ce5027b31b2e0d75d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6ed943877a76ab6b17443e5b194012d9008612ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/6eef551288136e9fb2d9de210b14148746203472"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/6ef96bc0c5b6ab5f8a4453b9cf5784fd55e3b59f"
     ], 
     "ci_platforms": [
@@ -57789,6 +62720,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/70cf4c8bdd833f8c62d8c89ef50d50008457f5ac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7108fee873f0120d41f469944cf1e24bd33ad684"
     ], 
     "ci_platforms": [
@@ -57855,6 +62808,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/71403746b8e54a5f9b6fa1882a7ff5322180dd01"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/718d23058d5c805a2984c087cd89f9cb6af065b4"
     ], 
     "ci_platforms": [
@@ -57877,6 +62852,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/71961e53698b07bfd57e9ea37067e0dd52298a3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/71a0dd688553c753919c58d00c8e8db130726b3b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/71c01818823d5c5fd8a3d1cb4c5db4aca51efdb2"
     ], 
     "ci_platforms": [
@@ -57899,6 +62918,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/71cbd5e4e98344dd16df8b21546439cdb0879e0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/71e2b03b503dbbdc0d2e724c562b9f1c77f972fa"
     ], 
     "ci_platforms": [
@@ -57965,6 +63006,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/72031f24261c32d2e3bb2c7909a9315227172730"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/72160b48e0995ee82f116d77a7fb23a028c10932"
     ], 
     "ci_platforms": [
@@ -58449,6 +63512,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/746477e7e8f093f87cb6924ab6476cda9689607d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/746d9837f0fc3c989b7fe0585b8365478f1c21fc"
     ], 
     "ci_platforms": [
@@ -58581,6 +63666,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/750668bd25d3c4d5c8ff863185749d31978b88e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7515e494e0ac5d2d3b53151b3d10bfcf81578c99"
     ], 
     "ci_platforms": [
@@ -58603,6 +63710,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/755e5b679c1bb2720590e166d5047588a0e2f8b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/75652d3d4f913e10f7edef130e3d82a03b82247f"
     ], 
     "ci_platforms": [
@@ -58757,6 +63886,94 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/75af1ed0b83b24a1d5201038a4b382d0ace6222f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/75cd5b751f530f494c224304b4024d490032e65a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/75f9b79cacbfef018bb131af2e2ba0735b2640ec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/76116b26156d91b16a70f28a126ed5f05ce55548"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/761f683f6486e3efb606bf08fa527a4c1a51f302"
     ], 
     "ci_platforms": [
@@ -58823,6 +64040,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/766995b9faa25c3b2c825413e5e9a702721de7fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/767c4f399ccca740ea3032eeade86851f12e7f9a"
     ], 
     "ci_platforms": [
@@ -58977,6 +64216,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7752153d87017b85112a49ea95aa25ca78d24431"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/77662d88e025c080212dd2dc4dd2030810926f40"
     ], 
     "ci_platforms": [
@@ -59065,6 +64326,72 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/77f4f436f910c45f216fe4d3f9b631612ed09cf6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/780fc96dea7f78bb9d1a074efbd966b03d78d653"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/783484ad9e15085e9039c7504aac71af1ad549a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/783b1f17ae90eba0ff7728e767b56ea6885e0b28"
     ], 
     "ci_platforms": [
@@ -59109,6 +64436,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/784ca396c157df8ba93bbe1e12c6d32609ef05a1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/784d6f5c093ab5360670173ce001e1a446f95822"
     ], 
     "ci_platforms": [
@@ -59197,6 +64546,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/78e43d163fc8226d72b979c0fe6e1593ef3cb542"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/79163c87e1c3340d05799cf27f1e898a932d1001"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/792276ed826b9078ecfbd51e0136962f5e10ed6e"
     ], 
     "ci_platforms": [
@@ -59263,6 +64656,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/795912f4ca380c73a3a3c956b1cba1e9051d92bf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/798e448161e03d40712655f913464a276b6d6129"
     ], 
     "ci_platforms": [
@@ -59571,6 +64986,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7b3a99b69df9931fe12dfce5d8c5153f43bf4fd9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7b44a92a28ff5c96be7c4dae5c56a9e5fa272ad3"
     ], 
     "ci_platforms": [
@@ -59615,6 +65052,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7b5a71e770bf9eed928f5e552a7659f8ad8a8b84"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7b747e0fabbfae7ecb4e9e8261121aaa42a21cc2"
     ], 
     "ci_platforms": [
@@ -59923,6 +65382,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7cae7e5c67636a72a00785e04cc55af57b9e1318"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7cc958be492e942df2b784fcc08a63d57c7fef92"
     ], 
     "ci_platforms": [
@@ -60143,6 +65624,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7e75ea44aa7347c2f827beecb27e3bf5b1907b8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7e8f7517bb0bb95011b48f1f4f4a631d4d756a5f"
     ], 
     "ci_platforms": [
@@ -60253,6 +65756,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7fb64b5785ebe699ca50327c88c1d8b99432fa23"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/7fe27d0f43c09c4070f479163e1479440c4bc7cc"
     ], 
     "ci_platforms": [
@@ -60297,6 +65822,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/7ff449b555102deaeea7245b5a370dd0820d2691"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8005d0a23f43613949321e9fc761180cdcd569c8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/801f08f6085a2986fb868d326c71bdcb16df1481"
     ], 
     "ci_platforms": [
@@ -60319,6 +65888,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/807a48bd33ce375438dbc158c1531891c5b54a51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/80a249d17248e0dc7dcc9fb64d8ac2dd0320a544"
     ], 
     "ci_platforms": [
@@ -60385,6 +65976,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/80d4266aee0b8b7dca74696dde949ebfaa052535"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/80ecd5087801e974eae7db730a496d2aca110648"
     ], 
     "ci_platforms": [
@@ -60561,6 +66174,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/817570ac3bbeab63961d78aa2fef496e87c7e056"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/819cac3befd0d7b12ffd734c26df1cdf43c376a2"
     ], 
     "ci_platforms": [
@@ -60693,6 +66328,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/823ef8523d3d3d90578d32e09e6822eb9ed42ecf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/826c36b53a0f249c139de4aec6fb113a70af3b6a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8272e45483cb4cc7113b0ffad71f9218542f9cd7"
     ], 
     "ci_platforms": [
@@ -60715,6 +66394,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/82731abc38788755495b1bac7b58bc0f12e4bdd1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/829a44d34a4c591b8808aa5eb283869e0fece45b"
     ], 
     "ci_platforms": [
@@ -60759,6 +66460,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/835062d78983dae5747ab4e207d227869ce90733"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/83566906d8ca1b2296d7d9042e1196a1cf69ab9c"
     ], 
     "ci_platforms": [
@@ -60781,6 +66504,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/83776278a4997b0d178602c8419f3e6481dec01d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/837db5272d730107ae362fcd3cb2c21e5f1ea53e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/839b0cad1196be563cec8e8a55184fc001b8401a"
     ], 
     "ci_platforms": [
@@ -60803,6 +66570,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/83a2a19743bb77278aba8cce1d04529d2cb0a744"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/83b2491b16c26c0dbb6aef5a9df10a3fa83beea2"
     ], 
     "ci_platforms": [
@@ -61111,6 +66900,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/853a546c5435e9eb9f2d13898755abeaf93d51b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8554d0f8fc68c84fbd8515165a3d98aad0dfab3e"
     ], 
     "ci_platforms": [
@@ -61243,6 +67054,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8644486ad9579f43b8c6f34b423c2c1159b20a9a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/86906b52f5fdad0955f5a93dd26ff420e4a58078"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/86bac2d397ae2c0c178171f1f9daf7a8603c6d7a"
     ], 
     "ci_platforms": [
@@ -61463,6 +67318,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/87a34188d51bc8b43bd7d9097958097e70154960"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/87a4605e106399e71e689468a23ba11e7f17de2b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/87add83a18a25fe585df8adc124eae6d70733f74"
     ], 
     "ci_platforms": [
@@ -61793,6 +67692,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/89cdf2f9a9682277284c24819a0cd336bbb04d60"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/89d8350297ce5dfc2a69e6e96afc86dba2bc3548"
     ], 
     "ci_platforms": [
@@ -62035,6 +67956,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8adec341bcbd14fb0bee52926141a4a5b3a885e2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8b00c51372acb33d4714fd7e012749bf44cf7b3b"
     ], 
     "ci_platforms": [
@@ -62145,6 +68088,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8b43d6ab6c1034fba9757ce801e237da089f1898"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8b53f252f8558726dc0daaee84e2b4d2f0835f44"
     ], 
     "ci_platforms": [
@@ -62255,6 +68220,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8c00268431d8fb83ee306f0a49bee4af8728c0b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8c395b9251d60823ef14014f6ad58b29968a1681"
     ], 
     "ci_platforms": [
@@ -62343,6 +68330,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8c5d9191880e9753a747e7ccd7824483bcd7568a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8c6776521d0f100708ecb9f8504e572d586b8a21"
     ], 
     "ci_platforms": [
@@ -62365,6 +68374,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8cbb67da0e40816cf4bedf4fa6ce176563fc0487"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8d1242821c2d5fc81c8e0b397d91cf75cb1b5f2c"
     ], 
     "ci_platforms": [
@@ -62409,6 +68440,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8d54be1edc097b319d26ee1a08b1da06bafd0bbc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8d7bb385d6b13b0e689a1e81e29113746218ba99"
     ], 
     "ci_platforms": [
@@ -62541,6 +68594,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8dfdb04ef558fba84dcbfa65a6aa318b10988fa9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8e226a7f67b7c6e9d439c3627bfa5644af992593"
     ], 
     "ci_platforms": [
@@ -62563,6 +68638,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8e49b880f6e9514963c8f82bc6c7131ab104200f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8e6332b7d5234f6a1a153f91131ea33f0a5535d8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8e94dd64fdbf453f06b351d6a8f77a43cc34e4bc"
     ], 
     "ci_platforms": [
@@ -62607,6 +68726,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8ea9969bced02fd855c7de7edb12f074226f6dab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8ebddbd256887fb5fe1be69a46023b34f815d2e8"
     ], 
     "ci_platforms": [
@@ -62651,6 +68792,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8efa9ad7c934a3c3cc01470ee1c21d7063f7b209"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8f332e450d6a489fed2627f387cf0d0db7bacd37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8f4187ea7f2efbcd933fdb2b0652b71ecaff7822"
     ], 
     "ci_platforms": [
@@ -62695,6 +68880,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8f71f51eba1aba1d839b19801c594eab968a892e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8f840f0a04cce56098d395939b446589ee67da0c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8f8b66436bade06813ec9ed4fce6774914b73db3"
     ], 
     "ci_platforms": [
@@ -62717,6 +68946,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/8fba35a2ec8e2eb182eeacd23592c92932c64200"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/8ff5277cdbe1417da64bfdb342747a23f5e4f956"
     ], 
     "ci_platforms": [
@@ -62805,6 +69056,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/902ad49db6c0518017e8438d1ee61e0841fda6e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/904edc7bb14e4da0172f3d58a74c8abf141da9fb"
     ], 
     "ci_platforms": [
@@ -62937,6 +69210,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/91236da3b95886937ab487700d8c72b40e6b9477"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/913614cd0ae1b1210d2f1bc354b876080726f7a8"
     ], 
     "ci_platforms": [
@@ -62981,6 +69276,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/91491f410776eb726c8a5face925c703737ed916"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/91980bd25cd4827c2e0c9ebb028d03ef226d0e73"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/91e2f574e7ceb7f69a93011aac68903cd014a6c7"
     ], 
     "ci_platforms": [
@@ -63135,6 +69474,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/92c816d98f9f8669f43b46b22d5da21464d9ef41"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/92d44998655e82d89a614c7b6a2f08c5fc7f8805"
     ], 
     "ci_platforms": [
@@ -63245,6 +69606,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/939a61533db8868591c514fc41c7dfb4232e3e4f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/940a622e8995529f6b0455906d8a035902682d2d"
     ], 
     "ci_platforms": [
@@ -63289,6 +69672,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/943924f902d02a4358ba2ae693087033d30e862b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/94571a4b13c435117ef9bd914443ce9a07da8e3f"
     ], 
     "ci_platforms": [
@@ -63311,6 +69716,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/946f3ee9686789790301935574f412b9cf5cdeec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/950511efda7aea60b3bfae95e31683210a88792c"
     ], 
     "ci_platforms": [
@@ -63355,6 +69782,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/958d48d95d2c2ff8b177ebd2149b9d9a89908f48"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/95940316e7104e9c2d5123b31e36b2dfd12fcea2"
     ], 
     "ci_platforms": [
@@ -63421,6 +69870,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/95e73caecc0ab06beaa9b84125adcb2e6eee2eff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/95f223f8964d294aafc2a6041a83cfa7761c31ab"
     ], 
     "ci_platforms": [
@@ -63443,6 +69914,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9625913195b7d7a5337016e8f9a29c8f3d6ad435"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9629c00d91e6146b29f7559a944e6bf8dce7d0f1"
     ], 
     "ci_platforms": [
@@ -63487,6 +69980,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/963c2fa0d8197bb8b6c7bbfcb43a9ae1ec29f2c7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/96a6293d4fc97c75f037bdb0f73dc5b62bbfa2e6"
     ], 
     "ci_platforms": [
@@ -63553,6 +70068,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/973f74081ad8c1d91ad1b0bfc10061de72d1b1bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/97440beca022cd5799f76654d8bec51f62c0bbaf"
     ], 
     "ci_platforms": [
@@ -63575,6 +70112,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/974be67fe5188cfa77f7db943dfdaa0a4a2c4e82"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/97539b673cb482cfa4d876df515270611b28f22a"
     ], 
     "ci_platforms": [
@@ -63619,6 +70178,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/976ed70e538943fc60d5b339528c70a69161d6a1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/97817475213736527fdc3b2a28cd45f52fe4ce1a"
     ], 
     "ci_platforms": [
@@ -63641,6 +70222,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/97b87b4a9d1846c2f2277f7291c545be955257e3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/97d261c920f2802c97343e07847c98afa3ff46a3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/97efcb1f37032ebf01b4b1065a9df66590b7051f"
     ], 
     "ci_platforms": [
@@ -63663,6 +70288,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/97f7a51a0bb869d09f9f1bd7a4f93c5d859c89eb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/980f0198dc66e867b1a5d04cf24bc02fbdf3b839"
     ], 
     "ci_platforms": [
@@ -63839,6 +70486,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/98a661d328f1ad6277c802604126d91965d6fda8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/98b88c0751f1d9e5dc3d4751d2cb52ed8f0b008d"
     ], 
     "ci_platforms": [
@@ -63883,6 +70552,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9916b65305d28acf75a17495b9f44d7b839b948f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/99789b6e9a0932dc95b686cf380872175603918f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9989534524a212092e9d7fede16106b586c434f4"
     ], 
     "ci_platforms": [
@@ -63927,6 +70640,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/99bb7db7244a6cb2bc0e6c275739f051f83b335a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/99c05d9bb9dd3b8205330e5265bc7dd94bcf87de"
     ], 
     "ci_platforms": [
@@ -64257,6 +70992,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9b922c2b47217bbc8c91fce66fc666d626cee86a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9bbb726cd811fce33aecdbcce3d287c252ed71d5"
     ], 
     "ci_platforms": [
@@ -64345,6 +71102,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9c052499ada417d5038f8cc7da62e6acae9ba9ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9c0911c1a4b91f842670082c14af67d1f4b7bb6f"
     ], 
     "ci_platforms": [
@@ -64389,6 +71168,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9c78f9e53f09be45b2dac44dc8452880e7bed04b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9c837f4e6cb572b3431b3a5065b889273712810e"
     ], 
     "ci_platforms": [
@@ -64411,6 +71212,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9ca8f5c67662fa6726db2680978e443d80785a9f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9cb91ce75745cc30995b8985a35ea31db766e54c"
     ], 
     "ci_platforms": [
@@ -64433,6 +71256,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9cc4eeecbb2df8b130cca5e455a0f6b8a6e00660"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9d004fd9a35647ba7ec169e6fedbf9dce5f9623f"
     ], 
     "ci_platforms": [
@@ -64455,6 +71300,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9d43466b9c4b8736cde82e337d9a9f881db82d11"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9d5d9a28271a6d21850feb249cfe27aa0a31130c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9d69b6fb15c861c294878da8aaf16a531dfb1b70"
     ], 
     "ci_platforms": [
@@ -64587,6 +71476,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9e273a94bf3c60f1c7875874c81d0b9309428752"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9e48b3aa2c25dbbab21148bdac91b5169ce088bf"
     ], 
     "ci_platforms": [
@@ -64741,6 +71652,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/9f1c4ea38c9fb86a62693f202b26b1be3c7b2d37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/9f1db4144e46f913ca02e0abe2ccd5c7481e2a92"
     ], 
     "ci_platforms": [
@@ -65225,6 +72158,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a1f59f79257ae56e6e6039d3fe838ca050f40385"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a1f6961a480f1eb49b394118b05b9cdabfb6f0a3"
     ], 
     "ci_platforms": [
@@ -65247,6 +72202,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a2180525f267c6d6b8f7501b100b97aef0d87f83"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a25eb9c166a097ea3afa590e3584eb9986bd9445"
     ], 
     "ci_platforms": [
@@ -65269,6 +72246,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a270e4304cc0dcd2c67b78c0495dedb10419f0af"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a2ac5153026b26fcbea42786e238b15017a684be"
     ], 
     "ci_platforms": [
@@ -65313,6 +72312,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a2d2b12575edfb559872c4f2ce63e95fdf68b774"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a2eb6f5e20c5171e7144f177d296eb00181ce461"
     ], 
     "ci_platforms": [
@@ -65357,6 +72378,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a31a10de37eda6db8ecc2270b6a368985a38a44b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a3469cc29207d27c818b2299bab7e7c5dde3ffaa"
     ], 
     "ci_platforms": [
@@ -65665,6 +72708,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a4da7f4642cfaf355445834075d3b4d04cf8b218"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a5089985010ccfa7630185464308aa5247f55de1"
     ], 
     "ci_platforms": [
@@ -65709,6 +72774,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a5be9b0f094ec76d5f082f4e06dafb5a01c066c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a619bb6ff4871fab3045e46bef8036f80d605f37"
     ], 
     "ci_platforms": [
@@ -65731,6 +72818,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a62651154d1e5c33e154ea4b57f042be89feed9c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a62960425c597cf5d2bd38e9412363991479837f"
     ], 
     "ci_platforms": [
@@ -65797,6 +72906,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a65bda38b60ae084a5dcc3b616660aa338feef17"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a660e999019a7dd3e950b51d6fa8f453390fb504"
     ], 
     "ci_platforms": [
@@ -65885,6 +73016,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a6a11f05565197ecb9cbf3a2ddf826564b425e74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a6f614d434a1fe2162f7872100baef21b2051b53"
     ], 
     "ci_platforms": [
@@ -65907,6 +73060,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a71ab47d9ad32e10acc8b9772a331cae045fb424"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a736ade657d046ea859cf50fe1ef044e02ca38e5"
     ], 
     "ci_platforms": [
@@ -66061,6 +73236,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a881a2dcd16f595644c1543ccf047b7ae5bb7fa4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a89d59f59e43670ca3e8baf454fea723ae295653"
     ], 
     "ci_platforms": [
@@ -66127,6 +73324,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a8c0a166004ee637f22f5838960c8f4320738694"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/a8c9f7043c578e48be49661be5207ceb9ec1b61f"
     ], 
     "ci_platforms": [
@@ -66303,6 +73522,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/a9e6f164e912d8964ae28f383dca6d980dcd4b94"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa05527f894960d22773d0e1c96e8ad9293e3910"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/aa0c7fda7faff932bf36e10d15ab2180ab1bca27"
     ], 
     "ci_platforms": [
@@ -66325,6 +73588,116 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa103991d1d90adf0af592c050c1d39532690f73"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa26dbb6bb031702e07e82a70162de89e31dbb60"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa2b2a1240b9ddfba14035695084096f93a4eea5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa58c60840b27f80a9779d2f4fc76154e12b7dc5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa682b09b1e785fe0ed7edc6b14a4e8e5282e043"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/aa6e8ab6cab71f0d7fe316a19c47fbeba5351315"
     ], 
     "ci_platforms": [
@@ -66347,6 +73720,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aa7e9b09e36bec073300d107795b7dc63eafbeb9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/aa926963580066aa503c5433dad9889fabc4ee08"
     ], 
     "ci_platforms": [
@@ -66611,6 +74006,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/abd5de7b5e9218d19a57c47d2ccd6a1bc022c7fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/abdb7891569085e3df0f6c7a5348c12bf3dd1ae0"
     ], 
     "ci_platforms": [
@@ -66743,6 +74160,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/acb33ec3207ddd5f641f8f989faa888bcc70385c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/acb49fc7f5d61f15e2e0b8f391678365381c5ab9"
     ], 
     "ci_platforms": [
@@ -66853,6 +74292,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/adc78556e789c046d7f82b77e967a9e7fdf6cdac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/adf1ecc62e1089054db8af9e380cd77323b62970"
     ], 
     "ci_platforms": [
@@ -66875,6 +74336,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/adf88d50a752961142e1a3fc4eeba380e6089a5f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/aed35edde0a0395829c43b45a34f537b9c6fc23a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/aee8da0d3f1d4f3c54bfefb5d53df17c6740fb37"
     ], 
     "ci_platforms": [
@@ -67007,6 +74512,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/af9d0bbc10db557c0ef9ab55a6f217b4f76a87db"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/afd047f5586f07990fa2efd6c67d3a7c55099c53"
     ], 
     "ci_platforms": [
@@ -67117,6 +74644,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b09e64aa807db006a219bd1b9faf1a2e00dc6d33"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b0c9bc430c79f064b61d8cad076b072c9c014804"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b0ff62377b87b846f720a70f0b7f7bdc76aa1315"
     ], 
     "ci_platforms": [
@@ -67227,6 +74798,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b233e6287f4208a2ae8f89fe25caf0a33b7b4e51"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b23f1233d0e21c4aaaebe2fe5931903698b2408c"
     ], 
     "ci_platforms": [
@@ -67469,6 +75062,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b36c3e5841c6aed7b0d439bd3b9c6d922d56c70b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b3776ef844b4910a2cd6d149dc13fb57bd523ac3"
     ], 
     "ci_platforms": [
@@ -67557,6 +75172,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b39f27387a256019038cddb91f65651c01afb825"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b3b9e307ce3af6fa515a33668374e15fcc909ae5"
     ], 
     "ci_platforms": [
@@ -67667,6 +75304,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b4b0f04d9a771ea9575d9cc484947fcadf4ef5bd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b4b8ba878466fc6c4e1939e38c38aa64026b055b"
     ], 
     "ci_platforms": [
@@ -67733,6 +75392,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b501cbf4c085ce0b75e4031810bf99f91905fb06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b51853fe4f799f7f959922fda1b3500668a45157"
     ], 
     "ci_platforms": [
@@ -67799,6 +75480,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b53a90f0ad5e8026e0354e149ed8b4782fda00ad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b55d66dbf3f2b795062e5a53379c2f63cab17062"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b56db2235df5a81ff15d0c07612de7eee0272304"
     ], 
     "ci_platforms": [
@@ -68041,6 +75766,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b6f721156f8dc6a353555929e459e61bab8b394a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b70abef1bf2c649cf31720136a099a88cff8d562"
     ], 
     "ci_platforms": [
@@ -68305,6 +76052,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b8845fbdf002c64053d7fa3e60add56f0a030992"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b88619bb22a3b2585cad3ace194fcdd8c6b63104"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b892c064b2703ac0dc31766946be487b197a541e"
     ], 
     "ci_platforms": [
@@ -68349,6 +76140,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b8bc377e53ca54ae4e30f437b69e270040c35f65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b8bedb9c38fd149bc494a65674a4af5e61dfb311"
     ], 
     "ci_platforms": [
@@ -68591,6 +76404,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b94e1db2cd1236075bb8772b72c64991d442e584"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b95899d40afc4b3ff87af2285b61ba66939873fa"
     ], 
     "ci_platforms": [
@@ -68679,6 +76514,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b9a7faa77ddf3a7e206e4d06f5d9d8de7d9c7df8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/b9d799eb148e4d8a8a235e385ca8302a8acc3896"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/b9eb50c5eb99cf0b419efa2cb8d7fdf2e71f6634"
     ], 
     "ci_platforms": [
@@ -68899,6 +76778,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/baee7b89cd2017f450c37137628688f25979b3bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/baf7b33805daf027e037e406d3442b3444108ac0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bb2affdc830241ebea35795fed3bc8d478330eec"
     ], 
     "ci_platforms": [
@@ -68965,6 +76888,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bb426bb115461f351e57f64c0378e331f74ed5fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bb54fde05891ecc235263ad087cfd9682a25f76d"
     ], 
     "ci_platforms": [
@@ -69031,6 +76976,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bbb2429766a7c4ef9cb7110d567fd48cd6507dc5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bbf053837b7e0e2adc868be62fc91248b8dce176"
     ], 
     "ci_platforms": [
@@ -69097,6 +77064,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc330aa616a792ff22a8c7428dcdb4d99accbe4b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bc42e00a7d67fb68df3cb5893908c04884b6ad5e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bc5e743f85f6632110277f09847381a402e1624c"
     ], 
     "ci_platforms": [
@@ -69251,6 +77262,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bcc655cbb7334db02fc7fe9d29bd49fd6ee4ee91"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bcc7eb464ff05cd0cd2669611776e55ca4dcb2b4"
     ], 
     "ci_platforms": [
@@ -69383,6 +77416,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bd4f7f4d43ceaec0429ddc248cd438284813cc64"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bd585e031f586c4313c6b00e5f247f6b272ce902"
     ], 
     "ci_platforms": [
@@ -69691,6 +77746,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bed4e119b86e8dd0a6c60cb96cc2f9e66d0a8857"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bef8cedf1a792786a027114c85a89a1bef3155c4"
     ], 
     "ci_platforms": [
@@ -69779,6 +77856,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bfafd0d497ccd035d6ef1478509c93a9d2443513"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/bfb3ae60341e80c10de105fa0f9a01f134033225"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/bfe2840aecee88c5301aedd16a6ac8cea0262005"
     ], 
     "ci_platforms": [
@@ -70109,6 +78230,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c1e5524945b3e3eabedfbb675be9e9ea99a36b94"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c2006fdf68d2a4cc0b31410d00e4dfca59315e85"
     ], 
     "ci_platforms": [
@@ -70197,6 +78340,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c29f3256e632a713aeb3ef647fff014a9be01a8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c29f63aa5c4462b359c9028b6e6031dc088d7d46"
     ], 
     "ci_platforms": [
@@ -70395,6 +78560,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c41f43520da236f84dd0e2157644d316ca6fac37"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c45cc40cc387134dec06733a01bde8fc44a2c9d9"
     ], 
     "ci_platforms": [
@@ -70571,6 +78758,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c5535d6d801d315d78792c9956a82711d0d5a803"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c5590a6799d6633ba08cc1f75e1a7d0a54d37e68"
     ], 
     "ci_platforms": [
@@ -70879,6 +79088,72 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c6ec8562082eda6ea9ae1cc27f33b920b93589e4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c6f9e7ce30494ccbf3a1f49bed7107d976e3cc4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c71747c667c94062a03ec0f0468212e7ac222c57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c73e85bdaa195d9659ae9b08995a9fb716f9c92a"
     ], 
     "ci_platforms": [
@@ -70923,6 +79198,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c767f1416feb8d7a2899ab276a4846e10f59531c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c76a1cca503160ca659aad6f7a05ca8fe5db439e"
     ], 
     "ci_platforms": [
@@ -71033,6 +79330,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c8b448134c9d165968599402c9633719573afd8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c8b5d9fdb7ade3538abb794a3231d5777a1640a4"
     ], 
     "ci_platforms": [
@@ -71209,6 +79528,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c955c8f169185554e8e1d45ded89db29c3164917"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/c957b37c99c5bb22b2c1f6dd050c57e685505599"
     ], 
     "ci_platforms": [
@@ -71297,6 +79638,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/c9f81864507c264369dd22c72aeb16f1cb1742b0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ca086cf78308275212c52012f06edf3b4152204a"
     ], 
     "ci_platforms": [
@@ -71451,6 +79814,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cb4f23427bca81db8ccf5f03bdb0c60418a20a74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cb9a688f0dbc2015c77920f344e2d029c87384ff"
     ], 
     "ci_platforms": [
@@ -71671,6 +80056,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cce1a22e2c3532ddb85af19d2f17cc7a11ca1050"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cd0e7c4cd361b786b6f27c481ed601fd373cb221"
     ], 
     "ci_platforms": [
@@ -71693,6 +80100,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cd2b1fed5910041aca30e39210ee21d4ebb80469"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cd4272fec464c45438dce72eb9381971ed0207de"
     ], 
     "ci_platforms": [
@@ -71715,6 +80144,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cd4ccfa79f65f31716296e690f3a76007edde2e3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/cd4f2c59f0cf55d9a73fb0b96d701c784c446048"
     ], 
     "ci_platforms": [
@@ -71847,6 +80298,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ce4a157481d32f9c2ec106f257278d3159e6bd21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ce6a90cb7d395fea7aa54ee9f7061cc45f5494d7"
     ], 
     "ci_platforms": [
@@ -71935,6 +80408,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ceb98039ba87c5c326c904f275490b25c7d90f1c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/cee29e303670fdd259d375da8345d6e49ba971b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ceecce905981d8291a79fe32f89e8be688dfee7e"
     ], 
     "ci_platforms": [
@@ -72001,6 +80518,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5834320218423296"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0597bbdd657fa4ed14443994c9147a1a7bbc205f"
     ], 
     "ci_platforms": [
@@ -72177,6 +80738,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-177af631195e806f4056847cea4d09b5eb28cf8a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-17ad251e24eaa152ded652bfe04d656fdcad28c4"
     ], 
     "ci_platforms": [
@@ -72463,6 +81046,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-373224be81ff98db60e9f81536f16a9ef92792d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-404a40c85b887a53235484f4620da325872eca49"
     ], 
     "ci_platforms": [
@@ -72903,6 +81508,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-59b587d15c0bcdb985417cd7a133cecfcc232698"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-59e58120d4f37a833a79e68372c4eaf361a92240"
     ], 
     "ci_platforms": [
@@ -73013,6 +81640,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5d73de981fb75553a7b2606e111716ee9f2af844"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-5fc15c2ee9c70fd834588cbd256cfb52cdcbcb8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-603222da20c147a532188e80fc1a26e4e8bc4bee"
     ], 
     "ci_platforms": [
@@ -73035,6 +81706,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-60a3f7ed4abddaa6a7c837ace86d048fa15e288b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-6db86c556caf542fe8c3345ef396467b1d609d32"
     ], 
     "ci_platforms": [
@@ -73849,6 +82542,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b208a1eb5ef9f229f309492329323f485768fa74"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b39ce8e62e5c9e046d67e946436609e01f067a53"
     ], 
     "ci_platforms": [
@@ -73893,6 +82608,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-b5ae6881c767a7769bb957ac379f22aafe4ef05e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-ba2c1509ff87865d9e23c056b9c7fe2732825ef0"
     ], 
     "ci_platforms": [
@@ -74707,6 +83444,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d0a8deab4d26bc005d022184c311c1ce4d5327bb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d0d622fa3916e800e959a3fc2c90e213d518e5f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d0fcc9d6dc91ead9fd27f0c613ea031f21fb4de4"
     ], 
     "ci_platforms": [
@@ -74773,6 +83554,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d123c89b3cafd995bf401032699fc7dba60f8de4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d17e7451bcef39ce542d84f2539f9586ea35f21e"
     ], 
     "ci_platforms": [
@@ -74971,6 +83774,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d263d6004c2cc33cd9d157dd31ff604870c4d6fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d27e050b2758f6658d166b0d30e9db9595388ef9"
     ], 
     "ci_platforms": [
@@ -75037,6 +83862,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d29859445bfeff04ca22b20408f9aa0e2e161abc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d29cf6979d8d58b4cb779a629ebee62d7e42fc9b"
     ], 
     "ci_platforms": [
@@ -75081,6 +83928,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d2ba1c23045223aa6f4c107f91d57786befae604"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d2c828ee88b3e352fad3263f1e1ff901a41fc7a6"
     ], 
     "ci_platforms": [
@@ -75103,6 +83972,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d2e66d1fdf0110212c632268aec5b06130db3e21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d2f7c85e3c87ad5b71ad423aa4a9d97a8191d867"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d3089d3ef9be14080abc156e5f2128c3c1a2f23a"
     ], 
     "ci_platforms": [
@@ -75323,6 +84236,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d4bd740db31b0e9925ce331c9c7d2fae5c1d15f2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d4c3ed789ef8a888244504601964f0a0c994a66d"
     ], 
     "ci_platforms": [
@@ -75477,6 +84412,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d5dad7a599e22cff371d595a5014475301670892"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d63251b34cf38052b657d62e353aa42d905e52c4"
     ], 
     "ci_platforms": [
@@ -75609,6 +84566,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d6b689f1b878d6914ced5d24f21c599c203594d4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d6d7dc448cc24272ce216dbc7365ebe6e6b7b367"
     ], 
     "ci_platforms": [
@@ -75653,6 +84632,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/d716fb79cd7dd78d2ff66dc8a0e2acef9a93f98a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/d73ee327123be0e9bc72485b5517dd1bf691e249"
     ], 
     "ci_platforms": [
@@ -76027,6 +85028,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/da57f06258c4f0de07611263dfba8be669dd780c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/da97ec2d11daf27fe924513c463810c867b88983"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dab32e8bb17a9bd7b04b8b895b7b48c27d38ef51"
     ], 
     "ci_platforms": [
@@ -76115,6 +85160,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/daed40229642eab256927f3bfb0288e036eab89f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/db0dbec7a0811cac7b250cf9b248d47936edc0d0"
     ], 
     "ci_platforms": [
@@ -76137,6 +85204,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/db25df0fa146d02874114b8605000e0135ff12dd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/db7c4b56e701832634e61cc0b3ab5206fabf518d"
     ], 
     "ci_platforms": [
@@ -76225,6 +85314,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dcaa24f054af09a755c794ac4c3485ee682437a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dcb9a8007d2693d35911dfcde7ae960adbeb2601"
     ], 
     "ci_platforms": [
@@ -76247,6 +85358,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dcc039d81106cd60cd611ff540d4669ebd10fe68"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dcc8e14bbb75292968233ce89acd404303a53cc3"
     ], 
     "ci_platforms": [
@@ -76357,6 +85490,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dd229da166c3bec675e882d17092238cf7d245f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dd6d1ddb251fc3574733232c4a85dabdcf60d4c3"
     ], 
     "ci_platforms": [
@@ -76423,6 +85578,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/dda7f9e8860f0e132312f57e3640402f33df308a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ddc34d5e97ac12572e6c39a336d219d91fa992b1"
     ], 
     "ci_platforms": [
@@ -76445,6 +85622,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ddd34e967b1460902af2d01818605e208c5c7524"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/dddf3303e3e8e558ca6f147ec11d8195b6de30bb"
     ], 
     "ci_platforms": [
@@ -76533,6 +85732,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/de45c55043f63ec680e990b1edf1f0cc60ebbf4e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/de838de0352fc7ee32452bc83043cf587176e120"
     ], 
     "ci_platforms": [
@@ -76665,6 +85886,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/df29cf0d3cd5cfd27a98b506fffee64476398bba"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/df380dfd997318c00cfc75313e6a7ecb041d38af"
     ], 
     "ci_platforms": [
@@ -77083,6 +86326,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e13344aeec0694c50eed41ae1b78e6d2ac4a4c6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e13361499a2326ef8dbc3746ceb61c61b2e1ad57"
     ], 
     "ci_platforms": [
@@ -77479,6 +86744,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e37b4c7b64414d4705d934f8a723a50dcbf42571"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e3854bc2e1bc52f498780be3147d6f870e85d8af"
     ], 
     "ci_platforms": [
@@ -77611,6 +86898,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e4068f14a046ce3ee7f1920cbd210b6e876c07ec"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e4238ff612439be100fc2188bffa6aac1d7e5e5c"
     ], 
     "ci_platforms": [
@@ -77699,6 +87008,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e452ab01690d7e326f5ef52f4a312d066c087a24"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e45762f05b01eb2c781cc8cb15db74a31d97566b"
     ], 
     "ci_platforms": [
@@ -77809,6 +87140,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e52ac2e3cad2e544488a01822115cb37d10a76ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e53a201505fe8412278d7444b1a915b353bacb3e"
     ], 
     "ci_platforms": [
@@ -77941,6 +87294,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e609da99f76fa36e4b9060650cbc3597af458b01"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e62a93cf5ead5a0c5e4cd13bce4cfe83c54b1c5a"
     ], 
     "ci_platforms": [
@@ -78051,6 +87426,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e6b74f64e8bdfdf98177aee58b8729ff2aa7ffb2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e709e8861c09e29cdae73e337587a63fb0ccf76d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e72218971bac83f556e86b0a65ec303e2a05eac8"
     ], 
     "ci_platforms": [
@@ -78293,6 +87712,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e839090caa1b1bfa8898eea683f5d5c9f1ed6dd1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e8616e0840a6d4077b322fa2b1906d1fd4c406bd"
     ], 
     "ci_platforms": [
@@ -78447,6 +87888,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e97beccbdbb6e29eb476efec4ea2c96c310e6615"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e9932127668f9de0743fc639dca31acedbfc68fd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/e9ae17566804496b92d2ddcf99129436d771fb81"
     ], 
     "ci_platforms": [
@@ -78469,6 +87954,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/e9d470cdf421f6c6c9eefd7f84bd09df6a8994b2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ea2cf809383d8725bec1b44ab774f04b3e6d5ae5"
     ], 
     "ci_platforms": [
@@ -78623,6 +88130,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eacf4905e489566a3e5fcaaeac9fe91cbf916e06"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/eaddce3919388311104c50b9089461ff59c8ac14"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/eaf587f7f303dda3ccc5becc6e645af7a47b36bf"
     ], 
     "ci_platforms": [
@@ -78821,6 +88372,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ec55cbebe6db506acf7af9e5d26386630319623d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ec56dad56975e8279b2b229288dff3bb0ceaf661"
     ], 
     "ci_platforms": [
@@ -79019,6 +88592,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ed47f70f76dadbb6744ede3eb7016f585c9fe59a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ed7d0b055e59602ec752162db7afc2b36ac7800a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ed913deced10ab045fe04c783f6a0e2678f1929f"
     ], 
     "ci_platforms": [
@@ -79151,6 +88768,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/edecc59c5809796f266abd8df4d5ecf6aae304ca"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/edfcf299569efc4788937d2cd4ca0e625fb9e527"
     ], 
     "ci_platforms": [
@@ -79217,6 +88856,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ee42f876c500996016a9f4a989147e5c2b5019fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ee624b408f8a50c79cdaebf4fb4195e6162b70da"
     ], 
     "ci_platforms": [
@@ -79261,6 +88922,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ee90aa84710c6a218a84b49ca6bc5d0e7a324220"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/eeb310d91038cb02862e187e68c5d6578233485b"
     ], 
     "ci_platforms": [
@@ -79305,6 +88988,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ef20d859b09ca00a80782df7097881ec4299cd25"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/ef24beeeff80ec8ad728919794e9de4a06cf7daa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/ef264406b5a2263cd7a9145f7ca68ed8fd6c50ad"
     ], 
     "ci_platforms": [
@@ -79437,6 +89164,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/efa40f9e7f8a5ba4649dbad1a66ff9cc6bc699b8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/efa80ac7daa93de08fc91bdf2a912269a3f2396a"
     ], 
     "ci_platforms": [
@@ -79569,6 +89318,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f09c5cabe569b5c22a16d7d584074d54d9343edc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f0a7e39c194ee3f30312ae2f4827bdbd43416a42"
     ], 
     "ci_platforms": [
@@ -79789,6 +89560,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f1b2889ae7091d6a14332343fe7a2bffd81039a7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f1b592b7e1a5af83eea1bccc2d7bcca302173d57"
     ], 
     "ci_platforms": [
@@ -79943,6 +89736,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f2b838edb5715e9f0f73897ed74eddaede87a43a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f2bb9fb90c0fb7dfd765e1c528330881e721c7d8"
     ], 
     "ci_platforms": [
@@ -80119,6 +89934,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f3b3769d79f1d9586c575c27dff353f343ceacaf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f3c0468b37c09b998096d18cd13a522dec09888b"
     ], 
     "ci_platforms": [
@@ -80141,6 +89978,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f3cad6a2ea4ebfd40568d4992d68784e82de2b20"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f3fba021c9e4cdee8ea694017ae1e40f55fead5d"
     ], 
     "ci_platforms": [
@@ -80273,6 +90132,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f503f8d526eaec9bab6cae97d09207deefa85d8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f575224a90d142bcd971b4f1634f4dc4988f8b15"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f5867f7dbacd22878e2955f4be8fca147442aa9d"
     ], 
     "ci_platforms": [
@@ -80537,6 +90440,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f7623c34b3b5fb243fe589d881e4e8489f578f21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f788d2b893fe39fe24582acffa6a70f1ca4e3037"
     ], 
     "ci_platforms": [
@@ -80779,6 +90704,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f875ad5830cb0b5d387a267e0200eb3027d025d5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f8a02d7d9317428fd142c05f9428840d3d30aff4"
     ], 
     "ci_platforms": [
@@ -80801,6 +90748,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f9048c4c18e729b6f49e929876ec30866deb16a9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f912a072f4abf312ebbe7f1a2bf5ebd8c51e35e2"
     ], 
     "ci_platforms": [
@@ -80845,6 +90814,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/f92897ee60bd24634aa1582f162c1c8f4b249148"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/f9540ce65b08ec33d9157d03bf5231b767460d4a"
     ], 
     "ci_platforms": [
@@ -81153,6 +91144,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fb17c3fec47ab446ee737ab4c7fa8cb85688d5be"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fb263a744a6d40e183e84ec8a81ca13859c8b5ce"
     ], 
     "ci_platforms": [
@@ -81483,6 +91496,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fc824337cead8b9e5229119c85c284fdd8e2d391"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fc9879794ab7f7cdc4959c204788fce6146c0579"
     ], 
     "ci_platforms": [
@@ -81549,6 +91584,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fd05ad1a9d183c2a25d820aca9940caacbaa0660"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fd4d68895bc219f52d93f3f2f302ff138e8ffeda"
     ], 
     "ci_platforms": [
@@ -81571,6 +91628,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fd4f7d5d3d21c75ccb5cde9491bf952bae753390"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fd825fd14341b700853b72e4fea0899c2dfb441b"
     ], 
     "ci_platforms": [
@@ -81747,6 +91826,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/fe786c056e1e068e9cb9a94d7e10cee1593436bc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/fe7ac5c3403c7f1673ead3176af4efe7c60b2c02"
     ], 
     "ci_platforms": [
@@ -83485,6 +93586,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/175f16901997fdee41ac9ec88f7e018d46d774e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/17b1758fc7cd69a00d140f113b1ac894023ff20b"
     ], 
     "ci_platforms": [
@@ -84717,6 +94840,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/26f250ae38865f030176a8801ce992536351a326"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/2717067bbc0e9bfc1d90d15cddf6154800a25ec6"
     ], 
     "ci_platforms": [
@@ -85641,6 +95786,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3233f2ab3b6c9431289ef7dc4f40676d0128bcad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/330dd22142ff48078b189f4533ccc56878d88f92"
     ], 
     "ci_platforms": [
@@ -85817,6 +95984,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3656614c7b0dc11d4dd7e1826f77fa96a88c420f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/368c75135a7341a96627d0dcfc4b2081003d8979"
     ], 
     "ci_platforms": [
@@ -86213,6 +96402,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/3dec1981e8677ec6ad2517feba29869d53f8d884"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/3e8f531043a07df2280bca73fe4a7987d82ce67e"
     ], 
     "ci_platforms": [
@@ -87049,6 +97260,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/4bed84590a55b06d7eb30d8faa4b00a881ba9b2c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/4e05d6cf1c3f0c04f6ee92d09a53ee0fe35c085a"
     ], 
     "ci_platforms": [
@@ -87841,6 +98074,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/591d46b83d2e6babc0ce3c753c4606a10c46d7ce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/591ef436ef8cc982b48fd827a4555b57cd9780e5"
     ], 
     "ci_platforms": [
@@ -87973,6 +98228,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5a52d683c9342dd301b0e699db36175aad715e1d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/5a8cbd42a033b7899383d48c3929e517dafbb995"
     ], 
     "ci_platforms": [
@@ -87995,6 +98272,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/5b7ff7c113c2bcf125271d22c937f758a0cd2ee4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/5c14b48da74ab06b3cc20c4fe355e24f7dd7852a"
     ], 
     "ci_platforms": [
@@ -88281,6 +98580,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/616e55354ba3517ce6762d6cd56600f97915e646"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/622d46854c2d38b5fe632649d58a69b7da0803c0"
     ], 
     "ci_platforms": [
@@ -89491,6 +99812,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/7a9a12b15c798b88f1a599779f52d14edf9f4ef5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/7af3156d286a32a6a6fede46d93ec12ded1ac138"
     ], 
     "ci_platforms": [
@@ -90569,6 +100912,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8f05b8da748cc04e64b688c4b435fe64699bd481"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/8f980dd25f1c77e3536131c2c620aa32e8c13180"
     ], 
     "ci_platforms": [
@@ -90613,6 +100978,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/8fd758e2603f1e3772cfcd295ff0f951988d7648"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9018925b5e791ae4b3ae9c84b8a4d47d86671c2d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/90a9c3390752b94ca19a58cb2fe6267bc818f718"
     ], 
     "ci_platforms": [
@@ -91119,6 +101528,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/9912de197918ac0e305f0c0107f863823e8ae818"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/998a54dc94ab6e7d6a6066415fb0dd9b52356171"
     ], 
     "ci_platforms": [
@@ -92307,6 +102738,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ab90bebd4c017827a6d5de61511445df81169eb6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/abd52da5882855a63632a6917df3639538928cd3"
     ], 
     "ci_platforms": [
@@ -92681,6 +103134,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/b26a3a83d0b319ce13a9ae164e90fa6da1b05a57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/b283eb8884c98dd50523995ce221aa1ecb3ca182"
     ], 
     "ci_platforms": [
@@ -93055,6 +103530,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ba25be123c630bd3e4aeb9bda6304dd1a7e51365"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/ba3566735888b53712c6b2e6d52ff5f2197afd6a"
     ], 
     "ci_platforms": [
@@ -93627,6 +104124,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c77ee0b6cb21ab7b7cf222c7f6563b3b1b1b6eed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/c784ad2e205ba49b5bb1302746723dbc57320981"
     ], 
     "ci_platforms": [
@@ -93649,6 +104168,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/c7b17d6ae5f3b155532a5a9bf0239c098c35eec1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/c84da54dacf04445b50448a70fb0ecdd08e9234a"
     ], 
     "ci_platforms": [
@@ -93957,6 +104498,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/ccc36ee2c6a0daad65a4d929599fda5cd38b8fd1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/cceb4c620c02337138e489383db0d4f4e2c7a722"
     ], 
     "ci_platforms": [
@@ -94243,6 +104806,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-133500314833c9037b34a4c34ad779dd78a0fa8d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/crash-14ed70cd9ea7987cdd0c8f6e39398ee7c60ee2ff"
     ], 
     "ci_platforms": [
@@ -94749,6 +105334,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/d3141a71cdaa7a0915c8c55abf2c940b0fd00172"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/d3386702918881101368cdba2c4967e86ff3a7b9"
     ], 
     "ci_platforms": [
@@ -95629,6 +106236,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/de9b9a35e1e7040e842b597b8d2fe4cd602e67f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/df20bbbb854cb997a73285ef30d227aa12d90e4e"
     ], 
     "ci_platforms": [
@@ -96047,6 +106676,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e5319a8570a762bbdd67135b49579097324e369a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/e5a7c086208248a15ee6fa5195fc4ce22469de15"
     ], 
     "ci_platforms": [
@@ -96091,6 +106742,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/e5e276acd665ccb47f868fe3bc36e647bbb840bd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/e61f728210ce72ed8b2c066bd1b1ecf9e6824b77"
     ], 
     "ci_platforms": [
@@ -96949,6 +107622,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/client_fuzzer_corpus/f69aa5666fd60c1b6814198f12d049abb0e9f148"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "client_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/client_fuzzer_corpus/f6af3f46aacee395877d7f7909f8e412a6538efb"
     ], 
     "ci_platforms": [
@@ -97939,6 +108634,28 @@
   }, 
   {
     "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/051268ade45dbed0aab896d7d9f4d10ba89d3b09"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/transport/chttp2/hpack_parser_corpus/0696e7bf7837d98de01c915d3c9d80e5d21b30d2"
     ], 
     "ci_platforms": [
@@ -100029,6 +110746,28 @@
   }, 
   {
     "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/5278e3581c069624157fd9176eddf52c0e58df67"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/transport/chttp2/hpack_parser_corpus/52fe8f0e1fa270ea16f66c93f2ffab265ce059e8"
     ], 
     "ci_platforms": [
@@ -102933,6 +113672,28 @@
   }, 
   {
     "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/bc4263a92952d56168b354f723eaa43a33cd0b35"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/transport/chttp2/hpack_parser_corpus/bcaa71abf23b2e5130e0cc464755fe769bf4aaa7"
     ], 
     "ci_platforms": [
@@ -103637,6 +114398,28 @@
   }, 
   {
     "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/crash-5ac3e1ea7764cfb6383629574262f82dc7b3cada"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/transport/chttp2/hpack_parser_corpus/d000502f32ca5620d7745f39ff6be3b547e26a6d"
     ], 
     "ci_platforms": [
@@ -103813,6 +114596,28 @@
   }, 
   {
     "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/d6d8b478e6d13945f7a6f7d27f424ff57ca12f7f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/transport/chttp2/hpack_parser_corpus/d76d0c7f24ae3cc3f530d5306b8dcc15290c7ff2"
     ], 
     "ci_platforms": [
@@ -104275,6 +115080,28 @@
   }, 
   {
     "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/e67c79d0ed89ab2d5e8d81127df22876e636ac44"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/transport/chttp2/hpack_parser_corpus/e6fab7572fb2a1c6e107b6f83cffd103a233d021"
     ], 
     "ci_platforms": [
@@ -104781,6 +115608,28 @@
   }, 
   {
     "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/f4b48c4f3f310ed767755267210f212dd62bd715"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/transport/chttp2/hpack_parser_corpus/f4d6ff635ae4fda497221da4bfa3e593df59a44e"
     ], 
     "ci_platforms": [
@@ -104935,6 +115784,28 @@
   }, 
   {
     "args": [
+      "test/core/transport/chttp2/hpack_parser_corpus/fcc06696e641a7743bfd2f3b7ecd88e7b727e00a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "hpack_parser_fuzzer_test_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/transport/chttp2/hpack_parser_corpus/fd34ec90fe8f9218fd25c3eac151aec998cff6d8"
     ], 
     "ci_platforms": [
@@ -125109,6 +135980,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/084e9e02b8f2ed41ff9c22fef80e522e491227c5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/08c42ef29eff83052c5887855f2fa3e07ebe470c"
     ], 
     "ci_platforms": [
@@ -125263,6 +136156,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/0c129f78eacfb0d0d3c89dd4e578724096a3cea0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/0c413d2b361b2221585026d42f3046ff4135d2ff"
     ], 
     "ci_platforms": [
@@ -125483,6 +136398,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/129382aa11fa2922053fa47ba691dddb98901260"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/13501419f349b7855d2e94060bd08b28923d1f37"
     ], 
     "ci_platforms": [
@@ -125505,6 +136442,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/1353e447b7b10fb3eabb02863a1fc5bc9bb50460"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/1421a8e9f045ac65a0f6938fae93fece1060c41d"
     ], 
     "ci_platforms": [
@@ -127045,6 +138004,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/3b55d09b98e3982d6f80913a792463c3974766db"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/3ca5da2f.bin"
     ], 
     "ci_platforms": [
@@ -127375,6 +138356,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/416160124b3b64fc9355f24dd789b3d1fd097b8b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/418f392319c44d06a018ce4c62569d527829177a"
     ], 
     "ci_platforms": [
@@ -127639,6 +138642,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/47563391b73b6ef4bf987014c3e631fe2555a377"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/49cb33cbb60f041e8e99dd718993acd2c3354416"
     ], 
     "ci_platforms": [
@@ -128937,6 +139962,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6c0ec181e81b915071766762f5d78e9b1ccc9128"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/6c5bb78b51cf5006c92258292de19550985c00ba"
     ], 
     "ci_platforms": [
@@ -128959,6 +140006,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/6c66271b74a11f4e7065a6acbc86e4611e7e0dcc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/6db42d0c5471ac697d82e882c01867b73f71c71f"
     ], 
     "ci_platforms": [
@@ -129157,6 +140226,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/72db978194609ac138bca393650740a3eae8f448"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/7342b3febb07521e39abdf4ee976d16199d51239"
     ], 
     "ci_platforms": [
@@ -129355,6 +140446,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/7df75412d12894fc501bd2d8493fe9e5a753ad88"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/7f15bbce.bin"
     ], 
     "ci_platforms": [
@@ -130081,6 +141194,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/92f1df2266f34a097e96dd22188d8633832d37b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/93beeba2.bin"
     ], 
     "ci_platforms": [
@@ -130125,6 +141260,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/947f53c0978672e59be452395670fa949a33cb4f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/9540d3ad3fa75bfb95c0d57cefd737611c7069a5"
     ], 
     "ci_platforms": [
@@ -130543,6 +141700,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a40c3ba87b4206142b134f67485859b7c9b7c75c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/a5348197.bin"
     ], 
     "ci_platforms": [
@@ -130675,6 +141854,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/a8305e9bb4a544eaef27e8bd21b4faabf524a84e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/a8b4049240b53947a8bc76cadf8d4ff9a802c783"
     ], 
     "ci_platforms": [
@@ -130961,6 +142162,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/ac4e19c9fe290afc54bbb1e5f6cfe84a9c1f3c29"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/ad810f7f.bin"
     ], 
     "ci_platforms": [
@@ -130983,6 +142206,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/ae297426638eb5a0611324f403c3189515274f1b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/aedefcd9bd7fc10b7bf60372da54c43e953523bd"
     ], 
     "ci_platforms": [
@@ -131159,6 +142404,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/b74dcd9c2780f145e09a27d2e03119576889a301"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/b7ce4a4f6eea20c0b83d9f7fa8406a0730ee0040"
     ], 
     "ci_platforms": [
@@ -131555,6 +142822,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/c39c0192d0d4f2b24f05c25a9e669cc091bff9e9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/c43d97f2.bin"
     ], 
     "ci_platforms": [
@@ -132017,6 +143306,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-73923add5066617ae08f187b79d2639b4fd96138"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-7af5da2a8da23d197d9336e32da72c9ff64c15b3"
     ], 
     "ci_platforms": [
@@ -132061,6 +143372,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-901723090ff2042ecc5a008ccd7ae0845c1681cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-c1f66840627e3bfdedf2e4c225bc4de0c267ed37"
     ], 
     "ci_platforms": [
@@ -132237,6 +143570,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/d297b3f84e3dee9f74bf1162718aff66a11a7f5c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/d44d94764e1761cb7278ffe5cb17871abab7ed89"
     ], 
     "ci_platforms": [
@@ -132567,6 +143922,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/e021c5b9815f02ee9d1e5a003cbf3500e19db13c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/e0d9a9a7.bin"
     ], 
     "ci_platforms": [
@@ -133293,6 +144670,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fc162db40f87facb73cff20751e23af2e1f5296e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fcb1dea251d1ce74e30351f13a3f71e3debec3d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/fd14bea45ecaf13af0053900edb2f17b71a0bf09"
     ], 
     "ci_platforms": [
@@ -133469,6 +144890,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/fe740f8c4ffd07f79456c8cee24ef556ee348f55"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/ff227015.bin"
     ], 
     "ci_platforms": [
@@ -133557,6 +145000,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-03c6f209b2f144734c83d81ed452839d9e244fe9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-082763e16153cb6b8f3f5308cd060e822f475e5a"
     ], 
     "ci_platforms": [
@@ -133623,6 +145088,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-129ecb5e7b80616f36791e3580844e520f2ba7d3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-13501419f349b7855d2e94060bd08b28923d1f37"
     ], 
     "ci_platforms": [
@@ -133755,6 +145242,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-30408c9d13f29804168fc62a0818cc894c6375ae"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-33d8bf197de7131be78244e10fbb0da5055cf266"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-350b5da741597222c98fe86768432507850317f5"
     ], 
     "ci_platforms": [
@@ -133887,6 +145418,50 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-51cdbfa3e97a46ceefde405e6ab087a109c26907"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-523cb1bca5ad56690c618b4ceac7fceca1113b9d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-58f116dfba8d428a01ca596174fca63f4ac523f0"
     ], 
     "ci_platforms": [
@@ -134283,6 +145858,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-a877fe99fd0e92721d162bc252bf72a4f67ba1ea"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-aa23c18f6badd88a7bec65e8b04f7801ba624ec6"
     ], 
     "ci_platforms": [
@@ -134415,6 +146012,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bd9d24f5c7c915174b6ca9d1a3573e16e0edee12"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-bda43d420a3e5d5228a5f5130207a1f11fc1c81f"
     ], 
     "ci_platforms": [
@@ -134613,6 +146232,28 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f3c688876395bf7a529f29f7b91532726cf5cbce"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "server_fuzzer_one_entry", 
+    "platforms": [
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/server_fuzzer_corpus/slow-unit-f412afea6b01aa53da919a41a65ffbf9885f2d65"
     ], 
     "ci_platforms": [
diff --git a/tools/run_tests/helper_scripts/pre_build_cmake.bat b/tools/run_tests/helper_scripts/pre_build_cmake.bat
new file mode 100644
index 0000000..c937b9e
--- /dev/null
+++ b/tools/run_tests/helper_scripts/pre_build_cmake.bat
@@ -0,0 +1,48 @@
+@rem Copyright 2017, Google Inc.
+@rem All rights reserved.
+@rem
+@rem Redistribution and use in source and binary forms, with or without
+@rem modification, are permitted provided that the following conditions are
+@rem met:
+@rem
+@rem     * Redistributions of source code must retain the above copyright
+@rem notice, this list of conditions and the following disclaimer.
+@rem     * Redistributions in binary form must reproduce the above
+@rem copyright notice, this list of conditions and the following disclaimer
+@rem in the documentation and/or other materials provided with the
+@rem distribution.
+@rem     * Neither the name of Google Inc. nor the names of its
+@rem contributors may be used to endorse or promote products derived from
+@rem this software without specific prior written permission.
+@rem
+@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+setlocal
+
+cd /d %~dp0\..\..\..
+
+mkdir cmake
+cd cmake
+mkdir build
+cd build
+
+@rem TODO(jtattermusch): Stop hardcoding path to yasm once Jenkins workers can locate yasm correctly
+cmake -G "Visual Studio 14 2015" -DgRPC_BUILD_TESTS=ON -DCMAKE_ASM_NASM_COMPILER="C:/Program Files (x86)/yasm/yasm.exe" ../.. || goto :error
+
+endlocal
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b %errorlevel%
diff --git a/tools/run_tests/helper_scripts/pre_build_cmake.sh b/tools/run_tests/helper_scripts/pre_build_cmake.sh
new file mode 100755
index 0000000..49083f0e
--- /dev/null
+++ b/tools/run_tests/helper_scripts/pre_build_cmake.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+cd $(dirname $0)/../../..
+
+mkdir -p cmake/build
+cd cmake/build
+
+# MSBUILD_CONFIG's values are suitable for cmake as well
+cmake -DgRPC_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=${MSBUILD_CONFIG} ../..
diff --git a/tools/run_tests/helper_scripts/pre_build_csharp.bat b/tools/run_tests/helper_scripts/pre_build_csharp.bat
index 139955d..f37f63b 100644
--- a/tools/run_tests/helper_scripts/pre_build_csharp.bat
+++ b/tools/run_tests/helper_scripts/pre_build_csharp.bat
@@ -31,9 +31,21 @@
 
 setlocal
 
+set ARCHITECTURE=%1
+
 @rem enter repo root
 cd /d %~dp0\..\..\..
 
+mkdir cmake
+cd cmake
+mkdir build
+cd build
+mkdir %ARCHITECTURE%
+cd %ARCHITECTURE%
+@rem TODO(jtattermusch): Stop hardcoding path to yasm once Jenkins workers can locate yasm correctly
+cmake -G "Visual Studio 14 2015" -A %ARCHITECTURE% -DgRPC_BUILD_TESTS=OFF -DCMAKE_ASM_NASM_COMPILER="C:/Program Files (x86)/yasm/yasm.exe" ../../.. || goto :error
+cd ..\..\..
+
 @rem Location of nuget.exe
 set NUGET=C:\nuget\nuget.exe
 
@@ -42,7 +54,6 @@
   @rem Restore Grpc packages by packages since Nuget client 3.4.4 doesnt support restore
   @rem by solution
   @rem Moving into each directory to let the restores work based on per-project packages.config files
-  %NUGET% restore vsprojects/grpc_csharp_ext.sln || goto :error
 
   cd src/csharp
 
diff --git a/tools/run_tests/interop/interop_html_report.template b/tools/run_tests/interop/interop_html_report.template
index 46cce42..88ecd4e 100644
--- a/tools/run_tests/interop/interop_html_report.template
+++ b/tools/run_tests/interop/interop_html_report.template
@@ -106,6 +106,30 @@
   % endfor
 % endif
 
+% if http2_badserver_cases:
+  <h2>HTTP/2 Bad Server Tests</h2>
+  ## Each column header is the client language.
+  <table style="width:100%" border="1">
+  <tr bgcolor="#00BFFF">
+  <th>Client languages &#9658;<br/>Test Cases &#9660;</th>
+  % for client_lang in client_langs_http2_badserver_cases:
+    <th>${client_lang}</th>
+  % endfor
+  </tr>
+  % for test_case in http2_badserver_cases:
+    <tr><td><b>${test_case}</b></td>
+    % for client_lang in client_langs_http2_badserver_cases:
+      <% 
+        shortname = 'cloud_to_cloud:%s:http2_server:%s' % (client_lang, 
+                                                           test_case)
+      %>
+      ${fill_one_test_result(shortname, resultset)}
+    % endfor
+    </tr> 
+  % endfor
+  </table>
+% endif
+
 % if http2_interop:
   ## Each column header is the server language.
   <h2>HTTP/2 Interop</h2> 
diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py
index b20bb40..865125f 100644
--- a/tools/run_tests/performance/scenario_config.py
+++ b/tools/run_tests/performance/scenario_config.py
@@ -48,25 +48,6 @@
   'max_possible': 60e9,
 }
 
-EMPTY_GENERIC_PAYLOAD = {
-  'bytebuf_params': {
-    'req_size': 0,
-    'resp_size': 0,
-  }
-}
-EMPTY_PROTO_PAYLOAD = {
-  'simple_params': {
-    'req_size': 0,
-    'resp_size': 0,
-  }
-}
-BIG_GENERIC_PAYLOAD = {
-  'bytebuf_params': {
-    'req_size': 65536,
-    'resp_size': 65536,
-  }
-}
-
 # target number of RPCs outstanding on across all client channels in
 # non-ping-pong tests (since we can only specify per-channel numbers, the
 # actual target will be slightly higher)
@@ -92,6 +73,7 @@
   scenario.pop('CATEGORIES', None)
   scenario.pop('CLIENT_LANGUAGE', None)
   scenario.pop('SERVER_LANGUAGE', None)
+  scenario.pop('EXCLUDED_POLL_ENGINES', None)
   return scenario
 
 
@@ -102,10 +84,25 @@
     n *= step
 
 
+def _payload_type(use_generic_payload, req_size, resp_size):
+    r = {}
+    sizes = {
+      'req_size': req_size,
+      'resp_size': resp_size,
+    }
+    if use_generic_payload:
+        r['bytebuf_params'] = sizes
+    else:
+        r['simple_params'] = sizes
+    return r
+
+
 def _ping_pong_scenario(name, rpc_type,
                         client_type, server_type,
                         secure=True,
                         use_generic_payload=False,
+                        req_size=0,
+                        resp_size=0,
                         unconstrained_client=None,
                         client_language=None,
                         server_language=None,
@@ -114,7 +111,8 @@
                         categories=DEFAULT_CATEGORIES,
                         channels=None,
                         outstanding=None,
-                        resource_quota_size=None):
+                        resource_quota_size=None,
+                        excluded_poll_engines=[]):
   """Creates a basic ping pong scenario."""
   scenario = {
     'name': name,
@@ -145,14 +143,16 @@
   if use_generic_payload:
     if server_type != 'ASYNC_GENERIC_SERVER':
       raise Exception('Use ASYNC_GENERIC_SERVER for generic payload.')
-    scenario['client_config']['payload_config'] = EMPTY_GENERIC_PAYLOAD
-    scenario['server_config']['payload_config'] = EMPTY_GENERIC_PAYLOAD
-  else:
-    # For proto payload, only the client should get the config.
-    scenario['client_config']['payload_config'] = EMPTY_PROTO_PAYLOAD
+    scenario['server_config']['payload_config'] = _payload_type(use_generic_payload, req_size, resp_size)
+
+  scenario['client_config']['payload_config'] = _payload_type(use_generic_payload, req_size, resp_size)
 
   if unconstrained_client:
     outstanding_calls = outstanding if outstanding is not None else OUTSTANDING_REQUESTS[unconstrained_client]
+    # clamp buffer usage to something reasonable (16 gig for now)
+    MAX_MEMORY_USE = 16 * 1024 * 1024 * 1024
+    if outstanding_calls * max(req_size, resp_size) > MAX_MEMORY_USE:
+        outstanding_calls = max(1, MAX_MEMORY_USE / max(req_size, resp_size))
     wide = channels if channels is not None else WIDE
     deep = int(math.ceil(1.0 * outstanding_calls / wide))
 
@@ -173,6 +173,9 @@
     scenario['SERVER_LANGUAGE'] = server_language
   if categories:
     scenario['CATEGORIES'] = categories
+  if len(excluded_poll_engines):
+    # The polling engines for which this scenario is excluded
+    scenario['EXCLUDED_POLL_ENGINES'] = excluded_poll_engines
   return scenario
 
 
@@ -228,7 +231,8 @@
           server_type='SYNC_SERVER',
           unconstrained_client='async',
           secure=secure,
-          categories=smoketest_categories + [SCALABLE])
+          categories=smoketest_categories + [SCALABLE],
+          excluded_poll_engines = ['poll-cv'])
 
       yield _ping_pong_scenario(
           'cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_%s' % secstr,
@@ -237,7 +241,8 @@
           server_type='SYNC_SERVER',
           unconstrained_client='async',
           secure=secure,
-          categories=smoketest_categories+[SCALABLE])
+          categories=smoketest_categories+[SCALABLE],
+          excluded_poll_engines = ['poll-cv'])
 
       for rpc_type in ['unary', 'streaming']:
         for synchronicity in ['sync', 'async']:
@@ -249,6 +254,18 @@
               async_server_threads=1,
               secure=secure)
 
+          for size in geometric_progression(1, 1024*1024*1024+1, 8):
+              yield _ping_pong_scenario(
+                  'cpp_protobuf_%s_%s_qps_unconstrained_%s_%db' % (synchronicity, rpc_type, secstr, size),
+                  rpc_type=rpc_type.upper(),
+                  req_size=size,
+                  resp_size=size,
+                  client_type='%s_CLIENT' % synchronicity.upper(),
+                  server_type='%s_SERVER' % synchronicity.upper(),
+                  unconstrained_client=synchronicity,
+                  secure=secure,
+                  categories=[SWEEP])
+
           yield _ping_pong_scenario(
               'cpp_protobuf_%s_%s_qps_unconstrained_%s' % (synchronicity, rpc_type, secstr),
               rpc_type=rpc_type.upper(),
diff --git a/tools/run_tests/python_utils/filter_pull_request_tests.py b/tools/run_tests/python_utils/filter_pull_request_tests.py
index ca1d6d4..3734f02 100644
--- a/tools/run_tests/python_utils/filter_pull_request_tests.py
+++ b/tools/run_tests/python_utils/filter_pull_request_tests.py
@@ -98,6 +98,7 @@
   '^test/distrib/php/': [_PHP_TEST_SUITE],
   '^test/distrib/python/': [_PYTHON_TEST_SUITE],
   '^test/distrib/ruby/': [_RUBY_TEST_SUITE],
+  '^tools/internal_ci/': [],
   '^vsprojects/': [_WINDOWS_TEST_SUITE],
   'binding\.gyp$': [_NODE_TEST_SUITE],
   'composer\.json$': [_PHP_TEST_SUITE],
diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py
index 7b2c62d..f304743 100755
--- a/tools/run_tests/python_utils/jobset.py
+++ b/tools/run_tests/python_utils/jobset.py
@@ -31,6 +31,7 @@
 
 from __future__ import print_function
 
+import logging
 import multiprocessing
 import os
 import platform
@@ -128,6 +129,8 @@
     'SKIPPED': 'cyan'
     }
 
+_FORMAT = '%(asctime)-15s %(message)s'
+logging.basicConfig(level=logging.INFO, format=_FORMAT)
 
 def message(tag, msg, explanatory_text=None, do_newline=False):
   if message.old_tag == tag and message.old_msg == msg and not explanatory_text:
@@ -137,8 +140,8 @@
   try:
     if platform_string() == 'windows' or not sys.stdout.isatty():
       if explanatory_text:
-        print(explanatory_text)
-      print('%s: %s' % (tag, msg))
+        logging.info(explanatory_text)
+      logging.info('%s: %s', tag, msg)
     else:
       sys.stdout.write('%s%s%s\x1b[%d;%dm%s\x1b[0m: %s%s' % (
           _BEGINNING_OF_LINE,
diff --git a/tools/run_tests/python_utils/report_utils.py b/tools/run_tests/python_utils/report_utils.py
index 352cf7a..9dad604 100644
--- a/tools/run_tests/python_utils/report_utils.py
+++ b/tools/run_tests/python_utils/report_utils.py
@@ -82,7 +82,8 @@
 
 def render_interop_html_report(
   client_langs, server_langs, test_cases, auth_test_cases, http2_cases,
-  resultset, num_failures, cloud_to_prod, prod_servers, http2_interop):
+  http2_badserver_cases, client_langs_http2_badserver_cases, resultset, 
+  num_failures, cloud_to_prod, prod_servers, http2_interop):
   """Generate HTML report for interop tests."""
   template_file = 'tools/run_tests/interop/interop_html_report.template'
   try:
@@ -97,6 +98,9 @@
   sorted_test_cases = sorted(test_cases)
   sorted_auth_test_cases = sorted(auth_test_cases)
   sorted_http2_cases = sorted(http2_cases)
+  sorted_http2_badserver_cases = sorted(http2_badserver_cases)
+  sorted_client_langs_http2_badserver_cases = sorted(
+      client_langs_http2_badserver_cases)
   sorted_client_langs = sorted(client_langs)
   sorted_server_langs = sorted(server_langs)
   sorted_prod_servers = sorted(prod_servers)
@@ -106,6 +110,9 @@
           'test_cases': sorted_test_cases,
           'auth_test_cases': sorted_auth_test_cases,
           'http2_cases': sorted_http2_cases,
+          'http2_badserver_cases': sorted_http2_badserver_cases,
+          'client_langs_http2_badserver_cases': (
+              sorted_client_langs_http2_badserver_cases),
           'resultset': resultset,
           'num_failures': num_failures,
           'cloud_to_prod': cloud_to_prod,
diff --git a/tools/run_tests/python_utils/start_port_server.py b/tools/run_tests/python_utils/start_port_server.py
new file mode 100644
index 0000000..4c9f6aa
--- /dev/null
+++ b/tools/run_tests/python_utils/start_port_server.py
@@ -0,0 +1,138 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from __future__ import print_function
+
+from six.moves import urllib
+import jobset
+import logging
+import os
+import socket
+import subprocess
+import sys
+import tempfile
+import time
+
+
+def start_port_server(port_server_port):
+    # check if a compatible port server is running
+    # if incompatible (version mismatch) ==> start a new one
+    # if not running ==> start a new one
+    # otherwise, leave it up
+    try:
+        version = int(
+            urllib.request.urlopen(
+                'http://localhost:%d/version_number' % port_server_port,
+                timeout=10).read())
+        logging.info('detected port server running version %d', version)
+        running = True
+    except Exception as e:
+        logging.exception('failed to detect port server')
+        running = False
+    if running:
+        current_version = int(
+            subprocess.check_output([
+                sys.executable, os.path.abspath(
+                    'tools/run_tests/python_utils/port_server.py'),
+                'dump_version'
+            ]))
+        logging.info('my port server is version %d', current_version)
+        running = (version >= current_version)
+        if not running:
+            logging.info('port_server version mismatch: killing the old one')
+            urllib.request.urlopen('http://localhost:%d/quitquitquit' %
+                                   port_server_port).read()
+            time.sleep(1)
+    if not running:
+        fd, logfile = tempfile.mkstemp()
+        os.close(fd)
+        logging.info('starting port_server, with log file %s', logfile)
+        args = [
+            sys.executable,
+            os.path.abspath('tools/run_tests/python_utils/port_server.py'),
+            '-p', '%d' % port_server_port, '-l', logfile
+        ]
+        env = dict(os.environ)
+        env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
+        if jobset.platform_string() == 'windows':
+            # Working directory of port server needs to be outside of Jenkins
+            # workspace to prevent file lock issues.
+            tempdir = tempfile.mkdtemp()
+            port_server = subprocess.Popen(
+                args,
+                env=env,
+                cwd=tempdir,
+                creationflags=0x00000008,  # detached process
+                close_fds=True)
+        else:
+            port_server = subprocess.Popen(
+                args, env=env, preexec_fn=os.setsid, close_fds=True)
+        time.sleep(1)
+        # ensure port server is up
+        waits = 0
+        while True:
+            if waits > 10:
+                logging.warning(
+                    'killing port server due to excessive start up waits')
+                port_server.kill()
+            if port_server.poll() is not None:
+                logging.error('port_server failed to start')
+                # try one final time: maybe another build managed to start one
+                time.sleep(1)
+                try:
+                    urllib.request.urlopen(
+                        'http://localhost:%d/get' % port_server_port,
+                        timeout=1).read()
+                    logging.info(
+                        'last ditch attempt to contact port server succeeded')
+                    break
+                except:
+                    logging.exception(
+                        'final attempt to contact port server failed')
+                    port_log = open(logfile, 'r').read()
+                    print(port_log)
+                    sys.exit(1)
+            try:
+                port_server_url = 'http://localhost:%d/get' % port_server_port
+                urllib.request.urlopen(port_server_url, timeout=1).read()
+                logging.info('port server is up and ready')
+                break
+            except socket.timeout:
+                logging.exception('while waiting for port_server')
+                time.sleep(1)
+                waits += 1
+            except urllib.error.URLError:
+                logging.exception('while waiting for port_server')
+                time.sleep(1)
+                waits += 1
+            except:
+                logging.exception('error while contacting port server at "%s".'
+                                  'Will try killing it.', port_server_url)
+                port_server.kill()
+                raise
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 53df334..d29bfa9 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -164,6 +164,7 @@
   def __init__(self):
     self.client_cwd = '../grpc-java'
     self.server_cwd = '../grpc-java'
+    self.http2_cwd = '../grpc-java'
     self.safename = str(self)
 
   def client_cmd(self, args):
@@ -197,11 +198,15 @@
     # TODO: this relies on running inside docker
     self.client_cwd = '/go/src/google.golang.org/grpc/interop/client'
     self.server_cwd = '/go/src/google.golang.org/grpc/interop/server'
+    self.http2_cwd = '/go/src/google.golang.org/grpc/interop/http2'
     self.safename = str(self)
 
   def client_cmd(self, args):
     return ['go', 'run', 'client.go'] + args
 
+  def client_cmd_http2interop(self, args):
+    return ['go', 'run', 'negative_http2_client.go'] + args
+
   def cloud_to_prod_env(self):
     return {}
 
@@ -393,6 +398,7 @@
   def __init__(self):
     self.client_cwd = None
     self.server_cwd = None
+    self.http2_cwd = None
     self.safename = str(self)
 
   def client_cmd(self, args):
@@ -468,6 +474,8 @@
 _HTTP2_BADSERVER_TEST_CASES = ['rst_after_header', 'rst_after_data', 'rst_during_data',
                      'goaway', 'ping', 'max_streams']
 
+_LANGUAGES_FOR_HTTP2_BADSERVER_TESTS = ['java', 'go', 'python']
+
 DOCKER_WORKDIR_ROOT = '/var/local/git/grpc'
 
 def docker_run_cmdline(cmdline, image, docker_args=[], cwd=None, environ=None):
@@ -602,11 +610,12 @@
     client_options = common_options + ['--server_port=%s' %
                                        (int(server_port)+offset)]
     cmdline = bash_cmdline(language.client_cmd_http2interop(client_options))
+    cwd = language.http2_cwd
   else:
     client_options = interop_only_options + common_options + ['--server_port=%s' % server_port]
     cmdline = bash_cmdline(language.client_cmd(client_options))
+    cwd = language.client_cwd
 
-  cwd = language.client_cwd
   environ = language.global_env()
   if docker_image:
     container_name = dockerjob.random_name('interop_client_%s' % language.safename)
@@ -830,8 +839,13 @@
 
 languages = set(_LANGUAGES[l]
                 for l in itertools.chain.from_iterable(
-                      _LANGUAGES.iterkeys() if x == 'all' else [x]
-                      for x in args.language))
+                    _LANGUAGES.iterkeys() if x == 'all' else [x]
+                    for x in args.language))
+
+languages_http2_badserver_interop = set()
+if args.http2_badserver_interop:
+  languages_http2_badserver_interop = set(
+      _LANGUAGES[l] for l in _LANGUAGES_FOR_HTTP2_BADSERVER_TESTS)
 
 http2Interop = Http2Client() if args.http2_interop else None
 http2InteropServer = Http2Server() if args.http2_badserver_interop else None
@@ -839,8 +853,10 @@
 docker_images={}
 if args.use_docker:
   # languages for which to build docker images
-  languages_to_build = set(_LANGUAGES[k] for k in set([str(l) for l in languages] +
-                                                    [s for s in servers]))
+  languages_to_build = set(
+      _LANGUAGES[k] for k in set([str(l) for l in languages] + [s for s in servers]))
+  languages_to_build = languages_to_build | languages_http2_badserver_interop
+
   if args.http2_interop:
     languages_to_build.add(http2Interop)
 
@@ -885,7 +901,6 @@
     spec = server_jobspec(http2InteropServer, docker_images.get(lang))
     job = dockerjob.DockerJob(spec)
     server_jobs[lang] = job
-    server_addresses[lang] = ('localhost', _DEFAULT_SERVER_PORT)
 
   jobs = []
   if args.cloud_to_prod:
@@ -934,19 +949,18 @@
     skip_server = []  # test cases unimplemented by server
     if server_language:
       skip_server = server_language.unimplemented_test_cases_server()
-    if not args.http2_badserver_interop:
-      for language in languages:
-        for test_case in _TEST_CASES:
-          if not test_case in language.unimplemented_test_cases():
-            if not test_case in skip_server:
-              test_job = cloud_to_cloud_jobspec(language,
-                                                test_case,
-                                                server_name,
-                                                server_host,
-                                                server_port,
-                                                docker_image=docker_images.get(str(language)),
-                                                insecure=args.insecure)
-              jobs.append(test_job)
+    for language in languages:
+      for test_case in _TEST_CASES:
+        if not test_case in language.unimplemented_test_cases():
+          if not test_case in skip_server:
+            test_job = cloud_to_cloud_jobspec(language,
+                                              test_case,
+                                              server_name,
+                                              server_host,
+                                              server_port,
+                                              docker_image=docker_images.get(str(language)),
+                                              insecure=args.insecure)
+            jobs.append(test_job)
 
     if args.http2_interop:
       for test_case in _HTTP2_TEST_CASES:
@@ -962,16 +976,16 @@
                                           insecure=args.insecure)
         jobs.append(test_job)
 
-    if args.http2_badserver_interop:
-      for language in languages:
-        for test_case in _HTTP2_BADSERVER_TEST_CASES:
-          test_job = cloud_to_cloud_jobspec(language,
-                                            test_case,
-                                            server_name,
-                                            server_host,
-                                            server_port,
-                                            docker_image=docker_images.get(str(language)))
-          jobs.append(test_job)
+  if args.http2_badserver_interop:
+    for language in languages_http2_badserver_interop:
+      for test_case in _HTTP2_BADSERVER_TEST_CASES:
+        test_job = cloud_to_cloud_jobspec(language,
+                                          test_case,
+                                          str(http2InteropServer),
+                                          'localhost',
+                                          _DEFAULT_SERVER_PORT,
+                                          docker_image=docker_images.get(str(language)))
+        jobs.append(test_job)
 
   if not jobs:
     print('No jobs to run.')
@@ -992,9 +1006,13 @@
     if "http2" in name:
       job[0].http2results = aggregate_http2_results(job[0].message)
 
+  http2_badserver_test_cases = (
+      _HTTP2_BADSERVER_TEST_CASES if args.http2_badserver_interop else [])
+
   report_utils.render_interop_html_report(
       set([str(l) for l in languages]), servers, _TEST_CASES, _AUTH_TEST_CASES,
-      _HTTP2_TEST_CASES, resultset, num_failures,
+      _HTTP2_TEST_CASES, http2_badserver_test_cases,
+      _LANGUAGES_FOR_HTTP2_BADSERVER_TESTS, resultset, num_failures,
       args.cloud_to_prod_auth or args.cloud_to_prod, args.prod_servers,
       args.http2_interop)
 
diff --git a/tools/run_tests/run_microbenchmark.py b/tools/run_tests/run_microbenchmark.py
new file mode 100755
index 0000000..4307906
--- /dev/null
+++ b/tools/run_tests/run_microbenchmark.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python2.7
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import cgi
+import multiprocessing
+import os
+import subprocess
+import sys
+import argparse
+
+import python_utils.jobset as jobset
+import python_utils.start_port_server as start_port_server
+
+flamegraph_dir = os.path.join(os.path.expanduser('~'), 'FlameGraph')
+
+os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
+if not os.path.exists('reports'):
+  os.makedirs('reports')
+
+port_server_port = 32766
+start_port_server.start_port_server(port_server_port)
+
+def fnize(s):
+  out = ''
+  for c in s:
+    if c in '<>, /':
+      if len(out) and out[-1] == '_': continue
+      out += '_'
+    else:
+      out += c
+  return out
+
+# index html
+index_html = """
+<html>
+<head>
+<title>Microbenchmark Results</title>
+</head>
+<body>
+"""
+
+def heading(name):
+  global index_html
+  index_html += "<h1>%s</h1>\n" % name
+
+def link(txt, tgt):
+  global index_html
+  index_html += "<p><a href=\"%s\">%s</a></p>\n" % (
+      cgi.escape(tgt, quote=True), cgi.escape(txt))
+
+def text(txt):
+  global index_html
+  index_html += "<p><pre>%s</pre></p>\n" % cgi.escape(txt)
+
+def collect_latency(bm_name, args):
+  """generate latency profiles"""
+  benchmarks = []
+  profile_analysis = []
+  cleanup = []
+
+  heading('Latency Profiles: %s' % bm_name)
+  subprocess.check_call(
+      ['make', bm_name,
+       'CONFIG=basicprof', '-j', '%d' % multiprocessing.cpu_count()])
+  for line in subprocess.check_output(['bins/basicprof/%s' % bm_name,
+                                       '--benchmark_list_tests']).splitlines():
+    link(line, '%s.txt' % fnize(line))
+    benchmarks.append(
+        jobset.JobSpec(['bins/basicprof/%s' % bm_name,
+                        '--benchmark_filter=^%s$' % line,
+                        '--benchmark_min_time=0.05'],
+                       environ={'LATENCY_TRACE': '%s.trace' % fnize(line)}))
+    profile_analysis.append(
+        jobset.JobSpec([sys.executable,
+                        'tools/profiling/latency_profile/profile_analyzer.py',
+                        '--source', '%s.trace' % fnize(line), '--fmt', 'simple',
+                        '--out', 'reports/%s.txt' % fnize(line)], timeout_seconds=None))
+    cleanup.append(jobset.JobSpec(['rm', '%s.trace' % fnize(line)]))
+    # periodically flush out the list of jobs: profile_analysis jobs at least
+    # consume upwards of five gigabytes of ram in some cases, and so analysing
+    # hundreds of them at once is impractical -- but we want at least some
+    # concurrency or the work takes too long
+    if len(benchmarks) >= min(16, multiprocessing.cpu_count()):
+      # run up to half the cpu count: each benchmark can use up to two cores
+      # (one for the microbenchmark, one for the data flush)
+      jobset.run(benchmarks, maxjobs=max(1, multiprocessing.cpu_count()/2),
+                 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
+      jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count())
+      jobset.run(cleanup, maxjobs=multiprocessing.cpu_count())
+      benchmarks = []
+      profile_analysis = []
+      cleanup = []
+  # run the remaining benchmarks that weren't flushed
+  if len(benchmarks):
+    jobset.run(benchmarks, maxjobs=max(1, multiprocessing.cpu_count()/2),
+               add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
+    jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count())
+    jobset.run(cleanup, maxjobs=multiprocessing.cpu_count())
+
+def collect_perf(bm_name, args):
+  """generate flamegraphs"""
+  heading('Flamegraphs: %s' % bm_name)
+  subprocess.check_call(
+      ['make', bm_name,
+       'CONFIG=mutrace', '-j', '%d' % multiprocessing.cpu_count()])
+  benchmarks = []
+  profile_analysis = []
+  cleanup = []
+  for line in subprocess.check_output(['bins/mutrace/%s' % bm_name,
+                                       '--benchmark_list_tests']).splitlines():
+    link(line, '%s.svg' % fnize(line))
+    benchmarks.append(
+        jobset.JobSpec(['perf', 'record', '-o', '%s-perf.data' % fnize(line),
+                        '-g', '-F', '997',
+                        'bins/mutrace/%s' % bm_name,
+                        '--benchmark_filter=^%s$' % line,
+                        '--benchmark_min_time=10']))
+    profile_analysis.append(
+        jobset.JobSpec(['tools/run_tests/performance/process_local_perf_flamegraphs.sh'],
+                       environ = {
+                           'PERF_BASE_NAME': fnize(line),
+                           'OUTPUT_DIR': 'reports',
+                           'OUTPUT_FILENAME': fnize(line),
+                       }))
+    cleanup.append(jobset.JobSpec(['rm', '%s-perf.data' % fnize(line)]))
+    cleanup.append(jobset.JobSpec(['rm', '%s-out.perf' % fnize(line)]))
+    # periodically flush out the list of jobs: temporary space required for this
+    # processing is large
+    if len(benchmarks) >= 20:
+      # run up to half the cpu count: each benchmark can use up to two cores
+      # (one for the microbenchmark, one for the data flush)
+      jobset.run(benchmarks, maxjobs=1,
+                 add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
+      jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count())
+      jobset.run(cleanup, maxjobs=multiprocessing.cpu_count())
+      benchmarks = []
+      profile_analysis = []
+      cleanup = []
+  # run the remaining benchmarks that weren't flushed
+  if len(benchmarks):
+    jobset.run(benchmarks, maxjobs=1,
+               add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
+    jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count())
+    jobset.run(cleanup, maxjobs=multiprocessing.cpu_count())
+
+def collect_summary(bm_name, args):
+  heading('Summary: %s' % bm_name)
+  subprocess.check_call(
+      ['make', bm_name,
+       'CONFIG=counters', '-j', '%d' % multiprocessing.cpu_count()])
+  cmd = ['bins/counters/%s' % bm_name,
+         '--benchmark_out=out.json',
+         '--benchmark_out_format=json']
+  if args.summary_time is not None:
+    cmd += ['--benchmark_min_time=%d' % args.summary_time]
+  text(subprocess.check_output(cmd))
+  if args.bigquery_upload:
+    with open('out.csv', 'w') as f:
+      f.write(subprocess.check_output(['tools/profiling/microbenchmarks/bm2bq.py', 'out.json']))
+    subprocess.check_call(['bq', 'load', 'microbenchmarks.microbenchmarks', 'out.csv'])
+
+collectors = {
+  'latency': collect_latency,
+  'perf': collect_perf,
+  'summary': collect_summary,
+}
+
+argp = argparse.ArgumentParser(description='Collect data from microbenchmarks')
+argp.add_argument('-c', '--collect',
+                  choices=sorted(collectors.keys()),
+                  nargs='+',
+                  default=sorted(collectors.keys()),
+                  help='Which collectors should be run against each benchmark')
+argp.add_argument('-b', '--benchmarks',
+                  default=['bm_fullstack',
+                           'bm_closure',
+                           'bm_cq',
+                           'bm_call_create',
+                           'bm_error',
+                           'bm_chttp2_hpack',
+                           'bm_metadata'],
+                  nargs='+',
+                  type=str,
+                  help='Which microbenchmarks should be run')
+argp.add_argument('--bigquery_upload',
+                  default=False,
+                  action='store_const',
+                  const=True,
+                  help='Upload results from summary collection to bigquery')
+argp.add_argument('--summary_time',
+                  default=None,
+                  type=int,
+                  help='Minimum time to run benchmarks for the summary collection')
+args = argp.parse_args()
+
+for bm_name in args.benchmarks:
+  for collect in args.collect:
+    collectors[collect](bm_name, args)
+
+index_html += "</body>\n</html>\n"
+with open('reports/index.html', 'w') as f:
+  f.write(index_html)
diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py
index 12b5e01..7c04d22 100755
--- a/tools/run_tests/run_performance_tests.py
+++ b/tools/run_tests/run_performance_tests.py
@@ -96,16 +96,18 @@
     # specify -o output file so perf.data gets collected when worker stopped
     cmdline = perf_cmd + ['-o', '%s-perf.data' % perf_file_base_name] + cmdline
 
+  worker_timeout = 3 * 60
   if remote_host:
     user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host)
     ssh_cmd = ['ssh']
+    cmdline = ['timeout', '%s' % (worker_timeout + 30)] + cmdline
     ssh_cmd.extend([str(user_at_host), 'cd ~/performance_workspace/grpc/ && %s' % ' '.join(cmdline)])
     cmdline = ssh_cmd
 
   jobspec = jobset.JobSpec(
       cmdline=cmdline,
       shortname=shortname,
-      timeout_seconds=5*60,  # workers get restarted after each scenario
+      timeout_seconds=worker_timeout,  # workers get restarted after each scenario
       verbose_success=True)
   return QpsWorkerJob(jobspec, language, host_and_port, perf_file_base_name)
 
@@ -591,12 +593,13 @@
   # write the index fil to the output dir, with all profiles from all scenarios/workers
   report_utils.render_perf_profiling_results('%s/index.html' % args.flame_graph_reports, profile_output_files)
 
+report_utils.render_junit_xml_report(merged_resultset, args.xml_report,
+                                     suite_name='benchmarks')
+
 if total_scenario_failures > 0 or qps_workers_killed > 0:
   print('%s scenarios failed and %s qps worker jobs killed' % (total_scenario_failures, qps_workers_killed))
   sys.exit(1)
 
-report_utils.render_junit_xml_report(merged_resultset, args.xml_report,
-                                     suite_name='benchmarks')
 if perf_report_failures > 0:
   print('%s perf profile collection jobs failed' % perf_report_failures)
   sys.exit(1)
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 0558360..9741624 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python
 # Copyright 2015, Google Inc.
 # All rights reserved.
 #
@@ -38,6 +38,7 @@
 import glob
 import itertools
 import json
+import logging
 import multiprocessing
 import os
 import os.path
@@ -57,6 +58,7 @@
 import python_utils.jobset as jobset
 import python_utils.report_utils as report_utils
 import python_utils.watch_dirs as watch_dirs
+import python_utils.start_port_server as start_port_server
 
 
 _ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
@@ -79,6 +81,13 @@
 
 _DEFAULT_TIMEOUT_SECONDS = 5 * 60
 
+def run_shell_command(cmd, env=None, cwd=None):
+  try:
+    subprocess.check_output(cmd, shell=True, env=env, cwd=cwd)
+  except subprocess.CalledProcessError as e:
+    logging.exception("Error while running command '%s'. Exit status %d. Output:\n%s",
+                       e.cmd, e.returncode, e.output)
+    raise
 
 # SimpleConfig: just compile with CONFIG=config, and run the binary to test
 class Config(object):
@@ -197,10 +206,17 @@
   def configure(self, config, args):
     self.config = config
     self.args = args
-    if self.platform == 'windows':
+    if self.args.compiler == 'cmake':
+      _check_arch(self.args.arch, ['default'])
+      self._use_cmake = True
+      self._docker_distro = 'jessie'
+      self._make_options = []
+    elif self.platform == 'windows':
+      self._use_cmake = False
       self._make_options = [_windows_toolset_option(self.args.compiler),
                             _windows_arch_option(self.args.arch)]
     else:
+      self._use_cmake = False
       self._docker_distro, self._make_options = self._compiler_options(self.args.use_docker,
                                                                        self.args.compiler)
     if args.iomgr_platform == "uv":
@@ -220,6 +236,9 @@
     out = []
     binaries = get_c_tests(self.args.travis, self.test_lang)
     for target in binaries:
+      if self._use_cmake and target.get('boringssl', False):
+        # cmake doesn't build boringssl tests
+        continue
       polling_strategies = (_POLLING_STRATEGIES.get(self.platform, ['all'])
                             if target.get('uses_polling', True)
                             else ['all'])
@@ -234,17 +253,37 @@
         timeout_scaling = 1
         if polling_strategy == 'poll-cv':
           timeout_scaling *= 5
+
+        if polling_strategy in target.get('excluded_poll_engines', []):
+          continue
+
+        # Scale overall test timeout if running under various sanitizers.
+        config = self.args.config
+        if ('asan' in config
+            or config == 'msan'
+            or config == 'tsan'
+            or config == 'ubsan'
+            or config == 'helgrind'
+            or config == 'memcheck'):
+          timeout_scaling *= 20
+
         if self.config.build_config in target['exclude_configs']:
           continue
         if self.args.iomgr_platform in target.get('exclude_iomgrs', []):
           continue
         if self.platform == 'windows':
-          binary = 'vsprojects/%s%s/%s.exe' % (
-              'x64/' if self.args.arch == 'x64' else '',
-              _MSBUILD_CONFIG[self.config.build_config],
-              target['name'])
+          if self._use_cmake:
+            binary = 'cmake/build/%s/%s.exe' % (_MSBUILD_CONFIG[self.config.build_config], target['name'])
+          else:
+            binary = 'vsprojects/%s%s/%s.exe' % (
+                'x64/' if self.args.arch == 'x64' else '',
+                _MSBUILD_CONFIG[self.config.build_config],
+                target['name'])
         else:
-          binary = 'bins/%s/%s' % (self.config.build_config, target['name'])
+          if self._use_cmake:
+            binary = 'cmake/build/%s' % target['name']
+          else:
+            binary = 'bins/%s/%s' % (self.config.build_config, target['name'])
         cpu_cost = target['cpu_cost']
         if cpu_cost == 'capacity':
           cpu_cost = multiprocessing.cpu_count()
@@ -268,9 +307,9 @@
                 assert base is not None
                 assert line[1] == ' '
                 test = base + line.strip()
-                cmdline = [binary] + ['--gtest_filter=%s' % test]
+                cmdline = [binary, '--gtest_filter=%s' % test] + target['args']
                 out.append(self.config.job_spec(cmdline,
-                                                shortname='%s --gtest_filter=%s %s' % (binary, test, shortname_ext),
+                                                shortname='%s %s' % (' '.join(cmdline), shortname_ext),
                                                 cpu_cost=cpu_cost,
                                                 timeout_seconds=_DEFAULT_TIMEOUT_SECONDS * timeout_scaling,
                                                 environ=env))
@@ -299,10 +338,16 @@
     return self._make_options;
 
   def pre_build_steps(self):
-    if self.platform == 'windows':
-      return [['tools\\run_tests\\helper_scripts\\pre_build_c.bat']]
+    if self._use_cmake:
+      if self.platform == 'windows':
+        return [['tools\\run_tests\\helper_scripts\\pre_build_cmake.bat']]
+      else:
+        return [['tools/run_tests/helper_scripts/pre_build_cmake.sh']]
     else:
-      return []
+      if self.platform == 'windows':
+        return [['tools\\run_tests\\helper_scripts\\pre_build_c.bat']]
+      else:
+        return []
 
   def build_steps(self):
     return []
@@ -314,7 +359,10 @@
       return [['tools/run_tests/helper_scripts/post_tests_c.sh']]
 
   def makefile_name(self):
-    return 'Makefile'
+    if self._use_cmake:
+      return 'cmake/build/Makefile'
+    else:
+      return 'Makefile'
 
   def _clang_make_options(self, version_suffix=''):
     return ['CC=clang%s' % version_suffix,
@@ -644,11 +692,18 @@
     _check_compiler(self.args.compiler, ['default'])
 
   def test_specs(self):
+    #TODO(apolcyn) turn mac ruby tests back on once ruby 2.4 issues done
+    if platform_string() == 'mac':
+      print('skipping ruby test_specs on mac until running on 2.4')
+      return []
     return [self.config.job_spec(['tools/run_tests/helper_scripts/run_ruby.sh'],
                                  timeout_seconds=10*60,
                                  environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
 
   def pre_build_steps(self):
+    if platform_string() == 'mac':
+      print('skipping ruby pre_build_steps on mac until running on 2.4')
+      return []
     return [['tools/run_tests/helper_scripts/pre_build_ruby.sh']]
 
   def make_targets(self):
@@ -658,9 +713,15 @@
     return []
 
   def build_steps(self):
+    if platform_string() == 'mac':
+      print('skipping ruby build_steps on mac until running on 2.4')
+      return []
     return [['tools/run_tests/helper_scripts/build_ruby.sh']]
 
   def post_tests_steps(self):
+    if platform_string() == 'mac':
+      print('skipping ruby post_test_steps on mac until running on 2.4')
+      return []
     return [['tools/run_tests/helper_scripts/post_tests_ruby.sh']]
 
   def makefile_name(self):
@@ -682,12 +743,10 @@
     self.config = config
     self.args = args
     if self.platform == 'windows':
-      # Explicitly choosing between x86 and x64 arch doesn't work yet
+      _check_compiler(self.args.compiler, ['coreclr', 'default'])
       _check_arch(self.args.arch, ['default'])
-      # CoreCLR use 64bit runtime by default.
-      arch_option = 'x64' if self.args.compiler == 'coreclr' else self.args.arch
-      self._make_options = [_windows_toolset_option(self.args.compiler),
-                            _windows_arch_option(arch_option)]
+      self._cmake_arch_option = 'x64' if self.args.compiler == 'coreclr' else 'Win32'
+      self._make_options = []
     else:
       _check_compiler(self.args.compiler, ['default', 'coreclr'])
       if self.platform == 'linux' and self.args.compiler == 'coreclr':
@@ -759,7 +818,7 @@
 
   def pre_build_steps(self):
     if self.platform == 'windows':
-      return [['tools\\run_tests\\helper_scripts\\pre_build_csharp.bat']]
+      return [['tools\\run_tests\\helper_scripts\\pre_build_csharp.bat', self._cmake_arch_option]]
     else:
       return [['tools/run_tests/helper_scripts/pre_build_csharp.sh']]
 
@@ -777,7 +836,7 @@
         return [['tools/run_tests/helper_scripts/build_csharp_coreclr.sh']]
     else:
       if self.platform == 'windows':
-        return [[_windows_build_bat(self.args.compiler),
+        return [['vsprojects\\build_vs2015.bat',
                  'src/csharp/Grpc.sln',
                  '/p:Configuration=%s' % _MSBUILD_CONFIG[self.config.build_config]]]
       else:
@@ -790,7 +849,10 @@
       return [['tools/run_tests/helper_scripts/post_tests_csharp.sh']]
 
   def makefile_name(self):
-    return 'Makefile'
+    if self.platform == 'windows':
+      return 'cmake/build/%s/Makefile' % self._cmake_arch_option
+    else:
+      return 'Makefile'
 
   def dockerfile_dir(self):
     return 'tools/dockerfile/test/csharp_%s_%s' % (self._docker_distro,
@@ -998,12 +1060,10 @@
 def _windows_build_bat(compiler):
   """Returns name of build.bat for selected compiler."""
   # For CoreCLR, fall back to the default compiler for C core
-  if compiler == 'default' or compiler == 'vs2013' or compiler == 'coreclr':
+  if compiler == 'default' or compiler == 'vs2013':
     return 'vsprojects\\build_vs2013.bat'
   elif compiler == 'vs2015':
     return 'vsprojects\\build_vs2015.bat'
-  elif compiler == 'vs2010':
-    return 'vsprojects\\build_vs2010.bat'
   else:
     print('Compiler %s not supported.' % compiler)
     sys.exit(1)
@@ -1016,8 +1076,6 @@
     return '/p:PlatformToolset=v120'
   elif compiler == 'vs2015':
     return '/p:PlatformToolset=v140'
-  elif compiler == 'vs2010':
-    return '/p:PlatformToolset=v100'
   else:
     print('Compiler %s not supported.' % compiler)
     sys.exit(1)
@@ -1055,6 +1113,18 @@
         raise argparse.ArgumentTypeError(msg)
 
 
+def percent_type(arg_str):
+  pct = float(arg_str)
+  if pct > 100 or pct < 0:
+    raise argparse.ArgumentTypeError(
+        "'%f' is not a valid percentage in the [0, 100] range" % pct)
+  return pct
+
+# This is math.isclose in python >= 3.5
+def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
+      return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
+
+
 # parse command line
 argp = argparse.ArgumentParser(description='Run grpc tests.')
 argp.add_argument('-c', '--config',
@@ -1067,6 +1137,8 @@
 argp.add_argument('--regex_exclude', default='', type=str)
 argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int)
 argp.add_argument('-s', '--slowdown', default=1.0, type=float)
+argp.add_argument('-p', '--sample_percent', default=100.0, type=percent_type,
+                  help='Run a random sample with that percentage of tests')
 argp.add_argument('-f', '--forever',
                   default=False,
                   action='store_const',
@@ -1107,11 +1179,12 @@
                   choices=['default',
                            'gcc4.4', 'gcc4.6', 'gcc4.8', 'gcc4.9', 'gcc5.3',
                            'clang3.4', 'clang3.5', 'clang3.6', 'clang3.7',
-                           'vs2010', 'vs2013', 'vs2015',
+                           'vs2013', 'vs2015',
                            'python2.7', 'python3.4', 'python3.5', 'python3.6', 'pypy', 'pypy3',
                            'node0.12', 'node4', 'node5', 'node6', 'node7',
                            'electron1.3',
-                           'coreclr'],
+                           'coreclr',
+                           'cmake'],
                   default='default',
                   help='Selects compiler to use. Allowed values depend on the platform and language.')
 argp.add_argument('--iomgr_platform',
@@ -1161,7 +1234,7 @@
   cwd = 'third_party/%s' % submodule
   def git(cmd, cwd=cwd):
     print('in %s: git %s' % (cwd, cmd))
-    subprocess.check_call('git %s' % cmd, cwd=cwd, shell=True)
+    run_shell_command('git %s' % cmd, cwd=cwd)
   git('fetch')
   git('checkout %s' % branch)
   git('pull origin %s' % branch)
@@ -1169,7 +1242,7 @@
     need_to_regenerate_projects = True
 if need_to_regenerate_projects:
   if jobset.platform_string() == 'linux':
-    subprocess.check_call('tools/buildgen/generate_projects.sh', shell=True)
+    run_shell_command('tools/buildgen/generate_projects.sh')
   else:
     print('WARNING: may need to regenerate projects, but since we are not on')
     print('         Linux this step is being skipped. Compilation MAY fail.')
@@ -1238,15 +1311,19 @@
   if not args.travis:
     env['TTY_FLAG'] = '-t'  # enables Ctrl-C when not on Jenkins.
 
-  subprocess.check_call(['tools/run_tests/dockerize/build_docker_and_run_tests.sh'],
-                        shell=True,
-                        env=env)
+  run_shell_command('tools/run_tests/dockerize/build_docker_and_run_tests.sh', env=env)
   sys.exit(0)
 
 _check_arch_option(args.arch)
 
 def make_jobspec(cfg, targets, makefile='Makefile'):
   if platform_string() == 'windows':
+    if makefile.startswith('cmake/build/'):
+      return [jobset.JobSpec(['cmake', '--build', '.',
+                              '--target', '%s' % target,
+                              '--config', _MSBUILD_CONFIG[cfg]],
+                             cwd=os.path.dirname(makefile),
+                             timeout_seconds=None) for target in targets]
     extra_args = []
     # better do parallel compilation
     # empirically /m:2 gives the best performance/price and should prevent
@@ -1263,6 +1340,13 @@
                       shell=True, timeout_seconds=None)
       for target in targets]
   else:
+    if targets and makefile.startswith('cmake/build/'):
+      # With cmake, we've passed all the build configuration in the pre-build step already
+      return [jobset.JobSpec([os.getenv('MAKE', 'make'),
+                              '-j', '%d' % args.jobs] +
+                             targets,
+                             cwd='cmake/build',
+                             timeout_seconds=None)]
     if targets:
       return [jobset.JobSpec([os.getenv('MAKE', 'make'),
                               '-f', makefile,
@@ -1321,97 +1405,6 @@
         'http://localhost:%d/quitquitquit' % legacy_server_port).read()
 
 
-def _start_port_server(port_server_port):
-  # check if a compatible port server is running
-  # if incompatible (version mismatch) ==> start a new one
-  # if not running ==> start a new one
-  # otherwise, leave it up
-  try:
-    version = int(urllib.request.urlopen(
-        'http://localhost:%d/version_number' % port_server_port,
-        timeout=10).read())
-    print('detected port server running version %d' % version)
-    running = True
-  except Exception as e:
-    print('failed to detect port server: %s' % sys.exc_info()[0])
-    print(e.strerror)
-    running = False
-  if running:
-    current_version = int(subprocess.check_output(
-        [sys.executable, os.path.abspath('tools/run_tests/python_utils/port_server.py'),
-         'dump_version']))
-    print('my port server is version %d' % current_version)
-    running = (version >= current_version)
-    if not running:
-      print('port_server version mismatch: killing the old one')
-      urllib.request.urlopen('http://localhost:%d/quitquitquit' % port_server_port).read()
-      time.sleep(1)
-  if not running:
-    fd, logfile = tempfile.mkstemp()
-    os.close(fd)
-    print('starting port_server, with log file %s' % logfile)
-    args = [sys.executable, os.path.abspath('tools/run_tests/python_utils/port_server.py'),
-            '-p', '%d' % port_server_port, '-l', logfile]
-    env = dict(os.environ)
-    env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
-    if platform_string() == 'windows':
-      # Working directory of port server needs to be outside of Jenkins
-      # workspace to prevent file lock issues.
-      tempdir = tempfile.mkdtemp()
-      port_server = subprocess.Popen(
-          args,
-          env=env,
-          cwd=tempdir,
-          creationflags = 0x00000008, # detached process
-          close_fds=True)
-    else:
-      port_server = subprocess.Popen(
-          args,
-          env=env,
-          preexec_fn=os.setsid,
-          close_fds=True)
-    time.sleep(1)
-    # ensure port server is up
-    waits = 0
-    while True:
-      if waits > 10:
-        print('killing port server due to excessive start up waits')
-        port_server.kill()
-      if port_server.poll() is not None:
-        print('port_server failed to start')
-        # try one final time: maybe another build managed to start one
-        time.sleep(1)
-        try:
-          urllib.request.urlopen('http://localhost:%d/get' % port_server_port,
-                          timeout=1).read()
-          print('last ditch attempt to contact port server succeeded')
-          break
-        except:
-          traceback.print_exc()
-          port_log = open(logfile, 'r').read()
-          print(port_log)
-          sys.exit(1)
-      try:
-        urllib.request.urlopen('http://localhost:%d/get' % port_server_port,
-                        timeout=1).read()
-        print('port server is up and ready')
-        break
-      except socket.timeout:
-        print('waiting for port_server: timeout')
-        traceback.print_exc();
-        time.sleep(1)
-        waits += 1
-      except urllib.error.URLError:
-        print('waiting for port_server: urlerror')
-        traceback.print_exc();
-        time.sleep(1)
-        waits += 1
-      except:
-        traceback.print_exc()
-        port_server.kill()
-        raise
-
-
 def _calculate_num_runs_failures(list_of_results):
   """Caculate number of runs and failures for a particular test.
 
@@ -1459,7 +1452,7 @@
   antagonists = [subprocess.Popen(['tools/run_tests/python_utils/antagonist.py'])
                  for _ in range(0, args.antagonists)]
   port_server_port = 32766
-  _start_port_server(port_server_port)
+  start_port_server.start_port_server(port_server_port)
   resultset = None
   num_test_failures = 0
   try:
@@ -1478,8 +1471,18 @@
     else:
       # whereas otherwise, we want to shuffle things up to give all tests a
       # chance to run.
-      massaged_one_run = list(one_run)  # random.shuffle needs an indexable seq.
-      random.shuffle(massaged_one_run)  # which it modifies in-place.
+      massaged_one_run = list(one_run)  # random.sample needs an indexable seq.
+      num_jobs = len(massaged_one_run)
+      # for a random sample, get as many as indicated by the 'sample_percent'
+      # argument. By default this arg is 100, resulting in a shuffle of all
+      # jobs.
+      sample_size = int(num_jobs * args.sample_percent/100.0)
+      massaged_one_run = random.sample(massaged_one_run, sample_size)
+      if not isclose(args.sample_percent, 100.0):
+        print("Running %d tests out of %d (~%d%%)" %
+              (sample_size, num_jobs, args.sample_percent))
+      else:
+        assert args.runs_per_test == 1, "Can't do sampling (-p) over multiple runs (-n)."
     if infinite_runs:
       assert len(massaged_one_run) > 0, 'Must have at least one test for a -n inf run'
     runs_sequence = (itertools.repeat(massaged_one_run) if infinite_runs
@@ -1490,7 +1493,7 @@
       jobset.message('START', 'Running tests quietly, only failing tests will be reported', do_newline=True)
     num_test_failures, resultset = jobset.run(
         all_runs, check_cancelled, newline_on_success=newline_on_success,
-        travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
+        travis=args.travis, maxjobs=args.jobs,
         stop_on_failure=args.stop_on_failure,
         add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port},
         quiet_success=args.quiet_success)
diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py
index 5a109bd..bc4fdab 100755
--- a/tools/run_tests/run_tests_matrix.py
+++ b/tools/run_tests/run_tests_matrix.py
@@ -206,6 +206,18 @@
                                   extra_args=extra_args,
                                   inner_jobs=inner_jobs)
 
+  # cmake build for C and C++
+  # TODO(jtattermusch): some of the tests are failing, so we force --build_only
+  # to make sure it's buildable at least.
+  test_jobs += _generate_jobs(languages=['c', 'c++'],
+                              configs=['dbg'],
+                              platforms=['linux', 'windows'],
+                              arch='default',
+                              compiler='cmake',
+                              labels=['portability'],
+                              extra_args=extra_args + ['--build_only'],
+                              inner_jobs=inner_jobs)
+
   test_jobs += _generate_jobs(languages=['python'],
                               configs=['dbg'],
                               platforms=['linux'],
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index 0b68319..cfe4e27 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -44,7 +44,7 @@
  44c25c892a6229b20db7cd9dc05584ea865896de third_party/benchmark (v0.1.0-343-g44c25c8)
  78684e5b222645828ca302e56b40b9daff2b2d27 third_party/boringssl (78684e5)
  886e7d75368e3f4fab3f4d0d3584e4abfc557755 third_party/boringssl-with-bazel (version_for_cocoapods_7.0-857-g886e7d7)
- f8a0efe03aa69b3336d8e228b37d4ccb17324b88 third_party/gflags (v2.2.0)
+ 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e third_party/gflags (v2.2.0)
  c99458533a9b4c743ed51537e25989ea55944908 third_party/googletest (release-1.7.0)
  a428e42072765993ff674fda72863c9f1aa2d268 third_party/protobuf (v3.1.0-alpha-1)
  bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c third_party/thrift (bcad917)
diff --git a/tools/run_tests/sanity/sanity_tests.yaml b/tools/run_tests/sanity/sanity_tests.yaml
index ce41da8..445f53e 100644
--- a/tools/run_tests/sanity/sanity_tests.yaml
+++ b/tools/run_tests/sanity/sanity_tests.yaml
@@ -12,6 +12,7 @@
 - script: tools/distrib/check_trailing_newlines.sh
 - script: tools/distrib/check_nanopb_output.sh
 - script: tools/distrib/check_include_guards.py
+- script: tools/distrib/pylint_code.sh
 - script: tools/distrib/yapf_code.sh
 - script: tools/distrib/python/check_grpcio_tools.py
 
diff --git a/tools/run_tests/stress_test/cleanup_docker_images.sh b/tools/run_tests/stress_test/cleanup_docker_images.sh
new file mode 100755
index 0000000..e424fcf
--- /dev/null
+++ b/tools/run_tests/stress_test/cleanup_docker_images.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+for img in `docker images | grep \<none\> | awk '{print  $3 }'` ; do docker rmi -f $img; done
+
diff --git a/tools/run_tests/stress_test/run_on_gke.py b/tools/run_tests/stress_test/run_on_gke.py
index 583e583..e2be76e 100755
--- a/tools/run_tests/stress_test/run_on_gke.py
+++ b/tools/run_tests/stress_test/run_on_gke.py
@@ -312,7 +312,7 @@
           [container_cmd],
           [],  # Empty args list since all args are passed via env variables
           client_env,
-          False  # Client is not a headless service.
+          True  # Client is a headless service (no need for an external ip)
       )
 
       if not is_success:
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index f630200..623de48 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -80,6 +80,17 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bdp_estimator_test", "vcxproj\test\bdp_estimator_test\bdp_estimator_test.vcxproj", "{56314C05-7748-B7FD-F9DE-F975A0275427}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bin_decoder_test", "vcxproj\test\bin_decoder_test\bin_decoder_test.vcxproj", "{6BFAC6BA-3B9D-E8F5-BE35-91E8EFB9E25B}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -153,17 +164,6 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chttp2_status_conversion_test", "vcxproj\test\chttp2_status_conversion_test\chttp2_status_conversion_test.vcxproj", "{ABAD3D2C-078C-7850-B413-3352A07C6176}"
-	ProjectSection(myProperties) = preProject
-        	lib = "False"
-	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
-		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
-		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
-		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chttp2_stream_map_test", "vcxproj\test\chttp2_stream_map_test\chttp2_stream_map_test.vcxproj", "{12F9C5F8-1BDA-305F-5A0B-B0F9CC7AA7A4}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -424,6 +424,15 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_spinlock_test", "vcxproj\test\gpr_spinlock_test\gpr_spinlock_test.vcxproj", "{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_stack_lockfree_test", "vcxproj\test\gpr_stack_lockfree_test\gpr_stack_lockfree_test.vcxproj", "{AD06B5CD-8D5C-A365-C46B-3CF32237A4F7}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1082,39 +1091,6 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "internal_api_canary_iomgr_test", "vcxproj\test\internal_api_canary_iomgr_test\internal_api_canary_iomgr_test.vcxproj", "{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}"
-	ProjectSection(myProperties) = preProject
-        	lib = "False"
-	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
-		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
-		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
-		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "internal_api_canary_support_test", "vcxproj\test\internal_api_canary_support_test\internal_api_canary_support_test.vcxproj", "{D53575C6-713C-E6E3-FD74-E65F20916498}"
-	ProjectSection(myProperties) = preProject
-        	lib = "False"
-	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
-		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
-		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
-		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "internal_api_canary_transport_test", "vcxproj\test\internal_api_canary_transport_test\internal_api_canary_transport_test.vcxproj", "{ED24E700-964E-B426-6A6A-1944E2EF7BCB}"
-	ProjectSection(myProperties) = preProject
-        	lib = "False"
-	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
-		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
-		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
-		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "invalid_call_argument_test", "vcxproj\test\invalid_call_argument_test\invalid_call_argument_test.vcxproj", "{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1467,6 +1443,17 @@
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "status_conversion_test", "vcxproj\test\status_conversion_test\status_conversion_test.vcxproj", "{21E2A241-9D48-02CD-92E4-4EEC98424CF5}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcp_client_uv_test", "vcxproj\test\tcp_client_uv_test\tcp_client_uv_test.vcxproj", "{9814D850-F3BB-8C7A-4C78-2751C1E272F4}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1736,6 +1723,22 @@
 		{8A811C28-E04E-A444-E4C1-7588DF5B90AE}.Release-DLL|Win32.Build.0 = Release|Win32
 		{8A811C28-E04E-A444-E4C1-7588DF5B90AE}.Release-DLL|x64.ActiveCfg = Release|x64
 		{8A811C28-E04E-A444-E4C1-7588DF5B90AE}.Release-DLL|x64.Build.0 = Release|x64
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Debug|Win32.ActiveCfg = Debug|Win32
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Debug|x64.ActiveCfg = Debug|x64
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Release|Win32.ActiveCfg = Release|Win32
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Release|x64.ActiveCfg = Release|x64
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Debug|Win32.Build.0 = Debug|Win32
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Debug|x64.Build.0 = Debug|x64
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Release|Win32.Build.0 = Release|Win32
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Release|x64.Build.0 = Release|x64
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Debug-DLL|x64.Build.0 = Debug|x64
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Release-DLL|Win32.Build.0 = Release|Win32
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Release-DLL|x64.ActiveCfg = Release|x64
+		{56314C05-7748-B7FD-F9DE-F975A0275427}.Release-DLL|x64.Build.0 = Release|x64
 		{6BFAC6BA-3B9D-E8F5-BE35-91E8EFB9E25B}.Debug|Win32.ActiveCfg = Debug|Win32
 		{6BFAC6BA-3B9D-E8F5-BE35-91E8EFB9E25B}.Debug|x64.ActiveCfg = Debug|x64
 		{6BFAC6BA-3B9D-E8F5-BE35-91E8EFB9E25B}.Release|Win32.ActiveCfg = Release|Win32
@@ -1848,22 +1851,6 @@
 		{19F92966-3B0E-4FF8-CD7C-435D353E079E}.Release-DLL|Win32.Build.0 = Release|Win32
 		{19F92966-3B0E-4FF8-CD7C-435D353E079E}.Release-DLL|x64.ActiveCfg = Release|x64
 		{19F92966-3B0E-4FF8-CD7C-435D353E079E}.Release-DLL|x64.Build.0 = Release|x64
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Debug|Win32.ActiveCfg = Debug|Win32
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Debug|x64.ActiveCfg = Debug|x64
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Release|Win32.ActiveCfg = Release|Win32
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Release|x64.ActiveCfg = Release|x64
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Debug|Win32.Build.0 = Debug|Win32
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Debug|x64.Build.0 = Debug|x64
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Release|Win32.Build.0 = Release|Win32
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Release|x64.Build.0 = Release|x64
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Debug-DLL|x64.Build.0 = Debug|x64
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Release-DLL|Win32.Build.0 = Release|Win32
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Release-DLL|x64.ActiveCfg = Release|x64
-		{ABAD3D2C-078C-7850-B413-3352A07C6176}.Release-DLL|x64.Build.0 = Release|x64
 		{12F9C5F8-1BDA-305F-5A0B-B0F9CC7AA7A4}.Debug|Win32.ActiveCfg = Debug|Win32
 		{12F9C5F8-1BDA-305F-5A0B-B0F9CC7AA7A4}.Debug|x64.ActiveCfg = Debug|x64
 		{12F9C5F8-1BDA-305F-5A0B-B0F9CC7AA7A4}.Release|Win32.ActiveCfg = Release|Win32
@@ -2296,6 +2283,22 @@
 		{B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|Win32.Build.0 = Release|Win32
 		{B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|x64.ActiveCfg = Release|x64
 		{B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|x64.Build.0 = Release|x64
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Debug|x64.ActiveCfg = Debug|x64
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Release|Win32.ActiveCfg = Release|Win32
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Release|x64.ActiveCfg = Release|x64
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Debug|Win32.Build.0 = Debug|Win32
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Debug|x64.Build.0 = Debug|x64
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Release|Win32.Build.0 = Release|Win32
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Release|x64.Build.0 = Release|x64
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Debug-DLL|x64.Build.0 = Debug|x64
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Release-DLL|Win32.Build.0 = Release|Win32
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Release-DLL|x64.ActiveCfg = Release|x64
+		{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}.Release-DLL|x64.Build.0 = Release|x64
 		{AD06B5CD-8D5C-A365-C46B-3CF32237A4F7}.Debug|Win32.ActiveCfg = Debug|Win32
 		{AD06B5CD-8D5C-A365-C46B-3CF32237A4F7}.Debug|x64.ActiveCfg = Debug|x64
 		{AD06B5CD-8D5C-A365-C46B-3CF32237A4F7}.Release|Win32.ActiveCfg = Release|Win32
@@ -3256,54 +3259,6 @@
 		{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|Win32.Build.0 = Release|Win32
 		{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|x64.ActiveCfg = Release|x64
 		{6756895E-05BF-8CC7-58F2-868DF0C0300C}.Release-DLL|x64.Build.0 = Release|x64
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug|Win32.ActiveCfg = Debug|Win32
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug|x64.ActiveCfg = Debug|x64
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release|Win32.ActiveCfg = Release|Win32
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release|x64.ActiveCfg = Release|x64
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug|Win32.Build.0 = Debug|Win32
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug|x64.Build.0 = Debug|x64
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release|Win32.Build.0 = Release|Win32
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release|x64.Build.0 = Release|x64
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Debug-DLL|x64.Build.0 = Debug|x64
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release-DLL|Win32.Build.0 = Release|Win32
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release-DLL|x64.ActiveCfg = Release|x64
-		{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}.Release-DLL|x64.Build.0 = Release|x64
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug|x64.ActiveCfg = Debug|x64
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release|Win32.ActiveCfg = Release|Win32
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release|x64.ActiveCfg = Release|x64
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug|Win32.Build.0 = Debug|Win32
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug|x64.Build.0 = Debug|x64
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release|Win32.Build.0 = Release|Win32
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release|x64.Build.0 = Release|x64
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Debug-DLL|x64.Build.0 = Debug|x64
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release-DLL|Win32.Build.0 = Release|Win32
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release-DLL|x64.ActiveCfg = Release|x64
-		{D53575C6-713C-E6E3-FD74-E65F20916498}.Release-DLL|x64.Build.0 = Release|x64
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug|Win32.ActiveCfg = Debug|Win32
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug|x64.ActiveCfg = Debug|x64
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release|Win32.ActiveCfg = Release|Win32
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release|x64.ActiveCfg = Release|x64
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug|Win32.Build.0 = Debug|Win32
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug|x64.Build.0 = Debug|x64
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release|Win32.Build.0 = Release|Win32
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release|x64.Build.0 = Release|x64
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Debug-DLL|x64.Build.0 = Debug|x64
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release-DLL|Win32.Build.0 = Release|Win32
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release-DLL|x64.ActiveCfg = Release|x64
-		{ED24E700-964E-B426-6A6A-1944E2EF7BCB}.Release-DLL|x64.Build.0 = Release|x64
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Debug|Win32.ActiveCfg = Debug|Win32
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Debug|x64.ActiveCfg = Debug|x64
 		{C32CA8A3-58E6-8EB9-B72F-C295547D36A6}.Release|Win32.ActiveCfg = Release|Win32
@@ -3816,6 +3771,22 @@
 		{529771F0-10B0-9B1A-1E7E-8A8E01870348}.Release-DLL|Win32.Build.0 = Release|Win32
 		{529771F0-10B0-9B1A-1E7E-8A8E01870348}.Release-DLL|x64.ActiveCfg = Release|x64
 		{529771F0-10B0-9B1A-1E7E-8A8E01870348}.Release-DLL|x64.Build.0 = Release|x64
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Debug|Win32.ActiveCfg = Debug|Win32
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Debug|x64.ActiveCfg = Debug|x64
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release|Win32.ActiveCfg = Release|Win32
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release|x64.ActiveCfg = Release|x64
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Debug|Win32.Build.0 = Debug|Win32
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Debug|x64.Build.0 = Debug|x64
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release|Win32.Build.0 = Release|Win32
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release|x64.Build.0 = Release|x64
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Debug-DLL|x64.Build.0 = Debug|x64
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|Win32.Build.0 = Release|Win32
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|x64.ActiveCfg = Release|x64
+		{21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|x64.Build.0 = Release|x64
 		{9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug|Win32.ActiveCfg = Debug|Win32
 		{9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Debug|x64.ActiveCfg = Debug|x64
 		{9814D850-F3BB-8C7A-4C78-2751C1E272F4}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj
index c4f9c55..44c21dd 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj
@@ -193,6 +193,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\env.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\mpscq.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\spinlock.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\string_windows.h" />
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
index 77a1ba6..a5924a6 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
@@ -269,6 +269,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\murmur_hash.h">
       <Filter>src\core\lib\support</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\spinlock.h">
+      <Filter>src\core\lib\support</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\support\stack_lockfree.h">
       <Filter>src\core\lib\support</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
index bd9c546..45f3037 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
@@ -264,9 +264,11 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\completion_queue.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\create_channel.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\create_channel_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\ext\health_check_service_server_builder_option.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\generic\async_generic_service.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\generic\generic_stub.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\grpc++.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\health_check_service_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\client_unary_call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen.h" />
@@ -313,6 +315,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
@@ -321,6 +324,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_helper.h" />
@@ -347,6 +351,8 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen.h" />
@@ -356,6 +362,8 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\common\channel_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\default_health_check_service.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\thread_manager\thread_manager.h" />
   </ItemGroup>
@@ -410,6 +418,14 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.cc">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\default_health_check_service.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health_check_service.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health_check_service_server_builder_option.cc">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\server_builder.cc">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\server_cc.cc">
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
index 93d8274..95cdb74 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
@@ -76,6 +76,18 @@
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.cc">
       <Filter>src\cpp\server</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\default_health_check_service.cc">
+      <Filter>src\cpp\server\health</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.c">
+      <Filter>src\cpp\server\health</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health_check_service.cc">
+      <Filter>src\cpp\server\health</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health_check_service_server_builder_option.cc">
+      <Filter>src\cpp\server\health</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\server_builder.cc">
       <Filter>src\cpp\server</Filter>
     </ClCompile>
@@ -132,6 +144,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\create_channel_posix.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\ext\health_check_service_server_builder_option.h">
+      <Filter>include\grpc++\ext</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\generic\async_generic_service.h">
       <Filter>include\grpc++\generic</Filter>
     </ClInclude>
@@ -141,6 +156,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\grpc++.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\health_check_service_interface.h">
+      <Filter>include\grpc++</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\call.h">
       <Filter>include\grpc++\impl</Filter>
     </ClInclude>
@@ -279,6 +297,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -303,6 +324,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -381,6 +405,12 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
       <Filter>include\grpc\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen.h">
@@ -404,6 +434,12 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h">
       <Filter>src\cpp\server</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\default_health_check_service.h">
+      <Filter>src\cpp\server\health</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.h">
+      <Filter>src\cpp\server\health</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h">
       <Filter>src\cpp\server</Filter>
     </ClInclude>
@@ -422,6 +458,9 @@
     <Filter Include="include\grpc++">
       <UniqueIdentifier>{784a0281-f547-aeb0-9f55-b26b7de9c769}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc++\ext">
+      <UniqueIdentifier>{25501d8e-5fae-2fe4-14a6-d69a07acefdd}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++\generic">
       <UniqueIdentifier>{51dae921-3aa2-1976-2ee4-c5615de1af54}</UniqueIdentifier>
     </Filter>
@@ -464,6 +503,9 @@
     <Filter Include="src\cpp\server">
       <UniqueIdentifier>{321b0980-74ad-e8ca-f23b-deffa5d6bb8f}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\cpp\server\health">
+      <UniqueIdentifier>{5bc9ef4e-78c1-159e-4e4e-30ddfce3e140}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\cpp\thread_manager">
       <UniqueIdentifier>{23f9df56-8604-52a0-e6a2-f01b8e68d0e7}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj b/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj
deleted file mode 100644
index cd3e406..0000000
--- a/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj
+++ /dev/null
@@ -1,170 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{3D3EAEA9-76C4-0CFE-4718-5A1F6B7F72C8}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>grpc++_test</TargetName>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>grpc++_test</TargetName>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\test\server_context_test_spouse.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\cpp\test\server_context_test_spouse.cc">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj.filters b/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj.filters
deleted file mode 100644
index e1d8fe1..0000000
--- a/vsprojects/vcxproj/grpc++_test/grpc++_test.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\src\cpp\test\server_context_test_spouse.cc">
-      <Filter>src\cpp\test</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="$(SolutionDir)\..\include\grpc++\test\server_context_test_spouse.h">
-      <Filter>include\grpc++\test</Filter>
-    </ClInclude>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="include">
-      <UniqueIdentifier>{418e2be9-9a04-af8a-8878-956543c507a1}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc++">
-      <UniqueIdentifier>{bcaf3a2d-e884-bfbd-477b-09634054bcc5}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="include\grpc++\test">
-      <UniqueIdentifier>{3a14b66f-1d31-2d06-e9a1-c6d1199ab04d}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src">
-      <UniqueIdentifier>{bc08c75b-ee7e-85a0-fb0f-7586bbd33c6f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src\cpp">
-      <UniqueIdentifier>{9797a57d-93ac-ff9c-5ac6-fd335777d782}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="src\cpp\test">
-      <UniqueIdentifier>{58d4b4e0-5617-abf4-48a6-f1264d127b27}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
index 7eba5c5..13d80ec 100644
--- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
@@ -160,6 +160,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
@@ -168,6 +169,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_helper.h" />
@@ -208,6 +210,14 @@
     <ClInclude Include="$(SolutionDir)\..\test\cpp\util\test_credentials_provider.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.grpc.pb.h">
+    </ClInclude>
     <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.cc">
     </ClCompile>
     <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.h">
diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
index 9a10e07..7981feb 100644
--- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
@@ -1,6 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\health\v1\health.proto">
+      <Filter>src\proto\grpc\health\v1</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.proto">
       <Filter>src\proto\grpc\testing</Filter>
     </ClCompile>
@@ -72,6 +75,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -96,6 +102,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -248,6 +257,12 @@
     <Filter Include="src\proto\grpc">
       <UniqueIdentifier>{f3daac52-2bfd-362e-9a76-04cd7a90aa34}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\proto\grpc\health">
+      <UniqueIdentifier>{d2393dd7-6f95-0e70-c36d-cd8ef8e2f17e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\health\v1">
+      <UniqueIdentifier>{f2f10901-f74f-a55a-abea-082923feb664}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\proto\grpc\testing">
       <UniqueIdentifier>{3df5f11f-e018-1126-8c22-291540035aa8}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
index 7f2e815..22ea361 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -264,9 +264,11 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\completion_queue.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\create_channel.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\create_channel_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\ext\health_check_service_server_builder_option.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\generic\async_generic_service.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\generic\generic_stub.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\grpc++.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\health_check_service_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\client_unary_call.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen.h" />
@@ -313,6 +315,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
@@ -321,6 +324,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_helper.h" />
@@ -352,6 +356,8 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\common\channel_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\default_health_check_service.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\cpp\thread_manager\thread_manager.h" />
   </ItemGroup>
@@ -396,6 +402,14 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.cc">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\default_health_check_service.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health_check_service.cc">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health_check_service_server_builder_option.cc">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\server_builder.cc">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\server_cc.cc">
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index df62384..c3cef2d 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -61,6 +61,18 @@
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.cc">
       <Filter>src\cpp\server</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\default_health_check_service.cc">
+      <Filter>src\cpp\server\health</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.c">
+      <Filter>src\cpp\server\health</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health_check_service.cc">
+      <Filter>src\cpp\server\health</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\cpp\server\health\health_check_service_server_builder_option.cc">
+      <Filter>src\cpp\server\health</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\server\server_builder.cc">
       <Filter>src\cpp\server</Filter>
     </ClCompile>
@@ -117,6 +129,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\create_channel_posix.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\ext\health_check_service_server_builder_option.h">
+      <Filter>include\grpc++\ext</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\generic\async_generic_service.h">
       <Filter>include\grpc++\generic</Filter>
     </ClInclude>
@@ -126,6 +141,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\grpc++.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\health_check_service_interface.h">
+      <Filter>include\grpc++</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\call.h">
       <Filter>include\grpc++\impl</Filter>
     </ClInclude>
@@ -264,6 +282,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -288,6 +309,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -377,6 +401,12 @@
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h">
       <Filter>src\cpp\server</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\default_health_check_service.h">
+      <Filter>src\cpp\server\health</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\cpp\server\health\health.pb.h">
+      <Filter>src\cpp\server\health</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h">
       <Filter>src\cpp\server</Filter>
     </ClInclude>
@@ -395,6 +425,9 @@
     <Filter Include="include\grpc++">
       <UniqueIdentifier>{eceb50c0-bb49-3812-b6bd-b0af6df81da7}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc++\ext">
+      <UniqueIdentifier>{e6643be2-2b2f-953d-ab14-27d89c835c8a}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++\generic">
       <UniqueIdentifier>{83717d3c-57d9-2bfa-ed9c-2b08f86da12b}</UniqueIdentifier>
     </Filter>
@@ -437,6 +470,9 @@
     <Filter Include="src\cpp\server">
       <UniqueIdentifier>{8a54a279-d14b-4237-0df3-1ffe1ef5a7af}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\cpp\server\health">
+      <UniqueIdentifier>{a003cb5c-7249-106c-8ee5-de5e11a6692c}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\cpp\thread_manager">
       <UniqueIdentifier>{e5b55f25-d99f-b8e5-9981-7da7fa7ba628}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index c159db6..fde60be 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -273,6 +273,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
@@ -323,6 +324,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
@@ -375,6 +377,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
@@ -388,14 +391,18 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
@@ -412,11 +419,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_errors.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
@@ -433,6 +438,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\lb_targets_info.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.h" />
@@ -449,11 +455,14 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
@@ -462,6 +471,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb_channel.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
@@ -481,6 +491,11 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_label.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_propagation.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_status.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\tracing.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
@@ -653,6 +668,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
@@ -691,11 +710,13 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
     </ClCompile>
@@ -707,6 +728,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
@@ -747,8 +770,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
@@ -791,6 +812,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\client_auth_filter.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\lb_targets_info.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.c">
@@ -831,6 +854,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.c">
@@ -841,6 +866,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.c">
@@ -865,6 +894,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb_channel_secure.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 1e099f3..8edbbc2 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -256,6 +256,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -313,13 +319,16 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
@@ -337,6 +346,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
@@ -397,9 +409,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.c">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
@@ -463,6 +472,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\client_auth_filter.c">
       <Filter>src\core\lib\security\transport</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\lb_targets_info.c">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.c">
       <Filter>src\core\lib\security\transport</Filter>
     </ClCompile>
@@ -523,6 +535,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
@@ -538,6 +553,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
@@ -574,6 +595,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.c">
       <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb_channel_secure.c">
+      <Filter>src\core\ext\lb_policy\grpclb</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
       <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClCompile>
@@ -672,6 +696,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
@@ -818,6 +845,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -974,6 +1004,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
@@ -1013,13 +1046,22 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
@@ -1037,6 +1079,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
@@ -1085,9 +1130,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_errors.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
@@ -1097,9 +1139,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
@@ -1148,6 +1187,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h">
       <Filter>src\core\lib\security\transport</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\lb_targets_info.h">
+      <Filter>src\core\lib\security\transport</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h">
       <Filter>src\core\lib\security\transport</Filter>
     </ClInclude>
@@ -1196,6 +1238,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
@@ -1211,6 +1256,12 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
@@ -1235,6 +1286,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h">
       <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb_channel.h">
+      <Filter>src\core\ext\lb_policy\grpclb</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h">
       <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClInclude>
@@ -1292,6 +1346,21 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_label.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_propagation.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_status.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_string.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\tracing.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index 230c3eb..6d4b4f7 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -153,6 +153,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
@@ -184,6 +185,7 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\fixtures\http_proxy.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\fixtures\proxy.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\debugger_macros.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\grpc_profiler.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\memory_counters.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\mock_endpoint.h" />
@@ -192,6 +194,7 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port_server_client.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
@@ -216,6 +219,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
@@ -268,6 +272,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
@@ -281,14 +286,18 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
@@ -314,6 +323,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\debugger_macros.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\grpc_profiler.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\memory_counters.c">
@@ -334,6 +345,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\slice_splitter.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
@@ -502,6 +515,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
@@ -540,11 +557,13 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
     </ClCompile>
@@ -556,6 +575,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
index 46a3815..5444f6f 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -31,6 +31,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.c">
       <Filter>test\core\iomgr</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\debugger_macros.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\grpc_profiler.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
@@ -61,6 +64,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\util\slice_splitter.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
       <Filter>src\core\lib\channel</Filter>
     </ClCompile>
@@ -313,6 +319,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -370,13 +382,16 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
@@ -394,6 +409,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
@@ -423,6 +441,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
@@ -512,6 +533,9 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.h">
       <Filter>test\core\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\debugger_macros.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\test\core\util\grpc_profiler.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
@@ -536,6 +560,9 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
       <Filter>src\core\lib\channel</Filter>
     </ClInclude>
@@ -608,6 +635,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -764,6 +794,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
@@ -803,13 +836,22 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
@@ -827,6 +869,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
index 7f3e101..1ea6465 100644
--- a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj
@@ -152,6 +152,7 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\fixtures\http_proxy.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\fixtures\proxy.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\debugger_macros.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\grpc_profiler.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\memory_counters.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\mock_endpoint.h" />
@@ -160,6 +161,7 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\port_server_client.h" />
     <ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\cq_verifier.c">
@@ -172,6 +174,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\debugger_macros.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\grpc_profiler.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\memory_counters.c">
@@ -192,6 +196,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\slice_splitter.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.c">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
diff --git a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
index 8be9f5b..e2ad88c 100644
--- a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters
@@ -16,6 +16,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.c">
       <Filter>test\core\iomgr</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\debugger_macros.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\util\grpc_profiler.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
@@ -46,6 +49,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\util\slice_splitter.c">
       <Filter>test\core\util</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\test\core\end2end\cq_verifier.h">
@@ -63,6 +69,9 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\iomgr\endpoint_tests.h">
       <Filter>test\core\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\debugger_macros.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\test\core\util\grpc_profiler.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
@@ -87,6 +96,9 @@
     <ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h">
       <Filter>test\core\util</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\test\core\util\trickle_endpoint.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index dcb943a..22f4740 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -264,6 +264,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice_buffer.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
@@ -313,6 +314,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
@@ -365,6 +367,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
@@ -378,14 +381,18 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
@@ -402,11 +409,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_encoder.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_parser.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_errors.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\incoming_metadata.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" />
@@ -416,11 +421,14 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
@@ -430,6 +438,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting_filter.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb_channel.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
@@ -447,6 +456,11 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_label.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_propagation.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_status.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\tracing.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
@@ -621,6 +635,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
@@ -659,11 +677,13 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
     </ClCompile>
@@ -675,6 +695,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
@@ -717,8 +739,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.c">
@@ -751,6 +771,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.c">
@@ -761,6 +783,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.c">
@@ -783,6 +809,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb_channel.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index ac84e01..5021cb4 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -259,6 +259,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_buffer.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_intern.c">
+      <Filter>src\core\lib\slice</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\slice\slice_string_helpers.c">
       <Filter>src\core\lib\slice</Filter>
     </ClCompile>
@@ -316,13 +322,16 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
       <Filter>src\core\lib\surface</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
@@ -340,6 +349,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.c">
+      <Filter>src\core\lib\transport</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
       <Filter>src\core\lib\transport</Filter>
     </ClCompile>
@@ -403,9 +415,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\parsing.c">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.c">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_lists.c">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClCompile>
@@ -454,6 +463,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
@@ -469,6 +481,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.c">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
@@ -502,6 +520,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.c">
       <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb_channel.c">
+      <Filter>src\core\ext\lb_policy\grpclb</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
       <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClCompile>
@@ -588,6 +609,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security_constants.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\load_reporting.h">
+      <Filter>include\grpc</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\slice.h">
       <Filter>include\grpc</Filter>
     </ClInclude>
@@ -731,6 +755,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h">
+      <Filter>src\core\lib\iomgr</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h">
       <Filter>src\core\lib\iomgr</Filter>
     </ClInclude>
@@ -887,6 +914,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\percent_encoding.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_hash_table.h">
+      <Filter>src\core\lib\slice</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\slice\slice_internal.h">
       <Filter>src\core\lib\slice</Filter>
     </ClInclude>
@@ -926,13 +956,22 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
       <Filter>src\core\lib\surface</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.h">
+      <Filter>src\core\lib\surface</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\bdp_estimator.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h">
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\error_utils.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\http2_errors.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
@@ -950,6 +989,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\status_conversion.h">
+      <Filter>src\core\lib\transport</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h">
       <Filter>src\core\lib\transport</Filter>
     </ClInclude>
@@ -998,9 +1040,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\hpack_table.h">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\http2_errors.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\huffsyms.h">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
@@ -1010,9 +1049,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\internal.h">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\status_conversion.h">
-      <Filter>src\core\ext\transport\chttp2\transport</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h">
       <Filter>src\core\ext\transport\chttp2\transport</Filter>
     </ClInclude>
@@ -1040,6 +1076,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
@@ -1055,6 +1094,12 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\proxy_mapper_registry.h">
+      <Filter>src\core\ext\client_channel</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
@@ -1082,6 +1127,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h">
       <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb_channel.h">
+      <Filter>src\core\ext\lb_policy\grpclb</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h">
       <Filter>src\core\ext\lb_policy\grpclb</Filter>
     </ClInclude>
@@ -1133,6 +1181,21 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_label.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_propagation.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_status.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_string.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\tracing.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/vsprojects/vcxproj/test/bdp_estimator_test/bdp_estimator_test.vcxproj b/vsprojects/vcxproj/test/bdp_estimator_test/bdp_estimator_test.vcxproj
new file mode 100644
index 0000000..e37d7b9
--- /dev/null
+++ b/vsprojects/vcxproj/test/bdp_estimator_test/bdp_estimator_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{56314C05-7748-B7FD-F9DE-F975A0275427}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>bdp_estimator_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>bdp_estimator_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\transport\bdp_estimator_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/bdp_estimator_test/bdp_estimator_test.vcxproj.filters b/vsprojects/vcxproj/test/bdp_estimator_test/bdp_estimator_test.vcxproj.filters
new file mode 100644
index 0000000..e45ccf8
--- /dev/null
+++ b/vsprojects/vcxproj/test/bdp_estimator_test/bdp_estimator_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\transport\bdp_estimator_test.c">
+      <Filter>test\core\transport</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{1b8a7ad9-0b72-aa3d-2dc8-80ad82788751}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{f503dc16-2668-27d5-0d1d-d32667aec533}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\transport">
+      <UniqueIdentifier>{0880eed5-543c-6ede-ac40-270a662f2563}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj b/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj
deleted file mode 100644
index 3809beb..0000000
--- a/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj
+++ /dev/null
@@ -1,210 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{4AAFDA9D-A596-DE6D-8288-A9219D7EBD93}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>bm_fullstack</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>bm_fullstack</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\microbenchmarks\bm_fullstack.cc">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\benchmark\benchmark.vcxproj">
-      <Project>{07978586-E47C-8709-A63E-895FBF3C3C7D}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
-      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj.filters b/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj.filters
deleted file mode 100644
index 76b29ad..0000000
--- a/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj.filters
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\microbenchmarks\bm_fullstack.cc">
-      <Filter>test\cpp\microbenchmarks</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{a2580d22-fbdd-9841-08c9-3173349c0837}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\cpp">
-      <UniqueIdentifier>{3d07ea20-516b-1ac1-4564-f1f04c929e99}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\cpp\microbenchmarks">
-      <UniqueIdentifier>{c130900b-fb0a-d96a-530e-f837d1a9582e}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/chttp2_status_conversion_test/chttp2_status_conversion_test.vcxproj b/vsprojects/vcxproj/test/chttp2_status_conversion_test/chttp2_status_conversion_test.vcxproj
deleted file mode 100644
index f5b8838..0000000
--- a/vsprojects/vcxproj/test/chttp2_status_conversion_test/chttp2_status_conversion_test.vcxproj
+++ /dev/null
@@ -1,199 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{ABAD3D2C-078C-7850-B413-3352A07C6176}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>chttp2_status_conversion_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>chttp2_status_conversion_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\transport\chttp2\status_conversion_test.c">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/chttp2_status_conversion_test/chttp2_status_conversion_test.vcxproj.filters b/vsprojects/vcxproj/test/chttp2_status_conversion_test/chttp2_status_conversion_test.vcxproj.filters
deleted file mode 100644
index d94af50..0000000
--- a/vsprojects/vcxproj/test/chttp2_status_conversion_test/chttp2_status_conversion_test.vcxproj.filters
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\transport\chttp2\status_conversion_test.c">
-      <Filter>test\core\transport\chttp2</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{29690dfb-a808-84b3-d82e-deadb5d04103}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core">
-      <UniqueIdentifier>{d17e51ca-73ac-6f31-d02c-631ac849c194}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\transport">
-      <UniqueIdentifier>{3f03cd74-998e-23ed-a372-a1b706d35bf4}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\transport\chttp2">
-      <UniqueIdentifier>{b65a9b0c-fa3d-1919-b70f-9d2d5cc28077}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj
index ad6865a..986217b 100644
--- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj
+++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj
@@ -173,6 +173,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
@@ -181,6 +182,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_helper.h" />
diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters
index 1b367b1..b48fe4f 100644
--- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters
+++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters
@@ -60,6 +60,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -84,6 +87,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj
index 9df6702..fd014fd 100644
--- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj
+++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj
@@ -173,6 +173,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
@@ -181,6 +182,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_helper.h" />
diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters
index c8f62ff..176204f 100644
--- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters
+++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters
@@ -63,6 +63,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -87,6 +90,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
index 6506f24..08b3acd 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
@@ -199,6 +199,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\invoke_large_request.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\keepalive_timeout.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\large_metadata.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\load_reporting_hook.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
index 77e5ebf..3a8670c 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
@@ -73,6 +73,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\invoke_large_request.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\keepalive_timeout.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\large_metadata.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
index 176e8f7..96418c3 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
@@ -201,6 +201,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\invoke_large_request.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\keepalive_timeout.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\large_metadata.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\load_reporting_hook.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
index fa70267..cf40abe 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
@@ -76,6 +76,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\invoke_large_request.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\keepalive_timeout.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\large_metadata.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/gpr_spinlock_test/gpr_spinlock_test.vcxproj b/vsprojects/vcxproj/test/gpr_spinlock_test/gpr_spinlock_test.vcxproj
new file mode 100644
index 0000000..a2f3d2e
--- /dev/null
+++ b/vsprojects/vcxproj/test/gpr_spinlock_test/gpr_spinlock_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{D8EDE51A-CBB2-0362-D59B-09AA92A94F45}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>gpr_spinlock_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>gpr_spinlock_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\support\spinlock_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/gpr_spinlock_test/gpr_spinlock_test.vcxproj.filters b/vsprojects/vcxproj/test/gpr_spinlock_test/gpr_spinlock_test.vcxproj.filters
new file mode 100644
index 0000000..3e9d061
--- /dev/null
+++ b/vsprojects/vcxproj/test/gpr_spinlock_test/gpr_spinlock_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\support\spinlock_test.c">
+      <Filter>test\core\support</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{f79012a0-59dc-e99f-b27d-78bbccc328a1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{3aa9f8c4-b90f-3b8b-e967-900dbe335130}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\support">
+      <UniqueIdentifier>{51bef72c-ce73-a264-d69b-3711b6599f8c}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj
index 88e4bf6..e5d4f0b 100644
--- a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj
+++ b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj
@@ -174,6 +174,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
@@ -182,6 +183,7 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_helper.h" />
diff --git a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters
index fece7f3..5cba594 100644
--- a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters
+++ b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters
@@ -54,6 +54,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
@@ -78,6 +81,9 @@
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
       <Filter>include\grpc++\impl\codegen</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/test/grpclb_test/grpclb_test.vcxproj b/vsprojects/vcxproj/test/grpclb_test/grpclb_test.vcxproj
index 91b9a6e..cd5aa4c 100644
--- a/vsprojects/vcxproj/test/grpclb_test/grpclb_test.vcxproj
+++ b/vsprojects/vcxproj/test/grpclb_test/grpclb_test.vcxproj
@@ -172,24 +172,24 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
-    </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
       <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
     </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
       <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
     </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />
diff --git a/vsprojects/vcxproj/test/health_service_end2end_test/health_service_end2end_test.vcxproj b/vsprojects/vcxproj/test/health_service_end2end_test/health_service_end2end_test.vcxproj
new file mode 100644
index 0000000..28530d0
--- /dev/null
+++ b/vsprojects/vcxproj/test/health_service_end2end_test/health_service_end2end_test.vcxproj
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{3EB2B3E9-8BC3-8DF7-82CB-38462FFE5919}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>health_service_end2end_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>health_service_end2end_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\health_service_end2end_test.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/health_service_end2end_test/health_service_end2end_test.vcxproj.filters b/vsprojects/vcxproj/test/health_service_end2end_test/health_service_end2end_test.vcxproj.filters
new file mode 100644
index 0000000..cccf968
--- /dev/null
+++ b/vsprojects/vcxproj/test/health_service_end2end_test/health_service_end2end_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\health_service_end2end_test.cc">
+      <Filter>test\cpp\end2end</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{00d750b2-db02-2106-d9b7-1d3b2ca58604}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{02e29b2f-d68a-4474-8483-621ecfd7fa9d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\end2end">
+      <UniqueIdentifier>{b0de697a-d73a-23e1-c9af-fa0edf011d4d}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj b/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj
deleted file mode 100644
index 11d89a0..0000000
--- a/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj
+++ /dev/null
@@ -1,199 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{28AE726B-1BFB-202B-48D2-41AF9D09B9EA}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>internal_api_canary_iomgr_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>internal_api_canary_iomgr_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj.filters b/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj.filters
deleted file mode 100644
index f1ee82d..0000000
--- a/vsprojects/vcxproj/test/internal_api_canary_iomgr_test/internal_api_canary_iomgr_test.vcxproj.filters
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
-      <Filter>test\core\internal_api_canaries</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{881986d1-d1fe-b377-cf26-b3377af95009}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core">
-      <UniqueIdentifier>{4f9a544e-5680-18ee-30d7-38179bf82cee}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\internal_api_canaries">
-      <UniqueIdentifier>{6ab29f78-ec9d-d63a-8e8f-0d7552b3edd4}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj b/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj
deleted file mode 100644
index 59092dc..0000000
--- a/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj
+++ /dev/null
@@ -1,199 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{D53575C6-713C-E6E3-FD74-E65F20916498}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>internal_api_canary_support_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>internal_api_canary_support_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj.filters b/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj.filters
deleted file mode 100644
index f7f4e32..0000000
--- a/vsprojects/vcxproj/test/internal_api_canary_support_test/internal_api_canary_support_test.vcxproj.filters
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
-      <Filter>test\core\internal_api_canaries</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{a6c31cba-af9d-78ea-8980-8b77c9fc4485}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core">
-      <UniqueIdentifier>{d84283b8-4529-6c09-18bf-20a69f14f7ab}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\internal_api_canaries">
-      <UniqueIdentifier>{ea379f93-9285-7180-0d69-24a56da2b201}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj b/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj
deleted file mode 100644
index 110f7e3..0000000
--- a/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj
+++ /dev/null
@@ -1,199 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{ED24E700-964E-B426-6A6A-1944E2EF7BCB}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>internal_api_canary_transport_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>internal_api_canary_transport_test</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj.filters b/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj.filters
deleted file mode 100644
index 1e0b4c5..0000000
--- a/vsprojects/vcxproj/test/internal_api_canary_transport_test/internal_api_canary_transport_test.vcxproj.filters
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\internal_api_canaries\iomgr.c">
-      <Filter>test\core\internal_api_canaries</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{38e59e26-aad9-60fd-a1a7-c8fd9b606e2f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core">
-      <UniqueIdentifier>{79aad60f-59b8-09e2-2cad-5b5e083ac008}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\core\internal_api_canaries">
-      <UniqueIdentifier>{e4f0214e-e3ec-b5b8-c00b-2932b5ec2422}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj b/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj
deleted file mode 100644
index 34507b6..0000000
--- a/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj
+++ /dev/null
@@ -1,210 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{91678827-DAEF-2E2F-9CD1-1F5E5DD54842}</ProjectGuid>
-    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
-    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
-    <PlatformToolset>v100</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
-    <PlatformToolset>v110</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
-    <PlatformToolset>v120</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
-    <PlatformToolset>v140</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
-    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>json_run_localhost</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>json_run_localhost</TargetName>
-    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
-    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
-    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
-    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
-  </PropertyGroup>
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <SDLCheck>true</SDLCheck>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <TreatWarningAsError>true</TreatWarningAsError>
-      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
-      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
-      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\json_run_localhost.cc">
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
-      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
-      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
-      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
-      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
-      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
-      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
-    </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
-      <Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</Project>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
-  </ImportGroup>
-  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
-    <PropertyGroup>
-      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
-    </PropertyGroup>
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
-    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
-  </Target>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj.filters b/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj.filters
deleted file mode 100644
index 84c5d1e..0000000
--- a/vsprojects/vcxproj/test/json_run_localhost/json_run_localhost.vcxproj.filters
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\json_run_localhost.cc">
-      <Filter>test\cpp\qps</Filter>
-    </ClCompile>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Filter Include="test">
-      <UniqueIdentifier>{6a0e8372-94ed-67cd-edda-56ba97debf76}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\cpp">
-      <UniqueIdentifier>{2a065f28-e35d-1a75-6e12-fd86e7b99443}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="test\cpp\qps">
-      <UniqueIdentifier>{6eec400a-a3a2-2904-8b49-92aeb69c4448}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-</Project>
-
diff --git a/vsprojects/vcxproj/test/proto_utils_test/proto_utils_test.vcxproj b/vsprojects/vcxproj/test/proto_utils_test/proto_utils_test.vcxproj
new file mode 100644
index 0000000..fc23556
--- /dev/null
+++ b/vsprojects/vcxproj/test/proto_utils_test/proto_utils_test.vcxproj
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{D55F5F6B-BAB1-C421-7138-CDC08C686DCF}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>proto_utils_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>proto_utils_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_helper.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\codegen\proto_utils_test.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/proto_utils_test/proto_utils_test.vcxproj.filters b/vsprojects/vcxproj/test/proto_utils_test/proto_utils_test.vcxproj.filters
new file mode 100644
index 0000000..e6b4a92
--- /dev/null
+++ b/vsprojects/vcxproj/test/proto_utils_test/proto_utils_test.vcxproj.filters
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\codegen\proto_utils_test.cc">
+      <Filter>test\cpp\codegen</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\metadata_map.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h">
+      <Filter>include\grpc++\impl\codegen\security</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\slice.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_helper.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\exec_ctx_fwd.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
+      <Filter>include\grpc\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+      <Filter>include\grpc++\impl\codegen</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="include">
+      <UniqueIdentifier>{cc3989e4-cb32-e89b-2d05-41ad6dd1dfdf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc">
+      <UniqueIdentifier>{59dc67c7-fb18-960b-db77-99ea8e6c0a5f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++">
+      <UniqueIdentifier>{6c2c28e0-a57f-8eb7-4897-41ec191373f9}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl">
+      <UniqueIdentifier>{6740e44a-b709-0cb2-faa4-c1a792d909c5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen">
+      <UniqueIdentifier>{cbb79e1d-95bc-e475-8e86-af33a7603af1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc++\impl\codegen\security">
+      <UniqueIdentifier>{c4a45c0f-ccce-7e26-d0bb-9e54ad676140}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl">
+      <UniqueIdentifier>{4aff0d7b-5c9d-080c-faa6-e8126853f149}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="include\grpc\impl\codegen">
+      <UniqueIdentifier>{35a120bf-8b2f-77e1-cab7-24259b5ed1db}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test">
+      <UniqueIdentifier>{9d60ac43-ff38-4dfc-8c33-9167fb47fa90}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{7845357d-2b4b-6f25-c68b-79be9ab587fb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\codegen">
+      <UniqueIdentifier>{22e8c70f-796c-f2c0-d87d-e4ef419609a1}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/server_context_test_spouse_test/server_context_test_spouse_test.vcxproj b/vsprojects/vcxproj/test/server_context_test_spouse_test/server_context_test_spouse_test.vcxproj
index 9e586c6..fe2b1ab 100644
--- a/vsprojects/vcxproj/test/server_context_test_spouse_test/server_context_test_spouse_test.vcxproj
+++ b/vsprojects/vcxproj/test/server_context_test_spouse_test/server_context_test_spouse_test.vcxproj
@@ -167,9 +167,6 @@
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
       <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
     </ProjectReference>
-    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test\grpc++_test.vcxproj">
-      <Project>{3D3EAEA9-76C4-0CFE-4718-5A1F6B7F72C8}</Project>
-    </ProjectReference>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
       <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
     </ProjectReference>
diff --git a/vsprojects/vcxproj/test/status_conversion_test/status_conversion_test.vcxproj b/vsprojects/vcxproj/test/status_conversion_test/status_conversion_test.vcxproj
new file mode 100644
index 0000000..ab1e3a7
--- /dev/null
+++ b/vsprojects/vcxproj/test/status_conversion_test/status_conversion_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{21E2A241-9D48-02CD-92E4-4EEC98424CF5}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>status_conversion_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>status_conversion_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\transport\status_conversion_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/status_conversion_test/status_conversion_test.vcxproj.filters b/vsprojects/vcxproj/test/status_conversion_test/status_conversion_test.vcxproj.filters
new file mode 100644
index 0000000..72ebef5
--- /dev/null
+++ b/vsprojects/vcxproj/test/status_conversion_test/status_conversion_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\transport\status_conversion_test.c">
+      <Filter>test\core\transport</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{4702a9eb-d239-c799-0712-b7af210665bd}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{2f2eed07-7d0f-4b4a-67c0-96e860bb6b16}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\transport">
+      <UniqueIdentifier>{269c6750-9126-9b6a-4196-b7cbe492ee9f}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+