Merge pull request #12850 from markdroth/lb_pick_error_fix

Return LB picks with an error upon shutdown.
diff --git a/.clang_complete b/.clang_complete
index 1818679..4c4a86f 100644
--- a/.clang_complete
+++ b/.clang_complete
@@ -9,3 +9,4 @@
 -Ithird_party/benchmark/include
 -Ithird_party/zlib
 -Ithird_party/protobuf/src
+-Ithird_party/abseil-cpp
diff --git a/.gitmodules b/.gitmodules
index 8af0052..d7f23ff 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -27,3 +27,6 @@
 [submodule "third_party/bloaty"]
 	path = third_party/bloaty
 	url = https://github.com/google/bloaty.git
+[submodule "third_party/abseil-cpp"]
+	path = third_party/abseil-cpp
+	url = https://github.com/abseil/abseil-cpp
diff --git a/BUILD b/BUILD
index 8ccc748..99411f9 100644
--- a/BUILD
+++ b/BUILD
@@ -515,6 +515,8 @@
         "src/core/lib/support/atomic_with_std.h",
         "src/core/lib/support/env.h",
         "src/core/lib/support/memory.h",
+        "src/core/lib/support/vector.h",
+        "src/core/lib/support/manual_constructor.h",
         "src/core/lib/support/mpscq.h",
         "src/core/lib/support/murmur_hash.h",
         "src/core/lib/support/spinlock.h",
@@ -528,6 +530,7 @@
     public_hdrs = GPR_PUBLIC_HDRS,
     deps = [
         "gpr_codegen",
+        "@com_google_absl//absl/container:inlined_vector"
     ],
 )
 
@@ -1258,6 +1261,7 @@
         "src/core/ext/transport/chttp2/transport/bin_encoder.h",
         "src/core/ext/transport/chttp2/transport/chttp2_transport.h",
         "src/core/ext/transport/chttp2/transport/frame.h",
+        "src/core/ext/transport/chttp2/transport/flow_control.h",
         "src/core/ext/transport/chttp2/transport/frame_data.h",
         "src/core/ext/transport/chttp2/transport/frame_goaway.h",
         "src/core/ext/transport/chttp2/transport/frame_ping.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 139d1bd..3ac6c9b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -381,7 +381,6 @@
 add_dependencies(buildtests_c arena_test)
 add_dependencies(buildtests_c backoff_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 byte_stream_test)
@@ -460,6 +459,7 @@
 endif()
 add_dependencies(buildtests_c grpc_jwt_verifier_test)
 add_dependencies(buildtests_c grpc_security_connector_test)
+add_dependencies(buildtests_c grpc_ssl_credentials_test)
 if(_gRPC_PLATFORM_LINUX)
 add_dependencies(buildtests_c handshake_client)
 endif()
@@ -544,7 +544,6 @@
 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()
@@ -561,7 +560,6 @@
 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)
@@ -592,7 +590,6 @@
 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)
@@ -637,6 +634,7 @@
 add_dependencies(buildtests_cxx alarm_cpp_test)
 add_dependencies(buildtests_cxx async_end2end_test)
 add_dependencies(buildtests_cxx auth_property_iterator_test)
+add_dependencies(buildtests_cxx bdp_estimator_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_cxx bm_arena)
 endif()
@@ -704,12 +702,16 @@
 add_dependencies(buildtests_cxx grpclb_api_test)
 add_dependencies(buildtests_cxx grpclb_end2end_test)
 add_dependencies(buildtests_cxx grpclb_test)
+add_dependencies(buildtests_cxx h2_ssl_cert_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 inproc_sync_unary_ping_pong_test)
+endif()
+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)
@@ -758,6 +760,8 @@
 add_dependencies(buildtests_cxx stress_test)
 add_dependencies(buildtests_cxx thread_manager_test)
 add_dependencies(buildtests_cxx thread_stress_test)
+add_dependencies(buildtests_cxx transport_pid_controller_test)
+add_dependencies(buildtests_cxx vector_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_cxx writes_per_rpc_test)
 endif()
@@ -850,6 +854,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr
@@ -942,6 +947,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_test_util
@@ -1240,6 +1246,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc
@@ -1550,6 +1557,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_cronet
@@ -1616,7 +1624,7 @@
   test/core/end2end/fixtures/http_proxy_fixture.c
   test/core/end2end/fixtures/proxy.c
   test/core/iomgr/endpoint_tests.c
-  test/core/util/debugger_macros.c
+  test/core/util/debugger_macros.cc
   test/core/util/grpc_profiler.c
   test/core/util/memory_counters.c
   test/core/util/mock_endpoint.c
@@ -1832,6 +1840,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_test_util
@@ -1880,7 +1889,7 @@
   test/core/end2end/fixtures/http_proxy_fixture.c
   test/core/end2end/fixtures/proxy.c
   test/core/iomgr/endpoint_tests.c
-  test/core/util/debugger_macros.c
+  test/core/util/debugger_macros.cc
   test/core/util/grpc_profiler.c
   test/core/util/memory_counters.c
   test/core/util/mock_endpoint.c
@@ -2096,6 +2105,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_test_util_unsecure
@@ -2394,6 +2404,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_unsecure
@@ -2484,6 +2495,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(reconnect_server
@@ -2526,6 +2538,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(test_tcp_server
@@ -2607,6 +2620,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -2809,6 +2823,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -3103,6 +3118,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -3304,6 +3320,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -3369,6 +3386,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -3430,6 +3448,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -3488,6 +3507,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -3566,6 +3586,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -3706,6 +3727,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -3848,6 +3870,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -4040,6 +4063,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4099,6 +4123,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4159,6 +4184,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -4237,6 +4263,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4292,6 +4319,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4362,6 +4390,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4413,6 +4442,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4482,6 +4512,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4533,6 +4564,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4621,6 +4653,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -4668,6 +4701,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_csharp_ext
@@ -4763,6 +4797,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(ares
@@ -4801,6 +4836,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(bad_client_test
@@ -4842,6 +4878,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(bad_ssl_test_server
@@ -4943,6 +4980,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(end2end_tests
@@ -5044,6 +5082,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(end2end_nosec_tests
@@ -5075,6 +5114,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(alarm_test
@@ -5104,6 +5144,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(algorithm_test
@@ -5133,6 +5174,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(alloc_test
@@ -5160,6 +5202,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(alpn_test
@@ -5189,6 +5232,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(arena_test
@@ -5216,6 +5260,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(backoff_test
@@ -5245,6 +5290,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(bad_server_response_test
@@ -5259,35 +5305,6 @@
 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 ${CARES_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
-  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
 )
@@ -5304,6 +5321,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(bin_decoder_test
@@ -5331,6 +5349,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(bin_encoder_test
@@ -5358,6 +5377,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(byte_stream_test
@@ -5387,6 +5407,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(census_context_test
@@ -5416,6 +5437,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(census_intrusive_hash_map_test
@@ -5445,6 +5467,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(census_resource_test
@@ -5474,6 +5497,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(census_trace_context_test
@@ -5503,6 +5527,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(channel_create_test
@@ -5531,6 +5556,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(check_epollexclusive
@@ -5566,6 +5592,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(chttp2_hpack_encoder_test
@@ -5595,6 +5622,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(chttp2_stream_map_test
@@ -5624,6 +5652,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(chttp2_varint_test
@@ -5653,6 +5682,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(combiner_test
@@ -5682,6 +5712,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(compression_test
@@ -5711,6 +5742,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(concurrent_connectivity_test
@@ -5740,6 +5772,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(connection_refused_test
@@ -5769,6 +5802,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(dns_resolver_connectivity_test
@@ -5798,6 +5832,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(dns_resolver_test
@@ -5828,6 +5863,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(dualstack_socket_test
@@ -5858,6 +5894,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(endpoint_pair_test
@@ -5887,6 +5924,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(error_test
@@ -5917,6 +5955,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(ev_epollsig_linux_test
@@ -5947,6 +5986,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(fake_resolver_test
@@ -5978,6 +6018,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(fake_transport_security_test
@@ -6008,6 +6049,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(fd_conservation_posix_test
@@ -6039,6 +6081,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(fd_posix_test
@@ -6069,6 +6112,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(fling_client
@@ -6098,6 +6142,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(fling_server
@@ -6128,6 +6173,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(fling_stream_test
@@ -6159,6 +6205,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(fling_test
@@ -6188,6 +6235,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gen_hpack_tables
@@ -6222,6 +6270,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gen_legal_metadata_characters
@@ -6254,6 +6303,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gen_percent_encoding_tables
@@ -6288,6 +6338,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(goaway_server_test
@@ -6318,6 +6369,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_avl_test
@@ -6345,6 +6397,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_cmdline_test
@@ -6372,6 +6425,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_cpu_test
@@ -6399,6 +6453,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_env_test
@@ -6426,6 +6481,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_histogram_test
@@ -6453,6 +6509,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_host_port_test
@@ -6480,6 +6537,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_log_test
@@ -6507,6 +6565,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_mpscq_test
@@ -6534,6 +6593,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_spinlock_test
@@ -6561,6 +6621,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_stack_lockfree_test
@@ -6588,6 +6649,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_string_test
@@ -6615,6 +6677,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_sync_test
@@ -6642,6 +6705,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_thd_test
@@ -6669,6 +6733,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_time_test
@@ -6696,6 +6761,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_tls_test
@@ -6723,6 +6789,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(gpr_useful_test
@@ -6750,6 +6817,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_auth_context_test
@@ -6779,6 +6847,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_b64_test
@@ -6808,6 +6877,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_byte_buffer_reader_test
@@ -6837,6 +6907,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_channel_args_test
@@ -6866,6 +6937,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_channel_stack_builder_test
@@ -6895,6 +6967,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_channel_stack_test
@@ -6924,6 +6997,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_completion_queue_test
@@ -6953,6 +7027,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_completion_queue_threading_test
@@ -6981,6 +7056,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_create_jwt
@@ -7017,6 +7093,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_credentials_test
@@ -7046,6 +7123,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_fetch_oauth2
@@ -7075,6 +7153,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_invalid_channel_args_test
@@ -7105,6 +7184,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_json_token_test
@@ -7135,6 +7215,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_jwt_verifier_test
@@ -7163,6 +7244,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_print_google_default_creds_token
@@ -7198,6 +7280,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_security_connector_test
@@ -7209,6 +7292,36 @@
 )
 
 endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
+add_executable(grpc_ssl_credentials_test
+  test/core/security/ssl_credentials_test.c
+)
+
+
+target_include_directories(grpc_ssl_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 ${CARES_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
+)
+
+target_link_libraries(grpc_ssl_credentials_test
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif (gRPC_BUILD_TESTS)
 
 add_executable(grpc_verify_jwt
   test/core/security/verify_jwt.c
@@ -7226,6 +7339,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(grpc_verify_jwt
@@ -7262,6 +7376,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(handshake_client
@@ -7294,6 +7409,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(handshake_server
@@ -7325,6 +7441,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(hpack_parser_test
@@ -7354,6 +7471,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(hpack_table_test
@@ -7383,6 +7501,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(http_parser_test
@@ -7412,6 +7531,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(httpcli_format_request_test
@@ -7442,6 +7562,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(httpcli_test
@@ -7473,6 +7594,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(httpscli_test
@@ -7503,6 +7625,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(init_test
@@ -7532,6 +7655,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(invalid_call_argument_test
@@ -7561,6 +7685,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(json_rewrite
@@ -7588,6 +7713,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(json_rewrite_test
@@ -7617,6 +7743,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(json_stream_error_test
@@ -7646,6 +7773,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(json_test
@@ -7675,6 +7803,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(lame_client_test
@@ -7704,6 +7833,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(lb_policies_test
@@ -7733,6 +7863,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(load_file_test
@@ -7762,6 +7893,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(memory_profile_client
@@ -7791,6 +7923,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(memory_profile_server
@@ -7821,6 +7954,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(memory_profile_test
@@ -7851,6 +7985,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(message_compress_test
@@ -7880,6 +8015,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(minimal_stack_is_minimal_test
@@ -7909,6 +8045,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(mlog_test
@@ -7938,6 +8075,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(multiple_server_queues_test
@@ -7967,6 +8105,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(murmur_hash_test
@@ -7994,6 +8133,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(no_server_test
@@ -8023,6 +8163,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(num_external_connectivity_watchers_test
@@ -8052,6 +8193,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(parse_address_test
@@ -8081,6 +8223,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(percent_encoding_test
@@ -8111,6 +8254,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(pollset_set_test
@@ -8142,6 +8286,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(resolve_address_posix_test
@@ -8172,6 +8317,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(resolve_address_test
@@ -8201,6 +8347,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(resource_quota_test
@@ -8230,6 +8377,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(secure_channel_create_test
@@ -8259,6 +8407,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(secure_endpoint_test
@@ -8288,6 +8437,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(sequential_connectivity_test
@@ -8317,6 +8467,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(server_chttp2_test
@@ -8346,6 +8497,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(server_test
@@ -8375,6 +8527,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(slice_buffer_test
@@ -8404,6 +8557,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(slice_hash_table_test
@@ -8433,6 +8587,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(slice_string_helpers_test
@@ -8462,6 +8617,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(slice_test
@@ -8491,6 +8647,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(sockaddr_resolver_test
@@ -8520,6 +8677,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(sockaddr_utils_test
@@ -8550,6 +8708,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(socket_utils_test
@@ -8582,6 +8741,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(ssl_transport_security_test
@@ -8611,6 +8771,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(status_conversion_test
@@ -8640,6 +8801,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(stream_compression_test
@@ -8669,6 +8831,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(stream_owned_slice_test
@@ -8699,6 +8862,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(tcp_client_posix_test
@@ -8729,6 +8893,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(tcp_client_uv_test
@@ -8759,6 +8924,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(tcp_posix_test
@@ -8790,6 +8956,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(tcp_server_posix_test
@@ -8820,6 +8987,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(tcp_server_uv_test
@@ -8849,6 +9017,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(time_averaged_stats_test
@@ -8878,6 +9047,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(timeout_encoding_test
@@ -8907,6 +9077,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(timer_heap_test
@@ -8936,6 +9107,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(timer_list_test
@@ -8965,6 +9137,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(transport_connectivity_state_test
@@ -8994,6 +9167,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(transport_metadata_test
@@ -9006,35 +9180,6 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
-
-add_executable(transport_pid_controller_test
-  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 ${CARES_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
-  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
-  gpr
-)
-
-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
@@ -9053,6 +9198,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(transport_security_test
@@ -9084,6 +9230,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(udp_server_test
@@ -9114,6 +9261,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(uri_parser_test
@@ -9144,6 +9292,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(wakeup_fd_cv_test
@@ -9176,6 +9325,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9216,6 +9366,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9256,6 +9407,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9277,6 +9429,47 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+
+add_executable(bdp_estimator_test
+  test/core/transport/bdp_estimator_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+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 ${CARES_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bdp_estimator_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util
+  grpc++
+  grpc_test_util
+  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(bm_arena
@@ -9297,6 +9490,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9341,6 +9535,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9385,6 +9580,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9429,6 +9625,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9473,6 +9670,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9517,6 +9715,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9561,6 +9760,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9605,6 +9805,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9649,6 +9850,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9693,6 +9895,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9737,6 +9940,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9782,6 +9986,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9826,6 +10031,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9870,6 +10076,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9913,6 +10120,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9950,6 +10158,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -9987,6 +10196,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10029,6 +10239,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10070,6 +10281,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10110,6 +10322,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10185,6 +10398,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10259,6 +10473,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10296,6 +10511,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10333,6 +10549,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10372,6 +10589,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10411,6 +10629,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10447,6 +10666,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10486,6 +10706,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10533,6 +10754,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10569,6 +10791,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10609,6 +10832,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10656,6 +10880,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10693,6 +10918,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -10730,6 +10956,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -10766,6 +10993,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -10802,6 +11030,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -10838,6 +11067,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -10874,6 +11104,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -10910,6 +11141,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -10946,6 +11178,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE ${_gRPC_PROTO_GENS_DIR}
 )
 
@@ -10999,6 +11232,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11049,6 +11283,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11094,6 +11329,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11141,6 +11377,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11163,6 +11400,46 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(h2_ssl_cert_test
+  test/core/end2end/h2_ssl_cert_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+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 ${CARES_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(h2_ssl_cert_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  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/googletest/src/gtest-all.cc
@@ -11181,6 +11458,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11221,6 +11499,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11262,6 +11541,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11285,6 +11565,52 @@
 if (gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
+add_executable(inproc_sync_unary_ping_pong_test
+  test/cpp/qps/inproc_sync_unary_ping_pong_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(inproc_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 ${CARES_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(inproc_sync_unary_ping_pong_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  qps
+  grpc++_core_stats
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  grpc++_test_config
+  ${_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_client
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
@@ -11302,6 +11628,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11346,6 +11673,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11392,6 +11720,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11433,6 +11762,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11475,6 +11805,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11521,6 +11852,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11559,6 +11891,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11599,6 +11932,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11634,6 +11968,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11676,6 +12011,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11713,6 +12049,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11756,6 +12093,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11800,6 +12138,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11844,6 +12183,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11908,6 +12248,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -11970,6 +12311,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12013,6 +12355,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12054,6 +12397,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12098,6 +12442,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12152,6 +12497,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12192,6 +12538,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12232,6 +12579,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12273,6 +12621,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12327,6 +12676,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12367,6 +12717,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12407,6 +12758,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12446,6 +12798,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12486,6 +12839,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12558,6 +12912,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12599,6 +12954,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12637,6 +12993,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12658,6 +13015,87 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+
+add_executable(transport_pid_controller_test
+  test/core/transport/pid_controller_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+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 ${CARES_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(transport_pid_controller_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util
+  grpc++
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
+add_executable(vector_test
+  test/core/support/vector_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(vector_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 ${CARES_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(vector_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  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(writes_per_rpc_test
@@ -12678,6 +13116,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -12717,6 +13156,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(public_headers_must_be_c89
@@ -12744,6 +13184,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(badreq_bad_client_test
@@ -12775,6 +13216,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(connection_prefix_bad_client_test
@@ -12806,6 +13248,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(head_of_line_blocking_bad_client_test
@@ -12837,6 +13280,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(headers_bad_client_test
@@ -12868,6 +13312,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(initial_settings_frame_bad_client_test
@@ -12883,37 +13328,6 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
-add_executable(large_metadata_bad_client_test
-  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 ${CARES_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
-)
-
-target_link_libraries(large_metadata_bad_client_test
-  ${_gRPC_SSL_LIBRARIES}
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  bad_client_test
-  grpc_test_util_unsecure
-  grpc_unsecure
-  gpr_test_util
-  gpr
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
 add_executable(server_registered_method_bad_client_test
   test/core/bad_client/tests/server_registered_method.c
 )
@@ -12930,6 +13344,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(server_registered_method_bad_client_test
@@ -12961,6 +13376,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(simple_request_bad_client_test
@@ -12992,6 +13408,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(unknown_frame_bad_client_test
@@ -13023,6 +13440,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(window_overflow_bad_client_test
@@ -13055,6 +13473,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(bad_ssl_cert_server
@@ -13087,6 +13506,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(bad_ssl_cert_test
@@ -13117,6 +13537,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_census_test
@@ -13147,6 +13568,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_compress_test
@@ -13177,6 +13599,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_fakesec_test
@@ -13208,6 +13631,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_fd_test
@@ -13239,6 +13663,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_full_test
@@ -13270,6 +13695,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_full+pipe_test
@@ -13301,6 +13727,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_full+trace_test
@@ -13331,6 +13758,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_full+workarounds_test
@@ -13361,6 +13789,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_http_proxy_test
@@ -13391,6 +13820,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_load_reporting_test
@@ -13421,6 +13851,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_oauth2_test
@@ -13451,6 +13882,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_proxy_test
@@ -13481,6 +13913,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_sockpair_test
@@ -13511,6 +13944,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_sockpair+trace_test
@@ -13541,6 +13975,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_sockpair_1byte_test
@@ -13571,6 +14006,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_ssl_test
@@ -13585,36 +14021,6 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
-add_executable(h2_ssl_cert_test
-  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 ${CARES_INCLUDE_DIR}
-  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
-  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
-  gpr_test_util
-  gpr
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
-
 add_executable(h2_ssl_proxy_test
   test/core/end2end/fixtures/h2_ssl_proxy.c
 )
@@ -13631,6 +14037,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_ssl_proxy_test
@@ -13662,6 +14069,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_uds_test
@@ -13693,6 +14101,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(inproc_test
@@ -13723,6 +14132,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_census_nosec_test
@@ -13753,6 +14163,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_compress_nosec_test
@@ -13784,6 +14195,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_fd_nosec_test
@@ -13815,6 +14227,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_full_nosec_test
@@ -13846,6 +14259,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_full+pipe_nosec_test
@@ -13877,6 +14291,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_full+trace_nosec_test
@@ -13907,6 +14322,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_full+workarounds_nosec_test
@@ -13937,6 +14353,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_http_proxy_nosec_test
@@ -13967,6 +14384,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_load_reporting_nosec_test
@@ -13997,6 +14415,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_proxy_nosec_test
@@ -14027,6 +14446,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_sockpair_nosec_test
@@ -14057,6 +14477,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_sockpair+trace_nosec_test
@@ -14087,6 +14508,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_sockpair_1byte_nosec_test
@@ -14118,6 +14540,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(h2_uds_nosec_test
@@ -14149,6 +14572,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(inproc_nosec_test
@@ -14182,6 +14606,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -14225,6 +14650,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -14268,6 +14694,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -14311,6 +14738,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
   PRIVATE third_party/googletest/googletest/include
   PRIVATE third_party/googletest/googletest
   PRIVATE third_party/googletest/googlemock/include
@@ -14352,6 +14780,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(api_fuzzer_one_entry
@@ -14382,6 +14811,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(client_fuzzer_one_entry
@@ -14412,6 +14842,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(hpack_parser_fuzzer_test_one_entry
@@ -14442,6 +14873,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(http_request_fuzzer_test_one_entry
@@ -14472,6 +14904,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(http_response_fuzzer_test_one_entry
@@ -14502,6 +14935,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(json_fuzzer_test_one_entry
@@ -14532,6 +14966,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(nanopb_fuzzer_response_test_one_entry
@@ -14562,6 +14997,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(nanopb_fuzzer_serverlist_test_one_entry
@@ -14592,6 +15028,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(percent_decode_fuzzer_one_entry
@@ -14622,6 +15059,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(percent_encode_fuzzer_one_entry
@@ -14652,6 +15090,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(server_fuzzer_one_entry
@@ -14682,6 +15121,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(ssl_server_fuzzer_one_entry
@@ -14712,6 +15152,7 @@
   PRIVATE ${CARES_INCLUDE_DIR}
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp
 )
 
 target_link_libraries(uri_fuzzer_test_one_entry
diff --git a/INSTALL.md b/INSTALL.md
index ea613f3..15725bd 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -94,6 +94,7 @@
 ### Building using CMake (RECOMMENDED)
 
 Builds gRPC C and C++ with boringssl.
+- Install Visual Studio 2015 or 2017 (Visual C++ compiler will be used).
 - Install [CMake](https://cmake.org/download/).
 - Install [Active State Perl](https://www.activestate.com/activeperl/) (`choco install activeperl`)
 - Install [Ninja](https://ninja-build.org/) (`choco install ninja`)
@@ -101,7 +102,9 @@
 - Install [yasm](http://yasm.tortall.net/) and add it to `PATH` (`choco install yasm`)
 - Run these commands in the repo root directory
 
-Using Ninja (faster build, supports boringssl's assembly optimizations)
+#### cmake: Using Ninja (faster build, supports boringssl's assembly optimizations).
+Please note that when using Ninja, you'll still need Visual C++ (part of Visual Studio)
+installed to be able to compile the C/C++ sources.
 ```
 > md .build
 > cd .build
@@ -110,7 +113,12 @@
 > cmake --build .
 ```
 
-Using Visual Studio 2015 (can only build with OPENSSL_NO_ASM)
+#### cmake: Using Visual Studio 2015 (can only build with OPENSSL_NO_ASM).
+When using the "Visual Studio" generator,
+cmake will generate a solution (`grpc.sln`) that contains a VS project for 
+every target defined in `CMakeLists.txt` (+ few extra convenience projects
+added automatically by cmake). After opening the solution with Visual Studio 
+you will be able to browse and build the code as usual.
 ```
 > md .build
 > cd .build
diff --git a/Makefile b/Makefile
index 382956d..325c912 100644
--- a/Makefile
+++ b/Makefile
@@ -327,7 +327,7 @@
 ifeq ($(SYSTEM),Darwin)
 CXXFLAGS += -stdlib=libc++
 endif
-CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
+CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1 -Ithird_party/abseil-cpp
 LDFLAGS += -g
 
 CPPFLAGS += $(CPPFLAGS_$(CONFIG))
@@ -952,7 +952,6 @@
 arena_test: $(BINDIR)/$(CONFIG)/arena_test
 backoff_test: $(BINDIR)/$(CONFIG)/backoff_test
 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
 byte_stream_test: $(BINDIR)/$(CONFIG)/byte_stream_test
@@ -1020,6 +1019,7 @@
 grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test
 grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token
 grpc_security_connector_test: $(BINDIR)/$(CONFIG)/grpc_security_connector_test
+grpc_ssl_credentials_test: $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test
 grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt
 handshake_client: $(BINDIR)/$(CONFIG)/handshake_client
 handshake_server: $(BINDIR)/$(CONFIG)/handshake_server
@@ -1092,7 +1092,6 @@
 timer_list_test: $(BINDIR)/$(CONFIG)/timer_list_test
 transport_connectivity_state_test: $(BINDIR)/$(CONFIG)/transport_connectivity_state_test
 transport_metadata_test: $(BINDIR)/$(CONFIG)/transport_metadata_test
-transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test
 transport_security_test: $(BINDIR)/$(CONFIG)/transport_security_test
 udp_server_test: $(BINDIR)/$(CONFIG)/udp_server_test
 uri_fuzzer_test: $(BINDIR)/$(CONFIG)/uri_fuzzer_test
@@ -1101,6 +1100,7 @@
 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
+bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
 bm_arena: $(BINDIR)/$(CONFIG)/bm_arena
 bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create
 bm_chttp2_hpack: $(BINDIR)/$(CONFIG)/bm_chttp2_hpack
@@ -1145,9 +1145,11 @@
 grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test
 grpclb_end2end_test: $(BINDIR)/$(CONFIG)/grpclb_end2end_test
 grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test
+h2_ssl_cert_test: $(BINDIR)/$(CONFIG)/h2_ssl_cert_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
+inproc_sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test
 interop_client: $(BINDIR)/$(CONFIG)/interop_client
 interop_server: $(BINDIR)/$(CONFIG)/interop_server
 interop_test: $(BINDIR)/$(CONFIG)/interop_test
@@ -1179,6 +1181,8 @@
 stress_test: $(BINDIR)/$(CONFIG)/stress_test
 thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test
 thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
+transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test
+vector_test: $(BINDIR)/$(CONFIG)/vector_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
@@ -1224,7 +1228,6 @@
 head_of_line_blocking_bad_client_test: $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test
 headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test
 initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
-large_metadata_bad_client_test: $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test
 server_registered_method_bad_client_test: $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test
 simple_request_bad_client_test: $(BINDIR)/$(CONFIG)/simple_request_bad_client_test
 unknown_frame_bad_client_test: $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test
@@ -1247,7 +1250,6 @@
 h2_sockpair+trace_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test
 h2_sockpair_1byte_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test
 h2_ssl_test: $(BINDIR)/$(CONFIG)/h2_ssl_test
-h2_ssl_cert_test: $(BINDIR)/$(CONFIG)/h2_ssl_cert_test
 h2_ssl_proxy_test: $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test
 h2_uds_test: $(BINDIR)/$(CONFIG)/h2_uds_test
 inproc_test: $(BINDIR)/$(CONFIG)/inproc_test
@@ -1352,7 +1354,6 @@
   $(BINDIR)/$(CONFIG)/arena_test \
   $(BINDIR)/$(CONFIG)/backoff_test \
   $(BINDIR)/$(CONFIG)/bad_server_response_test \
-  $(BINDIR)/$(CONFIG)/bdp_estimator_test \
   $(BINDIR)/$(CONFIG)/bin_decoder_test \
   $(BINDIR)/$(CONFIG)/bin_encoder_test \
   $(BINDIR)/$(CONFIG)/byte_stream_test \
@@ -1413,6 +1414,7 @@
   $(BINDIR)/$(CONFIG)/grpc_json_token_test \
   $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test \
   $(BINDIR)/$(CONFIG)/grpc_security_connector_test \
+  $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test \
   $(BINDIR)/$(CONFIG)/handshake_client \
   $(BINDIR)/$(CONFIG)/handshake_server \
   $(BINDIR)/$(CONFIG)/hpack_parser_test \
@@ -1473,7 +1475,6 @@
   $(BINDIR)/$(CONFIG)/timer_list_test \
   $(BINDIR)/$(CONFIG)/transport_connectivity_state_test \
   $(BINDIR)/$(CONFIG)/transport_metadata_test \
-  $(BINDIR)/$(CONFIG)/transport_pid_controller_test \
   $(BINDIR)/$(CONFIG)/transport_security_test \
   $(BINDIR)/$(CONFIG)/udp_server_test \
   $(BINDIR)/$(CONFIG)/uri_parser_test \
@@ -1484,7 +1485,6 @@
   $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \
   $(BINDIR)/$(CONFIG)/headers_bad_client_test \
   $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \
-  $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test \
   $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \
   $(BINDIR)/$(CONFIG)/simple_request_bad_client_test \
   $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \
@@ -1507,7 +1507,6 @@
   $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test \
   $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test \
   $(BINDIR)/$(CONFIG)/h2_ssl_test \
-  $(BINDIR)/$(CONFIG)/h2_ssl_cert_test \
   $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test \
   $(BINDIR)/$(CONFIG)/h2_uds_test \
   $(BINDIR)/$(CONFIG)/inproc_test \
@@ -1546,6 +1545,7 @@
   $(BINDIR)/$(CONFIG)/alarm_cpp_test \
   $(BINDIR)/$(CONFIG)/async_end2end_test \
   $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
+  $(BINDIR)/$(CONFIG)/bdp_estimator_test \
   $(BINDIR)/$(CONFIG)/bm_arena \
   $(BINDIR)/$(CONFIG)/bm_call_create \
   $(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
@@ -1583,9 +1583,11 @@
   $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/grpclb_end2end_test \
   $(BINDIR)/$(CONFIG)/grpclb_test \
+  $(BINDIR)/$(CONFIG)/h2_ssl_cert_test \
   $(BINDIR)/$(CONFIG)/health_service_end2end_test \
   $(BINDIR)/$(CONFIG)/http2_client \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
+  $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test \
   $(BINDIR)/$(CONFIG)/interop_client \
   $(BINDIR)/$(CONFIG)/interop_server \
   $(BINDIR)/$(CONFIG)/interop_test \
@@ -1617,6 +1619,8 @@
   $(BINDIR)/$(CONFIG)/stress_test \
   $(BINDIR)/$(CONFIG)/thread_manager_test \
   $(BINDIR)/$(CONFIG)/thread_stress_test \
+  $(BINDIR)/$(CONFIG)/transport_pid_controller_test \
+  $(BINDIR)/$(CONFIG)/vector_test \
   $(BINDIR)/$(CONFIG)/writes_per_rpc_test \
   $(BINDIR)/$(CONFIG)/boringssl_aes_test \
   $(BINDIR)/$(CONFIG)/boringssl_asn1_test \
@@ -1666,6 +1670,7 @@
   $(BINDIR)/$(CONFIG)/alarm_cpp_test \
   $(BINDIR)/$(CONFIG)/async_end2end_test \
   $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
+  $(BINDIR)/$(CONFIG)/bdp_estimator_test \
   $(BINDIR)/$(CONFIG)/bm_arena \
   $(BINDIR)/$(CONFIG)/bm_call_create \
   $(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
@@ -1703,9 +1708,11 @@
   $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/grpclb_end2end_test \
   $(BINDIR)/$(CONFIG)/grpclb_test \
+  $(BINDIR)/$(CONFIG)/h2_ssl_cert_test \
   $(BINDIR)/$(CONFIG)/health_service_end2end_test \
   $(BINDIR)/$(CONFIG)/http2_client \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
+  $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test \
   $(BINDIR)/$(CONFIG)/interop_client \
   $(BINDIR)/$(CONFIG)/interop_server \
   $(BINDIR)/$(CONFIG)/interop_test \
@@ -1737,6 +1744,8 @@
   $(BINDIR)/$(CONFIG)/stress_test \
   $(BINDIR)/$(CONFIG)/thread_manager_test \
   $(BINDIR)/$(CONFIG)/thread_stress_test \
+  $(BINDIR)/$(CONFIG)/transport_pid_controller_test \
+  $(BINDIR)/$(CONFIG)/vector_test \
   $(BINDIR)/$(CONFIG)/writes_per_rpc_test \
   $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure \
   $(BINDIR)/$(CONFIG)/resolver_component_test \
@@ -1765,8 +1774,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/backoff_test || ( echo test backoff_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"
@@ -1881,6 +1888,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test || ( echo test grpc_jwt_verifier_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_security_connector_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_security_connector_test || ( echo test grpc_security_connector_test failed ; exit 1 )
+	$(E) "[RUN]     Testing grpc_ssl_credentials_test"
+	$(Q) $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test || ( echo test grpc_ssl_credentials_test failed ; exit 1 )
 	$(E) "[RUN]     Testing handshake_client"
 	$(Q) $(BINDIR)/$(CONFIG)/handshake_client || ( echo test handshake_client failed ; exit 1 )
 	$(E) "[RUN]     Testing handshake_server"
@@ -1991,8 +2000,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/transport_connectivity_state_test || ( echo test transport_connectivity_state_test failed ; exit 1 )
 	$(E) "[RUN]     Testing transport_metadata_test"
 	$(Q) $(BINDIR)/$(CONFIG)/transport_metadata_test || ( echo test transport_metadata_test failed ; exit 1 )
-	$(E) "[RUN]     Testing transport_pid_controller_test"
-	$(Q) $(BINDIR)/$(CONFIG)/transport_pid_controller_test || ( echo test transport_pid_controller_test failed ; exit 1 )
 	$(E) "[RUN]     Testing transport_security_test"
 	$(Q) $(BINDIR)/$(CONFIG)/transport_security_test || ( echo test transport_security_test failed ; exit 1 )
 	$(E) "[RUN]     Testing udp_server_test"
@@ -2013,8 +2020,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing initial_settings_frame_bad_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test || ( echo test initial_settings_frame_bad_client_test failed ; exit 1 )
-	$(E) "[RUN]     Testing large_metadata_bad_client_test"
-	$(Q) $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test || ( echo test large_metadata_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_registered_method_bad_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test || ( echo test server_registered_method_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing simple_request_bad_client_test"
@@ -2039,6 +2044,8 @@
 	$(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 bdp_estimator_test"
+	$(Q) $(BINDIR)/$(CONFIG)/bdp_estimator_test || ( echo test bdp_estimator_test failed ; exit 1 )
 	$(E) "[RUN]     Testing bm_arena"
 	$(Q) $(BINDIR)/$(CONFIG)/bm_arena || ( echo test bm_arena failed ; exit 1 )
 	$(E) "[RUN]     Testing bm_call_create"
@@ -2109,8 +2116,12 @@
 	$(Q) $(BINDIR)/$(CONFIG)/grpclb_end2end_test || ( echo test grpclb_end2end_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpclb_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpclb_test || ( echo test grpclb_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_ssl_cert_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl_cert_test || ( echo test h2_ssl_cert_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 inproc_sync_unary_ping_pong_test"
+	$(Q) $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test || ( echo test inproc_sync_unary_ping_pong_test failed ; exit 1 )
 	$(E) "[RUN]     Testing interop_test"
 	$(Q) $(BINDIR)/$(CONFIG)/interop_test || ( echo test interop_test failed ; exit 1 )
 	$(E) "[RUN]     Testing memory_test"
@@ -2151,6 +2162,10 @@
 	$(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 transport_pid_controller_test"
+	$(Q) $(BINDIR)/$(CONFIG)/transport_pid_controller_test || ( echo test transport_pid_controller_test failed ; exit 1 )
+	$(E) "[RUN]     Testing vector_test"
+	$(Q) $(BINDIR)/$(CONFIG)/vector_test || ( echo test vector_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 )
 	$(E) "[RUN]     Testing resolver_component_tests_runner_invoker_unsecure"
@@ -3606,7 +3621,7 @@
     test/core/end2end/fixtures/http_proxy_fixture.c \
     test/core/end2end/fixtures/proxy.c \
     test/core/iomgr/endpoint_tests.c \
-    test/core/util/debugger_macros.c \
+    test/core/util/debugger_macros.cc \
     test/core/util/grpc_profiler.c \
     test/core/util/memory_counters.c \
     test/core/util/mock_endpoint.c \
@@ -3861,7 +3876,7 @@
     test/core/end2end/fixtures/http_proxy_fixture.c \
     test/core/end2end/fixtures/proxy.c \
     test/core/iomgr/endpoint_tests.c \
-    test/core/util/debugger_macros.c \
+    test/core/util/debugger_macros.cc \
     test/core/util/grpc_profiler.c \
     test/core/util/memory_counters.c \
     test/core/util/mock_endpoint.c \
@@ -8420,7 +8435,7 @@
 
 LIBARES_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBARES_SRC))))
 
-$(LIBARES_OBJS): CPPFLAGS += -Ithird_party/cares -Ithird_party/cares/cares $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux) $(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) -fvisibility=hidden -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(if $(subst MINGW32,,$(SYSTEM)),-DHAVE_CONFIG_H,)
+$(LIBARES_OBJS): CPPFLAGS += -Ithird_party/cares -Ithird_party/cares/cares -fvisibility=hidden -D_GNU_SOURCE $(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) $(if $(subst FreeBSD,,$(SYSTEM)),,-Ithird_party/cares/config_freebsd) $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux) $(if $(subst OpenBSD,,$(SYSTEM)),,-Ithird_party/cares/config_openbsd) -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(if $(subst MINGW32,,$(SYSTEM)),-DHAVE_CONFIG_H,)
 $(LIBARES_OBJS): CFLAGS += -Wno-sign-conversion $(if $(subst Darwin,,$(SYSTEM)),,-Wno-shorten-64-to-32) $(if $(subst MINGW32,,$(SYSTEM)),-Wno-invalid-source-encoding,)
 
 $(LIBDIR)/$(CONFIG)/libares.a: $(ZLIB_DEP)  $(LIBARES_OBJS) 
@@ -8961,38 +8976,6 @@
 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 \
 
@@ -11140,6 +11123,38 @@
 endif
 
 
+GRPC_SSL_CREDENTIALS_TEST_SRC = \
+    test/core/security/ssl_credentials_test.c \
+
+GRPC_SSL_CREDENTIALS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_SSL_CREDENTIALS_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test: $(GRPC_SSL_CREDENTIALS_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) $(GRPC_SSL_CREDENTIALS_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)/grpc_ssl_credentials_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/security/ssl_credentials_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_grpc_ssl_credentials_test: $(GRPC_SSL_CREDENTIALS_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GRPC_SSL_CREDENTIALS_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 GRPC_VERIFY_JWT_SRC = \
     test/core/security/verify_jwt.c \
 
@@ -13447,38 +13462,6 @@
 endif
 
 
-TRANSPORT_PID_CONTROLLER_TEST_SRC = \
-    test/core/transport/pid_controller_test.c \
-
-TRANSPORT_PID_CONTROLLER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_PID_CONTROLLER_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/transport_pid_controller_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/transport_pid_controller_test: $(TRANSPORT_PID_CONTROLLER_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) $(TRANSPORT_PID_CONTROLLER_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)/transport_pid_controller_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/transport/pid_controller_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_transport_pid_controller_test: $(TRANSPORT_PID_CONTROLLER_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(TRANSPORT_PID_CONTROLLER_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 TRANSPORT_SECURITY_TEST_SRC = \
     test/core/tsi/transport_security_test.c \
 
@@ -13768,6 +13751,49 @@
 endif
 
 
+BDP_ESTIMATOR_TEST_SRC = \
+    test/core/transport/bdp_estimator_test.cc \
+
+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
+
+
+
+
+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)/bdp_estimator_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bdp_estimator_test: $(PROTOBUF_DEP) $(BDP_ESTIMATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.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) $(BDP_ESTIMATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.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)/bdp_estimator_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/transport/bdp_estimator_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(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
+
+
 BM_ARENA_SRC = \
     test/cpp/microbenchmarks/bm_arena.cc \
 
@@ -15653,6 +15679,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
 
 
+H2_SSL_CERT_TEST_SRC = \
+    test/core/end2end/h2_ssl_cert_test.cc \
+
+H2_SSL_CERT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_CERT_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_ssl_cert_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)/h2_ssl_cert_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_ssl_cert_test: $(PROTOBUF_DEP) $(H2_SSL_CERT_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) $(H2_SSL_CERT_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)/h2_ssl_cert_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/h2_ssl_cert_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_h2_ssl_cert_test: $(H2_SSL_CERT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(H2_SSL_CERT_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 HEALTH_SERVICE_END2END_TEST_SRC = \
     test/cpp/end2end/health_service_end2end_test.cc \
 
@@ -15770,6 +15839,49 @@
 endif
 
 
+INPROC_SYNC_UNARY_PING_PONG_TEST_SRC = \
+    test/cpp/qps/inproc_sync_unary_ping_pong_test.cc \
+
+INPROC_SYNC_UNARY_PING_PONG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(INPROC_SYNC_UNARY_PING_PONG_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_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)/inproc_sync_unary_ping_pong_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test: $(PROTOBUF_DEP) $(INPROC_SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(INPROC_SYNC_UNARY_PING_PONG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/inproc_sync_unary_ping_pong_test.o:  $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.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 $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+
+deps_inproc_sync_unary_ping_pong_test: $(INPROC_SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(INPROC_SYNC_UNARY_PING_PONG_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -17143,6 +17255,92 @@
 endif
 
 
+TRANSPORT_PID_CONTROLLER_TEST_SRC = \
+    test/core/transport/pid_controller_test.cc \
+
+TRANSPORT_PID_CONTROLLER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_PID_CONTROLLER_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/transport_pid_controller_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)/transport_pid_controller_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/transport_pid_controller_test: $(PROTOBUF_DEP) $(TRANSPORT_PID_CONTROLLER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.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) $(TRANSPORT_PID_CONTROLLER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.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)/transport_pid_controller_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/transport/pid_controller_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_transport_pid_controller_test: $(TRANSPORT_PID_CONTROLLER_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(TRANSPORT_PID_CONTROLLER_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
+VECTOR_TEST_SRC = \
+    test/core/support/vector_test.cc \
+
+VECTOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(VECTOR_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/vector_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)/vector_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/vector_test: $(PROTOBUF_DEP) $(VECTOR_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) $(VECTOR_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)/vector_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/support/vector_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_vector_test: $(VECTOR_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(VECTOR_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 WRITES_PER_RPC_TEST_SRC = \
     test/cpp/performance/writes_per_rpc_test.cc \
 
@@ -18424,26 +18622,6 @@
 endif
 
 
-LARGE_METADATA_BAD_CLIENT_TEST_SRC = \
-    test/core/bad_client/tests/large_metadata.c \
-
-LARGE_METADATA_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LARGE_METADATA_BAD_CLIENT_TEST_SRC))))
-
-
-$(BINDIR)/$(CONFIG)/large_metadata_bad_client_test: $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/large_metadata_bad_client_test
-
-$(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/large_metadata.o:  $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_large_metadata_bad_client_test: $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_DEPS),true)
--include $(LARGE_METADATA_BAD_CLIENT_TEST_OBJS:.o=.dep)
-endif
-
-
 SERVER_REGISTERED_METHOD_BAD_CLIENT_TEST_SRC = \
     test/core/bad_client/tests/server_registered_method.c \
 
@@ -19100,38 +19278,6 @@
 endif
 
 
-H2_SSL_CERT_TEST_SRC = \
-    test/core/end2end/fixtures/h2_ssl_cert.c \
-
-H2_SSL_CERT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_CERT_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/h2_ssl_cert_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/h2_ssl_cert_test: $(H2_SSL_CERT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.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) $(LD) $(LDFLAGS) $(H2_SSL_CERT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(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)/h2_ssl_cert_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl_cert.o:  $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_h2_ssl_cert_test: $(H2_SSL_CERT_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(H2_SSL_CERT_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 H2_SSL_PROXY_TEST_SRC = \
     test/core/end2end/fixtures/h2_ssl_proxy.c \
 
diff --git a/WORKSPACE b/WORKSPACE
index bfb3a8c..907cef1 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -92,3 +92,8 @@
     path = "third_party/cares",
     build_file = "third_party/cares/cares.BUILD",
 )
+
+local_repository(
+    name = "com_google_absl",
+    path = "third_party/abseil-cpp",
+)
diff --git a/binding.gyp b/binding.gyp
index 91919c3..e004b0f 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -63,6 +63,7 @@
         '-Wno-long-long',
         '-Wno-unused-parameter',
         '-DOSATOMIC_USE_INLINED=1',
+        '-Ithird_party/abseil-cpp',
     ],
     'ldflags': [
         '-g',
@@ -184,6 +185,7 @@
               '-Wno-long-long',
               '-Wno-unused-parameter',
               '-DOSATOMIC_USE_INLINED=1',
+              '-Ithird_party/abseil-cpp',
           ],
           'OTHER_CPLUSPLUSFLAGS': [
               '-g',
@@ -193,6 +195,7 @@
               '-Wno-long-long',
               '-Wno-unused-parameter',
               '-DOSATOMIC_USE_INLINED=1',
+              '-Ithird_party/abseil-cpp',
             '-stdlib=libc++',
             '-std=c++11',
             '-Wno-error=deprecated-declarations'
diff --git a/build.yaml b/build.yaml
index d23716a..592cbb9 100644
--- a/build.yaml
+++ b/build.yaml
@@ -143,6 +143,7 @@
   - src/core/lib/support/atomic_with_atm.h
   - src/core/lib/support/atomic_with_std.h
   - src/core/lib/support/env.h
+  - src/core/lib/support/manual_constructor.h
   - src/core/lib/support/memory.h
   - src/core/lib/support/mpscq.h
   - src/core/lib/support/murmur_hash.h
@@ -426,6 +427,7 @@
   - 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/support/vector.h
   - src/core/lib/surface/alarm_internal.h
   - src/core/lib/surface/api_trace.h
   - src/core/lib/surface/call.h
@@ -741,7 +743,7 @@
   - test/core/end2end/fixtures/http_proxy_fixture.c
   - test/core/end2end/fixtures/proxy.c
   - test/core/iomgr/endpoint_tests.c
-  - test/core/util/debugger_macros.c
+  - test/core/util/debugger_macros.cc
   - test/core/util/grpc_profiler.c
   - test/core/util/memory_counters.c
   - test/core/util/mock_endpoint.c
@@ -776,6 +778,7 @@
   - src/core/ext/transport/chttp2/transport/bin_decoder.h
   - src/core/ext/transport/chttp2/transport/bin_encoder.h
   - src/core/ext/transport/chttp2/transport/chttp2_transport.h
+  - src/core/ext/transport/chttp2/transport/flow_control.h
   - src/core/ext/transport/chttp2/transport/frame.h
   - src/core/ext/transport/chttp2/transport/frame_data.h
   - src/core/ext/transport/chttp2/transport/frame_goaway.h
@@ -1735,6 +1738,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: alloc_test
   build: test
   language: c
@@ -1743,6 +1747,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: alpn_test
   build: test
   language: c
@@ -1775,6 +1780,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: backoff_test
   build: test
   language: c
@@ -1785,6 +1791,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: bad_server_response_test
   build: test
   language: c
@@ -1798,16 +1805,6 @@
   - 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
@@ -1816,6 +1813,7 @@
   deps:
   - grpc_test_util
   - grpc
+  uses_polling: false
 - name: bin_encoder_test
   build: test
   language: c
@@ -1824,6 +1822,7 @@
   deps:
   - grpc_test_util
   - grpc
+  uses_polling: false
 - name: byte_stream_test
   build: test
   language: c
@@ -1834,6 +1833,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: census_context_test
   build: test
   language: c
@@ -1844,6 +1844,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: census_intrusive_hash_map_test
   build: test
   language: c
@@ -1854,6 +1855,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: census_resource_test
   build: test
   language: c
@@ -1864,6 +1866,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: census_trace_context_test
   build: test
   language: c
@@ -1874,6 +1877,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: channel_create_test
   build: test
   language: c
@@ -1902,6 +1906,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: chttp2_stream_map_test
   build: test
   language: c
@@ -1912,6 +1917,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: chttp2_varint_test
   build: test
   language: c
@@ -1922,6 +1928,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: client_fuzzer
   build: fuzzer
   language: c
@@ -1957,6 +1964,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: concurrent_connectivity_test
   cpu_cost: 2.0
   build: test
@@ -2044,6 +2052,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: ev_epollsig_linux_test
   cpu_cost: 3
   build: test
@@ -2176,6 +2185,7 @@
   deps:
   - gpr
   - grpc
+  uses_polling: false
 - name: gen_legal_metadata_characters
   build: tool
   language: c
@@ -2188,6 +2198,7 @@
   src:
   - tools/codegen/core/gen_percent_encoding_tables.c
   deps: []
+  uses_polling: false
 - name: goaway_server_test
   cpu_cost: 0.1
   build: test
@@ -2213,6 +2224,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_cmdline_test
   build: test
   language: c
@@ -2221,6 +2233,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_cpu_test
   cpu_cost: 30
   build: test
@@ -2230,6 +2243,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_env_test
   build: test
   language: c
@@ -2238,6 +2252,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_histogram_test
   build: test
   language: c
@@ -2246,6 +2261,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_host_port_test
   build: test
   language: c
@@ -2254,6 +2270,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_log_test
   build: test
   language: c
@@ -2262,6 +2279,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_mpscq_test
   cpu_cost: 30
   build: test
@@ -2271,6 +2289,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_spinlock_test
   cpu_cost: 3
   build: test
@@ -2280,6 +2299,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_stack_lockfree_test
   cpu_cost: 7
   build: test
@@ -2289,6 +2309,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_string_test
   build: test
   language: c
@@ -2297,6 +2318,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_sync_test
   cpu_cost: 10
   build: test
@@ -2306,6 +2328,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_thd_test
   cpu_cost: 10
   build: test
@@ -2315,6 +2338,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_time_test
   build: test
   language: c
@@ -2323,6 +2347,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_tls_test
   build: test
   language: c
@@ -2331,6 +2356,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: gpr_useful_test
   build: test
   language: c
@@ -2339,6 +2365,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: grpc_auth_context_test
   build: test
   language: c
@@ -2349,6 +2376,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: grpc_b64_test
   build: test
   language: c
@@ -2359,6 +2387,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: grpc_byte_buffer_reader_test
   build: test
   language: c
@@ -2369,6 +2398,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: grpc_channel_args_test
   build: test
   language: c
@@ -2379,6 +2409,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: grpc_channel_stack_builder_test
   build: test
   language: c
@@ -2399,6 +2430,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: grpc_completion_queue_test
   build: test
   language: c
@@ -2430,6 +2462,7 @@
   - grpc
   - gpr
   secure: true
+  uses_polling: false
 - name: grpc_credentials_test
   build: test
   language: c
@@ -2461,6 +2494,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: grpc_json_token_test
   build: test
   language: c
@@ -2475,6 +2509,7 @@
   - linux
   - posix
   - mac
+  uses_polling: false
 - name: grpc_jwt_verifier_test
   build: test
   language: c
@@ -2485,6 +2520,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: grpc_print_google_default_creds_token
   build: tool
   language: c
@@ -2493,6 +2529,7 @@
   deps:
   - grpc
   - gpr
+  uses_polling: false
 - name: grpc_security_connector_test
   build: test
   language: c
@@ -2503,6 +2540,16 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: grpc_ssl_credentials_test
+  build: test
+  language: c
+  src:
+  - test/core/security/ssl_credentials_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: grpc_verify_jwt
   build: tool
   language: c
@@ -2511,6 +2558,7 @@
   deps:
   - grpc
   - gpr
+  uses_polling: false
 - name: handshake_client
   build: test
   language: c
@@ -2565,6 +2613,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: hpack_table_test
   build: test
   language: c
@@ -2575,6 +2624,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: http_parser_test
   build: test
   language: c
@@ -2585,6 +2635,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: http_request_fuzzer_test
   build: fuzzer
   language: c
@@ -2659,6 +2710,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: invalid_call_argument_test
   cpu_cost: 0.1
   build: test
@@ -2692,6 +2744,7 @@
   deps:
   - grpc
   - gpr
+  uses_polling: false
 - name: json_rewrite_test
   build: test
   language: c
@@ -2702,6 +2755,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: json_stream_error_test
   build: test
   language: c
@@ -2712,6 +2766,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: json_test
   build: test
   language: c
@@ -2722,6 +2777,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: lame_client_test
   build: test
   language: c
@@ -2744,6 +2800,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: load_file_test
   build: test
   language: c
@@ -2754,6 +2811,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: low_level_ping_pong_benchmark
   build: benchmark
   language: c
@@ -2779,6 +2837,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: memory_profile_server
   build: test
   run: false
@@ -2815,6 +2874,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: minimal_stack_is_minimal_test
   build: test
   language: c
@@ -2825,6 +2885,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: mlog_test
   flaky: true
   build: test
@@ -2836,6 +2897,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: multiple_server_queues_test
   build: test
   language: c
@@ -2854,6 +2916,7 @@
   deps:
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: nanopb_fuzzer_response_test
   build: fuzzer
   language: c
@@ -2913,6 +2976,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: percent_decode_fuzzer
   build: fuzzer
   language: c
@@ -2949,6 +3013,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: pollset_set_test
   build: test
   language: c
@@ -3078,6 +3143,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: slice_hash_table_test
   build: test
   language: c
@@ -3088,6 +3154,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: slice_string_helpers_test
   build: test
   language: c
@@ -3098,6 +3165,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: slice_test
   build: test
   language: c
@@ -3108,6 +3176,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: sockaddr_resolver_test
   build: test
   language: c
@@ -3182,6 +3251,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: stream_compression_test
   build: test
   language: c
@@ -3192,6 +3262,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: stream_owned_slice_test
   build: test
   language: c
@@ -3202,6 +3273,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: tcp_client_posix_test
   cpu_cost: 0.5
   build: test
@@ -3287,6 +3359,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: timeout_encoding_test
   build: test
   language: c
@@ -3297,6 +3370,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: timer_heap_test
   build: test
   language: c
@@ -3309,6 +3383,7 @@
   - gpr
   exclude_iomgrs:
   - uv
+  uses_polling: false
 - name: timer_list_test
   build: test
   language: c
@@ -3321,6 +3396,7 @@
   - gpr
   exclude_iomgrs:
   - uv
+  uses_polling: false
 - name: transport_connectivity_state_test
   build: test
   language: c
@@ -3341,16 +3417,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: transport_pid_controller_test
-  build: test
-  language: c
-  src:
-  - test/core/transport/pid_controller_test.c
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
 - name: transport_security_test
   build: test
   language: c
@@ -3459,6 +3525,20 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
+- name: bdp_estimator_test
+  build: test
+  language: c++
+  src:
+  - test/core/transport/bdp_estimator_test.cc
+  deps:
+  - grpc++_test_util
+  - grpc++
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  uses_polling: false
 - name: bm_arena
   build: test
   language: c++
@@ -3475,11 +3555,13 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
   - linux
   - posix
+  uses_polling: false
 - name: bm_call_create
   build: test
   language: c++
@@ -3496,11 +3578,13 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
   - linux
   - posix
+  uses_polling: false
 - name: bm_chttp2_hpack
   build: test
   language: c++
@@ -3517,11 +3601,13 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
   - linux
   - posix
+  uses_polling: false
 - name: bm_chttp2_transport
   build: test
   language: c++
@@ -3538,6 +3624,7 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
@@ -3559,6 +3646,7 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
@@ -3580,6 +3668,7 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
@@ -3601,6 +3690,7 @@
   - gpr
   args:
   - --benchmark_min_time=4
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
@@ -3622,11 +3712,13 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
   - linux
   - posix
+  uses_polling: false
 - name: bm_fullstack_streaming_ping_pong
   build: test
   language: c++
@@ -3645,6 +3737,7 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   excluded_poll_engines:
   - poll
@@ -3672,6 +3765,7 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   excluded_poll_engines:
   - poll
@@ -3698,6 +3792,7 @@
   - grpc++_test_config
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   excluded_poll_engines:
   - poll
@@ -3725,6 +3820,7 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   excluded_poll_engines:
   - poll
@@ -3750,11 +3846,13 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
   - linux
   - posix
+  uses_polling: false
 - name: bm_pollset
   build: test
   language: c++
@@ -3771,6 +3869,7 @@
   - gpr
   args:
   - --benchmark_min_time=0
+  benchmark: true
   defaults: benchmark
   platforms:
   - mac
@@ -3786,6 +3885,7 @@
   - grpc++
   - grpc
   - gpr
+  uses_polling: false
 - name: channel_filter_test
   gtest: true
   build: test
@@ -3796,6 +3896,7 @@
   - grpc++
   - grpc
   - gpr
+  uses_polling: false
 - name: cli_call_test
   gtest: true
   build: test
@@ -3857,6 +3958,7 @@
   excluded_poll_engines:
   - poll
   - poll-cv
+  - epollex
 - name: codegen_test_full
   gtest: true
   build: test
@@ -3875,6 +3977,7 @@
   - gpr
   filegroups:
   - grpc++_codegen_base
+  uses_polling: false
 - name: codegen_test_minimal
   gtest: true
   build: test
@@ -3893,6 +3996,7 @@
   filegroups:
   - grpc++_codegen_base
   - grpc++_codegen_base_src
+  uses_polling: false
 - name: credentials_test
   gtest: true
   build: test
@@ -3915,6 +4019,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: cxx_slice_test
   gtest: true
   build: test
@@ -3927,6 +4032,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: cxx_string_ref_test
   gtest: true
   build: test
@@ -3936,6 +4042,7 @@
   deps:
   - grpc++
   - grpc
+  uses_polling: false
 - name: cxx_time_test
   gtest: true
   build: test
@@ -3948,6 +4055,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: end2end_test
   gtest: true
   cpu_cost: 0.5
@@ -4011,6 +4119,7 @@
   - gpr
   args:
   - --generated_file_path=gens/src/proto/grpc/testing/
+  uses_polling: false
 - name: grpc_cli
   build: test
   run: false
@@ -4158,6 +4267,23 @@
   excluded_poll_engines:
   - poll
   - poll-cv
+  - epollex
+- name: h2_ssl_cert_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - test/core/end2end/end2end_tests.h
+  src:
+  - test/core/end2end/h2_ssl_cert_test.cc
+  deps:
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  uses:
+  - grpc++_test
 - name: health_service_end2end_test
   gtest: true
   build: test
@@ -4200,6 +4326,25 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: inproc_sync_unary_ping_pong_test
+  build: test
+  language: c++
+  src:
+  - test/cpp/qps/inproc_sync_unary_ping_pong_test.cc
+  deps:
+  - qps
+  - grpc++_core_stats
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  - grpc++_test_config
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: interop_client
   build: test
   run: false
@@ -4287,6 +4432,7 @@
   - gpr
   uses:
   - grpc++_test
+  uses_polling: false
 - name: metrics_client
   build: test
   run: false
@@ -4351,6 +4497,7 @@
   filegroups:
   - grpc++_codegen_base
   - grpc++_codegen_proto
+  uses_polling: false
 - name: qps_interarrival_test
   build: test
   run: false
@@ -4370,6 +4517,7 @@
   - mac
   - linux
   - posix
+  uses_polling: false
 - name: qps_json_driver
   build: test
   run: false
@@ -4606,6 +4754,10 @@
   - grpc
   - gpr_test_util
   - gpr
+  exclude_configs:
+  - tsan
+  timeout_seconds: 1200
+  uses_polling: false
 - name: status_test
   build: test
   language: c++
@@ -4617,6 +4769,7 @@
   - grpc
   - gpr_test_util
   - gpr
+  uses_polling: false
 - name: streaming_throughput_test
   gtest: true
   build: test
@@ -4686,6 +4839,32 @@
   - gpr_test_util
   - gpr
   timeout_seconds: 1200
+- name: transport_pid_controller_test
+  build: test
+  language: c++
+  src:
+  - test/core/transport/pid_controller_test.cc
+  deps:
+  - grpc++_test_util
+  - grpc++
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: vector_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - test/core/support/vector_test.cc
+  deps:
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  uses:
+  - grpc++_test
 - name: writes_per_rpc_test
   gtest: true
   cpu_cost: 0.5
@@ -4853,10 +5032,11 @@
   ares:
     CFLAGS: -Wno-sign-conversion $(if $(subst Darwin,,$(SYSTEM)),,-Wno-shorten-64-to-32)
       $(if $(subst MINGW32,,$(SYSTEM)),-Wno-invalid-source-encoding,)
-    CPPFLAGS: -Ithird_party/cares -Ithird_party/cares/cares $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux)
-      $(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) -fvisibility=hidden
-      -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(if $(subst
-      MINGW32,,$(SYSTEM)),-DHAVE_CONFIG_H,)
+    CPPFLAGS: -Ithird_party/cares -Ithird_party/cares/cares -fvisibility=hidden -D_GNU_SOURCE
+      $(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) $(if $(subst
+      FreeBSD,,$(SYSTEM)),,-Ithird_party/cares/config_freebsd) $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux)
+      $(if $(subst OpenBSD,,$(SYSTEM)),,-Ithird_party/cares/config_openbsd) -DWIN32_LEAN_AND_MEAN
+      -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(if $(subst MINGW32,,$(SYSTEM)),-DHAVE_CONFIG_H,)
   benchmark:
     CPPFLAGS: -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
   boringssl:
@@ -4866,6 +5046,7 @@
       -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
   global:
     CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
+      -Ithird_party/abseil-cpp
     LDFLAGS: -g
   zlib:
     CFLAGS: -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-implicit-function-declaration
diff --git a/doc/core/moving-to-c++.md b/doc/core/moving-to-c++.md
new file mode 100644
index 0000000..4c745b3
--- /dev/null
+++ b/doc/core/moving-to-c++.md
@@ -0,0 +1,60 @@
+# Moving gRPC core to C++
+
+October 2017
+
+ctiller, markdroth, vjpai
+
+## Background and Goal
+
+gRPC core was originally written in C89 for several reasons
+(possibility of kernel integration, ease of wrapping, compiler
+support, etc). Over time, this was changed to C99 as all relevant
+compilers in active use came to support C99 effectively.
+[Now, gRPC core is C++](https://github.com/grpc/proposal/blob/master/L6-allow-c%2B%2B-in-grpc-core.md)
+(although the code is still idiomatically C code) with C linkage for
+public functions. Throughout all of these transitions, the public
+header files are committed to remain in C89.
+
+The goal now is to make the gRPC core implementation true idiomatic
+C++ compatible with
+[Google's C++ style guide](https://google.github.io/styleguide/cppguide.html).
+
+## Constraints
+
+- No use of standard library
+  - Standard library makes wrapping difficult/impossible and also reduces platform portability
+  - This takes precedence over using C++ style guide
+- But lambdas are ok
+- As are third-party libraries that meet our build requirements (such as many parts of abseil)
+- There will be some C++ features that don't work
+  - `new` and `delete`
+  - pure virtual functions are not allowed because the message that prints out "Pure Virtual Function called" is part of the standard library
+    - Make a `#define GRPC_ABSTRACT {GPR_ASSERT(false);}` instead of `= 0;`
+- The sanity for making sure that we don't depend on libstdc++ is that at least some tests should explicitly not include it
+  - Most tests can migrate to use gtest
+    - There are tremendous # of code paths that can now be exposed to unit tests because of the use of gtest and C++
+  - But at least some tests should not use gtest
+
+
+## Roadmap
+
+- What should be the phases of getting code converted to idiomatic C++
+  - Opportunistically do leaf code that other parts don't depend on
+  - Spend a little time deciding how to do non-leaf stuff that isn't central or polymorphic (e.g., timer, call combiner)
+  - For big central or polymorphic interfaces, actually do an API review (for things like transport, filter API, endpoint, closure, exec_ctx, ...) .
+    - Core internal changes don't need a gRFC, but core surface changes do
+    - But an API review should include at least a PR with the header change and tests to use it before it gets used more broadly
+  - iomgr polling for POSIX is a gray area whether it's a leaf or central
+- What is the schedule?
+  - In Q4 2017, if some stuff happens opportunistically, great; otherwise ¯\\\_(ツ)\_/¯
+  - More updates as team time becomes available and committed to this project
+
+## Implications for C++ API and wrapped languages
+
+- For C++ structs, switch to `using` when possible (e.g., Slice,
+ByteBuffer, ...)
+- The C++ API implementation might directly start using
+`grpc_transport_stream_op_batch` rather than the core surface `grpc_op`.
+- Can we get wrapped languages to a point where we can statically link C++? This will take a year in probability but that would allow the use of `std::`
+  - Are there other environments that don't support std library, like maybe Android NDK?
+    - Probably, that might push things out to 18 months
diff --git a/doc/environment_variables.md b/doc/environment_variables.md
index f775de1..c5fb266 100644
--- a/doc/environment_variables.md
+++ b/doc/environment_variables.md
@@ -49,6 +49,7 @@
   - connectivity_state - traces connectivity state changes to channels
   - channel_stack_builder - traces information about channel stacks being built
   - executor - traces grpc's internal thread pool ('the executor')
+  - glb - traces the grpclb load balancer
   - http - traces state in the http2 transport engine
   - http2_stream_state - traces all http2 stream state mutations.
   - http1 - traces HTTP/1.x operations performed by gRPC
@@ -56,11 +57,12 @@
   - flowctl - traces http2 flow control
   - op_failure - traces error information when failure is pushed onto a
     completion queue
-  - round_robin - traces the round_robin load balancing policy
   - pick_first - traces the pick first load balancing policy
   - plugin_credentials - traces plugin credentials
+  - pollable_refcount - traces reference counting of 'pollable' objects (only 
+    in DEBUG)
   - resource_quota - trace resource quota objects internals
-  - glb - traces the grpclb load balancer
+  - round_robin - traces the round_robin load balancing policy
   - queue_pluck
   - queue_timeout
   - server_channel - lightweight trace of significant server channel events
diff --git a/doc/load-balancing.md b/doc/load-balancing.md
index 88ff354..8ff9407 100644
--- a/doc/load-balancing.md
+++ b/doc/load-balancing.md
@@ -129,10 +129,9 @@
         by the resolver. It asks the balancer for the server addresses to
         use for the server name originally requested by the client (i.e.,
         the same one originally passed to the name resolver).
-        - Note: The `grpclb` policy currently ignores any non-balancer
-          addresses returned by the resolver. However, in the future, it
-          may be changed to use these addresses as a fallback in case no
-          balancers can be contacted.
+        - Note: In the `grpclb` policy, the non-balancer addresses returned
+          by the resolver are used as a fallback in case no balancers can be
+          contacted when the LB policy is started.
      2. The gRPC servers to which the load balancer is directing the client
         may report load to the load balancers, if that information is needed
         by the load balancer's configuration.
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index f19b672..a9b451e 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -191,6 +191,7 @@
                       'src/core/lib/support/atomic_with_atm.h',
                       'src/core/lib/support/atomic_with_std.h',
                       'src/core/lib/support/env.h',
+                      'src/core/lib/support/manual_constructor.h',
                       'src/core/lib/support/memory.h',
                       'src/core/lib/support/mpscq.h',
                       'src/core/lib/support/murmur_hash.h',
@@ -248,6 +249,7 @@
                       'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                       'src/core/ext/transport/chttp2/transport/bin_encoder.h',
                       'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
+                      'src/core/ext/transport/chttp2/transport/flow_control.h',
                       'src/core/ext/transport/chttp2/transport/frame.h',
                       'src/core/ext/transport/chttp2/transport/frame_data.h',
                       'src/core/ext/transport/chttp2/transport/frame_goaway.h',
@@ -408,6 +410,7 @@
                       '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/support/vector.h',
                       'src/core/lib/surface/alarm_internal.h',
                       'src/core/lib/surface/api_trace.h',
                       'src/core/lib/surface/call.h',
@@ -736,6 +739,7 @@
                               'src/core/lib/support/atomic_with_atm.h',
                               'src/core/lib/support/atomic_with_std.h',
                               'src/core/lib/support/env.h',
+                              'src/core/lib/support/manual_constructor.h',
                               'src/core/lib/support/memory.h',
                               'src/core/lib/support/mpscq.h',
                               'src/core/lib/support/murmur_hash.h',
@@ -748,6 +752,7 @@
                               'src/core/ext/transport/chttp2/transport/bin_decoder.h',
                               'src/core/ext/transport/chttp2/transport/bin_encoder.h',
                               'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
+                              'src/core/ext/transport/chttp2/transport/flow_control.h',
                               'src/core/ext/transport/chttp2/transport/frame.h',
                               'src/core/ext/transport/chttp2/transport/frame_data.h',
                               'src/core/ext/transport/chttp2/transport/frame_goaway.h',
@@ -908,6 +913,7 @@
                               '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/support/vector.h',
                               'src/core/lib/surface/alarm_internal.h',
                               'src/core/lib/surface/api_trace.h',
                               'src/core/lib/surface/call.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index ce23e6f..4567058 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -89,6 +89,7 @@
   s.files += %w( src/core/lib/support/atomic_with_atm.h )
   s.files += %w( src/core/lib/support/atomic_with_std.h )
   s.files += %w( src/core/lib/support/env.h )
+  s.files += %w( src/core/lib/support/manual_constructor.h )
   s.files += %w( src/core/lib/support/memory.h )
   s.files += %w( src/core/lib/support/mpscq.h )
   s.files += %w( src/core/lib/support/murmur_hash.h )
@@ -180,6 +181,7 @@
   s.files += %w( src/core/ext/transport/chttp2/transport/bin_decoder.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.h )
+  s.files += %w( src/core/ext/transport/chttp2/transport/flow_control.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/frame.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.h )
   s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.h )
@@ -340,6 +342,7 @@
   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/support/vector.h )
   s.files += %w( src/core/lib/surface/alarm_internal.h )
   s.files += %w( src/core/lib/surface/api_trace.h )
   s.files += %w( src/core/lib/surface/call.h )
@@ -1123,8 +1126,10 @@
   s.files += %w( third_party/cares/cares/config-win32.h )
   s.files += %w( third_party/cares/cares/setup_once.h )
   s.files += %w( third_party/cares/ares_build.h )
-  s.files += %w( third_party/cares/config_linux/ares_config.h )
   s.files += %w( third_party/cares/config_darwin/ares_config.h )
+  s.files += %w( third_party/cares/config_freebsd/ares_config.h )
+  s.files += %w( third_party/cares/config_linux/ares_config.h )
+  s.files += %w( third_party/cares/config_openbsd/ares_config.h )
   s.files += %w( third_party/cares/cares/ares__close_sockets.c )
   s.files += %w( third_party/cares/cares/ares__get_hostent.c )
   s.files += %w( third_party/cares/cares/ares__read_line.c )
diff --git a/grpc.gyp b/grpc.gyp
index 53e3885..487d529 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -57,6 +57,7 @@
       '-Wno-long-long',
       '-Wno-unused-parameter',
       '-DOSATOMIC_USE_INLINED=1',
+      '-Ithird_party/abseil-cpp',
     ],
     'ldflags': [
       '-g',
@@ -134,6 +135,7 @@
             '-Wno-long-long',
             '-Wno-unused-parameter',
             '-DOSATOMIC_USE_INLINED=1',
+            '-Ithird_party/abseil-cpp',
           ],
           'OTHER_CPLUSPLUSFLAGS': [
             '-g',
@@ -143,6 +145,7 @@
             '-Wno-long-long',
             '-Wno-unused-parameter',
             '-DOSATOMIC_USE_INLINED=1',
+            '-Ithird_party/abseil-cpp',
             '-stdlib=libc++',
             '-std=c++11',
             '-Wno-error=deprecated-declarations'
@@ -515,7 +518,7 @@
         'test/core/end2end/fixtures/http_proxy_fixture.c',
         'test/core/end2end/fixtures/proxy.c',
         'test/core/iomgr/endpoint_tests.c',
-        'test/core/util/debugger_macros.c',
+        'test/core/util/debugger_macros.cc',
         'test/core/util/grpc_profiler.c',
         'test/core/util/memory_counters.c',
         'test/core/util/mock_endpoint.c',
@@ -722,7 +725,7 @@
         'test/core/end2end/fixtures/http_proxy_fixture.c',
         'test/core/end2end/fixtures/proxy.c',
         'test/core/iomgr/endpoint_tests.c',
-        'test/core/util/debugger_macros.c',
+        'test/core/util/debugger_macros.cc',
         'test/core/util/grpc_profiler.c',
         'test/core/util/memory_counters.c',
         'test/core/util/mock_endpoint.c',
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index d9988e5..06f107f 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -163,7 +163,7 @@
 
   /// Clears flag indicating that this is the last message in a stream,
   /// disabling coalescing.
-  inline WriteOptions& clear_last_messsage() {
+  inline WriteOptions& clear_last_message() {
     last_message_ = false;
     return *this;
   }
@@ -318,7 +318,11 @@
 Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) {
   write_options_ = options;
   bool own_buf;
-  Status result = SerializationTraits<M>::Serialize(
+  // TODO(vjpai): Remove the void below when possible
+  // The void in the template parameter below should not be needed
+  // (since it should be implicit) but is needed due to an observed
+  // difference in behavior between clang and gcc for certain internal users
+  Status result = SerializationTraits<M, void>::Serialize(
       message, send_buf_.bbuf_ptr(), &own_buf);
   if (!own_buf) {
     send_buf_.Duplicate();
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index bbf45b3..a948abe 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -140,7 +140,7 @@
   /// please use IPv6 any, i.e., [::]:<port>, which also accepts IPv4
   /// connections.  Valid values include dns:///localhost:1234, /
   /// 192.168.1.1:31416, dns:///[::1]:27182, etc.).
-  /// \params creds The credentials associated with the server.
+  /// \param creds The credentials associated with the server.
   /// \param selected_port[out] If not `nullptr`, gets populated with the port
   /// number bound to the \a grpc::Server for the corresponding endpoint after
   /// it is successfully bound, 0 otherwise.
diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h
index baea4bc..fb4bfc3 100644
--- a/include/grpc/impl/codegen/port_platform.h
+++ b/include/grpc/impl/codegen/port_platform.h
@@ -241,6 +241,29 @@
 #else /* _LP64 */
 #define GPR_ARCH_32 1
 #endif /* _LP64 */
+#elif defined(__OpenBSD__)
+#define GPR_PLATFORM_STRING "openbsd"
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE
+#endif
+#define GPR_OPENBSD 1
+#define GPR_CPU_POSIX 1
+#define GPR_GCC_ATOMIC 1
+#define GPR_GCC_TLS 1
+#define GPR_POSIX_LOG 1
+#define GPR_POSIX_ENV 1
+#define GPR_POSIX_TMPFILE 1
+#define GPR_POSIX_STRING 1
+#define GPR_POSIX_SUBPROCESS 1
+#define GPR_POSIX_SYNC 1
+#define GPR_POSIX_TIME 1
+#define GPR_GETPID_IN_UNISTD_H 1
+#define GPR_SUPPORT_CHANNELS_FROM_FD 1
+#ifdef _LP64
+#define GPR_ARCH_64 1
+#else /* _LP64 */
+#define GPR_ARCH_32 1
+#endif /* _LP64 */
 #elif defined(__native_client__)
 #define GPR_PLATFORM_STRING "nacl"
 #ifndef _BSD_SOURCE
diff --git a/include/grpc/support/sync.h b/include/grpc/support/sync.h
index fe8a59a..ddb8580 100644
--- a/include/grpc/support/sync.h
+++ b/include/grpc/support/sync.h
@@ -274,7 +274,23 @@
 #endif /* 0 */
 
 #ifdef __cplusplus
-}
+}  // extern "C"
+
+namespace grpc_core {
+
+class mu_guard {
+ public:
+  mu_guard(gpr_mu *mu) : mu_(mu) { gpr_mu_lock(mu); }
+  ~mu_guard() { gpr_mu_unlock(mu_); }
+
+  mu_guard(const mu_guard &) = delete;
+  mu_guard &operator=(const mu_guard &) = delete;
+
+ private:
+  gpr_mu *const mu_;
+};
+
+}  // namespace grpc_core
 #endif
 
 #endif /* GRPC_SUPPORT_SYNC_H */
diff --git a/package.xml b/package.xml
index df01421..d08b803 100644
--- a/package.xml
+++ b/package.xml
@@ -101,6 +101,7 @@
     <file baseinstalldir="/" name="src/core/lib/support/atomic_with_atm.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/atomic_with_std.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/env.h" role="src" />
+    <file baseinstalldir="/" name="src/core/lib/support/manual_constructor.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/support/memory.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" />
@@ -192,6 +193,7 @@
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_decoder.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/flow_control.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_data.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_goaway.h" role="src" />
@@ -352,6 +354,7 @@
     <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/support/vector.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/alarm_internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/call.h" role="src" />
diff --git a/setup.py b/setup.py
index 90c9316..bf8aea6 100644
--- a/setup.py
+++ b/setup.py
@@ -40,10 +40,14 @@
 CARES_INCLUDE = (
     os.path.join('third_party', 'cares'),
     os.path.join('third_party', 'cares', 'cares'),)
-if 'linux' in sys.platform:
-  CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
 if 'darwin' in sys.platform:
   CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),)
+if 'freebsd' in sys.platform:
+  CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_freebsd'),)
+if 'linux' in sys.platform:
+  CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
+if 'openbsd' in sys.platform:
+  CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_openbsd'),)
 README = os.path.join(PYTHON_STEM, 'README.rst')
 
 # Ensure we're in the proper directory whether or not we're being used by pip.
diff --git a/src/c-ares/gen_build_yaml.py b/src/c-ares/gen_build_yaml.py
index 6f8b748..4600d8d 100755
--- a/src/c-ares/gen_build_yaml.py
+++ b/src/c-ares/gen_build_yaml.py
@@ -29,10 +29,14 @@
     subprocess.call("third_party/cares/cares/configure", shell=True)
 
   def config_platform(x):
-    if 'linux' in sys.platform:
-      return 'src/cares/cares/config_linux/ares_config.h'
     if 'darwin' in sys.platform:
       return 'src/cares/cares/config_darwin/ares_config.h'
+    if 'freebsd' in sys.platform:
+      return 'src/cares/cares/config_freebsd/ares_config.h'
+    if 'linux' in sys.platform:
+      return 'src/cares/cares/config_linux/ares_config.h'
+    if 'openbsd' in sys.platform:
+      return 'src/cares/cares/config_openbsd/ares_config.h'
     if not os.path.isfile('third_party/cares/cares/ares_config.h'):
       gen_ares_build(x)
     return 'third_party/cares/cares/ares_config.h'
@@ -124,8 +128,10 @@
         "third_party/cares/cares/config-win32.h",
         "third_party/cares/cares/setup_once.h",
         "third_party/cares/ares_build.h",
+        "third_party/cares/config_darwin/ares_config.h",
+        "third_party/cares/config_freebsd/ares_config.h",
         "third_party/cares/config_linux/ares_config.h",
-        "third_party/cares/config_darwin/ares_config.h"
+        "third_party/cares/config_openbsd/ares_config.h"
     ],
   }]
 except:
diff --git a/src/core/ext/census/base_resources.h b/src/core/ext/census/base_resources.h
index 4b1b988..d24923b 100644
--- a/src/core/ext/census/base_resources.h
+++ b/src/core/ext/census/base_resources.h
@@ -29,4 +29,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H */
diff --git a/src/core/ext/census/census_interface.h b/src/core/ext/census/census_interface.h
index 12438e3..113c2b1 100644
--- a/src/core/ext/census/census_interface.h
+++ b/src/core/ext/census/census_interface.h
@@ -66,4 +66,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_CENSUS_INTERFACE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_CENSUS_INTERFACE_H */
diff --git a/src/core/ext/census/census_log.h b/src/core/ext/census/census_log.h
index cc9e008..ee336ae 100644
--- a/src/core/ext/census/census_log.h
+++ b/src/core/ext/census/census_log.h
@@ -81,4 +81,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_CENSUS_LOG_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_CENSUS_LOG_H */
diff --git a/src/core/ext/census/hash_table.h b/src/core/ext/census/hash_table.h
index c22ba8d..c3ed94e 100644
--- a/src/core/ext/census/hash_table.h
+++ b/src/core/ext/census/hash_table.h
@@ -121,4 +121,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_HASH_TABLE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_HASH_TABLE_H */
diff --git a/src/core/ext/census/mlog.h b/src/core/ext/census/mlog.h
index 7b4d392..8f74ba2 100644
--- a/src/core/ext/census/mlog.h
+++ b/src/core/ext/census/mlog.h
@@ -85,4 +85,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_MLOG_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_MLOG_H */
diff --git a/src/core/ext/census/resource.h b/src/core/ext/census/resource.h
index 5f7ac2a..56aaaaf 100644
--- a/src/core/ext/census/resource.h
+++ b/src/core/ext/census/resource.h
@@ -53,4 +53,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_RESOURCE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_RESOURCE_H */
diff --git a/src/core/ext/census/trace_context.h b/src/core/ext/census/trace_context.h
index c707c63..2b828ba 100644
--- a/src/core/ext/census/trace_context.h
+++ b/src/core/ext/census/trace_context.h
@@ -61,4 +61,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H */
diff --git a/src/core/ext/census/trace_propagation.h b/src/core/ext/census/trace_propagation.h
index 3394e9e..e05fd23 100644
--- a/src/core/ext/census/trace_propagation.h
+++ b/src/core/ext/census/trace_propagation.h
@@ -53,4 +53,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H */
diff --git a/src/core/ext/census/tracing.h b/src/core/ext/census/tracing.h
index 5fcbb1e..0690de8 100644
--- a/src/core/ext/census/tracing.h
+++ b/src/core/ext/census/tracing.h
@@ -114,4 +114,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_TRACING_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_TRACING_H */
diff --git a/src/core/ext/census/window_stats.h b/src/core/ext/census/window_stats.h
index 3b1d197..2a1d6d0 100644
--- a/src/core/ext/census/window_stats.h
+++ b/src/core/ext/census/window_stats.h
@@ -163,4 +163,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_CENSUS_WINDOW_STATS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_CENSUS_WINDOW_STATS_H */
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 22c2bc8..ea5e076 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -1205,6 +1205,9 @@
                              "Pick cancelled", &error, 1));
 }
 
+static void pick_after_resolver_result_start_locked(grpc_exec_ctx *exec_ctx,
+                                                    grpc_call_element *elem);
+
 static void pick_after_resolver_result_done_locked(grpc_exec_ctx *exec_ctx,
                                                    void *arg,
                                                    grpc_error *error) {
@@ -1228,7 +1231,7 @@
               chand, calld);
     }
     async_pick_done_locked(exec_ctx, elem, GRPC_ERROR_REF(error));
-  } else {
+  } else if (chand->lb_policy != NULL) {
     if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
       gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver returned, doing pick",
               chand, calld);
@@ -1242,6 +1245,30 @@
       async_pick_done_locked(exec_ctx, elem, GRPC_ERROR_NONE);
     }
   }
+  // TODO(roth): It should be impossible for chand->lb_policy to be NULL
+  // here, so the rest of this code should never actually be executed.
+  // However, we have reports of a crash on iOS that triggers this case,
+  // so we are temporarily adding this to restore branches that were
+  // removed in https://github.com/grpc/grpc/pull/12297.  Need to figure
+  // out what is actually causing this to occur and then figure out the
+  // right way to deal with it.
+  else if (chand->resolver != NULL) {
+    // No LB policy, so try again.
+    if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
+      gpr_log(GPR_DEBUG,
+              "chand=%p calld=%p: resolver returned but no LB policy, "
+              "trying again",
+              chand, calld);
+    }
+    pick_after_resolver_result_start_locked(exec_ctx, elem);
+  } else {
+    if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
+      gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver disconnected", chand,
+              calld);
+    }
+    async_pick_done_locked(
+        exec_ctx, elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
+  }
 }
 
 static void pick_after_resolver_result_start_locked(grpc_exec_ctx *exec_ctx,
@@ -1599,8 +1626,8 @@
   return count;
 }
 
-static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
-                                       grpc_error *error) {
+static void on_external_watch_complete_locked(grpc_exec_ctx *exec_ctx,
+                                              void *arg, grpc_error *error) {
   external_connectivity_watcher *w = (external_connectivity_watcher *)arg;
   grpc_closure *follow_up = w->on_complete;
   grpc_polling_entity_del_from_pollset_set(exec_ctx, &w->pollent,
@@ -1619,8 +1646,8 @@
   if (w->state != NULL) {
     external_connectivity_watcher_list_append(w->chand, w);
     GRPC_CLOSURE_RUN(exec_ctx, w->watcher_timer_init, GRPC_ERROR_NONE);
-    GRPC_CLOSURE_INIT(&w->my_closure, on_external_watch_complete, w,
-                      grpc_schedule_on_exec_ctx);
+    GRPC_CLOSURE_INIT(&w->my_closure, on_external_watch_complete_locked, w,
+                      grpc_combiner_scheduler(w->chand->combiner));
     grpc_connectivity_state_notify_on_state_change(
         exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
   } else {
diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h
index b32f378..152fe23 100644
--- a/src/core/ext/filters/client_channel/client_channel.h
+++ b/src/core/ext/filters/client_channel/client_channel.h
@@ -60,4 +60,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H */
diff --git a/src/core/ext/filters/client_channel/client_channel_factory.h b/src/core/ext/filters/client_channel/client_channel_factory.h
index bad8b97..4273c90 100644
--- a/src/core/ext/filters/client_channel/client_channel_factory.h
+++ b/src/core/ext/filters/client_channel/client_channel_factory.h
@@ -82,4 +82,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H */
diff --git a/src/core/ext/filters/client_channel/connector.h b/src/core/ext/filters/client_channel/connector.h
index b91c93e..b71e0aa 100644
--- a/src/core/ext/filters/client_channel/connector.h
+++ b/src/core/ext/filters/client_channel/connector.h
@@ -78,4 +78,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H */
diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.h b/src/core/ext/filters/client_channel/http_connect_handshaker.h
index 5042c61..05a23cd 100644
--- a/src/core/ext/filters/client_channel/http_connect_handshaker.h
+++ b/src/core/ext/filters/client_channel/http_connect_handshaker.h
@@ -39,4 +39,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_CONNECT_HANDSHAKER_H */
diff --git a/src/core/ext/filters/client_channel/http_proxy.h b/src/core/ext/filters/client_channel/http_proxy.h
index 65d5233..bdad03d 100644
--- a/src/core/ext/filters/client_channel/http_proxy.h
+++ b/src/core/ext/filters/client_channel/http_proxy.h
@@ -29,4 +29,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_PROXY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_HTTP_PROXY_H */
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index d4037fd..d6bdc13 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -345,9 +345,6 @@
   /** are we currently updating lb_call? */
   bool updating_lb_call;
 
-  /** are we currently updating lb_channel? */
-  bool updating_lb_channel;
-
   /** are we already watching the LB channel's connectivity? */
   bool watching_lb_channel;
 
@@ -360,9 +357,6 @@
   /** called upon changes to the LB channel's connectivity. */
   grpc_closure lb_channel_on_connectivity_changed;
 
-  /** args from the latest update received while already updating, or NULL */
-  grpc_lb_policy_args *pending_update_args;
-
   /************************************************************/
   /*  client data associated with the LB server communication */
   /************************************************************/
@@ -982,10 +976,6 @@
   }
   grpc_fake_resolver_response_generator_unref(glb_policy->response_generator);
   grpc_subchannel_index_unref();
-  if (glb_policy->pending_update_args != NULL) {
-    grpc_channel_args_destroy(exec_ctx, glb_policy->pending_update_args->args);
-    gpr_free(glb_policy->pending_update_args);
-  }
   gpr_free(glb_policy);
 }
 
@@ -1756,45 +1746,22 @@
   }
   const grpc_lb_addresses *addresses =
       (const grpc_lb_addresses *)arg->value.pointer.p;
-
+  // If a non-empty serverlist hasn't been received from the balancer,
+  // propagate the update to fallback_backend_addresses.
   if (glb_policy->serverlist == NULL) {
-    // If a non-empty serverlist hasn't been received from the balancer,
-    // propagate the update to fallback_backend_addresses.
     fallback_update_locked(exec_ctx, glb_policy, addresses);
-  } else if (glb_policy->updating_lb_channel) {
-    // If we have recieved serverlist from the balancer, we need to defer update
-    // when there is an in-progress one.
-    if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
-      gpr_log(GPR_INFO,
-              "Update already in progress for grpclb %p. Deferring update.",
-              (void *)glb_policy);
-    }
-    if (glb_policy->pending_update_args != NULL) {
-      grpc_channel_args_destroy(exec_ctx,
-                                glb_policy->pending_update_args->args);
-      gpr_free(glb_policy->pending_update_args);
-    }
-    glb_policy->pending_update_args = (grpc_lb_policy_args *)gpr_zalloc(
-        sizeof(*glb_policy->pending_update_args));
-    glb_policy->pending_update_args->client_channel_factory =
-        args->client_channel_factory;
-    glb_policy->pending_update_args->args = grpc_channel_args_copy(args->args);
-    glb_policy->pending_update_args->combiner = args->combiner;
-    return;
   }
-
-  glb_policy->updating_lb_channel = true;
   GPR_ASSERT(glb_policy->lb_channel != NULL);
+  // Propagate updates to the LB channel (pick_first) through the fake
+  // resolver.
   grpc_channel_args *lb_channel_args = build_lb_channel_args(
       exec_ctx, addresses, glb_policy->response_generator, args->args);
-  /* Propagate updates to the LB channel (pick first) through the fake resolver
-   */
   grpc_fake_resolver_response_generator_set_response(
       exec_ctx, glb_policy->response_generator, lb_channel_args);
   grpc_channel_args_destroy(exec_ctx, lb_channel_args);
-
+  // Start watching the LB channel connectivity for connection, if not
+  // already doing so.
   if (!glb_policy->watching_lb_channel) {
-    // Watch the LB channel connectivity for connection.
     glb_policy->lb_channel_connectivity = grpc_channel_check_connectivity_state(
         glb_policy->lb_channel, true /* try to connect */);
     grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(
@@ -1840,24 +1807,15 @@
       break;
     }
     case GRPC_CHANNEL_IDLE:
-      // lb channel inactive (probably shutdown prior to update). Restart lb
-      // call to kick the lb channel into gear.
-      GPR_ASSERT(glb_policy->lb_call == NULL);
+    // lb channel inactive (probably shutdown prior to update). Restart lb
+    // call to kick the lb channel into gear.
     /* fallthrough */
     case GRPC_CHANNEL_READY:
       if (glb_policy->lb_call != NULL) {
-        glb_policy->updating_lb_channel = false;
         glb_policy->updating_lb_call = true;
         grpc_call_cancel(glb_policy->lb_call, NULL);
-        // lb_on_server_status_received will pick up the cancel and reinit
+        // lb_on_server_status_received() will pick up the cancel and reinit
         // lb_call.
-        if (glb_policy->pending_update_args != NULL) {
-          grpc_lb_policy_args *args = glb_policy->pending_update_args;
-          glb_policy->pending_update_args = NULL;
-          glb_update_locked(exec_ctx, &glb_policy->base, args);
-          grpc_channel_args_destroy(exec_ctx, args->args);
-          gpr_free(args);
-        }
       } else if (glb_policy->started_picking && !glb_policy->shutting_down) {
         if (glb_policy->retry_timer_active) {
           grpc_timer_cancel(exec_ctx, &glb_policy->lb_call_retry_timer);
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
index c67df60..15c8a68 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
@@ -34,4 +34,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H */
diff --git a/src/core/ext/filters/client_channel/lb_policy_factory.h b/src/core/ext/filters/client_channel/lb_policy_factory.h
index 69bcba4..8790ffd 100644
--- a/src/core/ext/filters/client_channel/lb_policy_factory.h
+++ b/src/core/ext/filters/client_channel/lb_policy_factory.h
@@ -138,4 +138,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H */
diff --git a/src/core/ext/filters/client_channel/lb_policy_registry.h b/src/core/ext/filters/client_channel/lb_policy_registry.h
index 0867844..55154cb 100644
--- a/src/core/ext/filters/client_channel/lb_policy_registry.h
+++ b/src/core/ext/filters/client_channel/lb_policy_registry.h
@@ -45,4 +45,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_REGISTRY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_REGISTRY_H */
diff --git a/src/core/ext/filters/client_channel/parse_address.h b/src/core/ext/filters/client_channel/parse_address.h
index 742df38..27d06a1 100644
--- a/src/core/ext/filters/client_channel/parse_address.h
+++ b/src/core/ext/filters/client_channel/parse_address.h
@@ -53,4 +53,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */
diff --git a/src/core/ext/filters/client_channel/proxy_mapper.h b/src/core/ext/filters/client_channel/proxy_mapper.h
index 1325a9f..bb8259f 100644
--- a/src/core/ext/filters/client_channel/proxy_mapper.h
+++ b/src/core/ext/filters/client_channel/proxy_mapper.h
@@ -79,4 +79,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_H */
diff --git a/src/core/ext/filters/client_channel/proxy_mapper_registry.h b/src/core/ext/filters/client_channel/proxy_mapper_registry.h
index 2d389f1..39c607c 100644
--- a/src/core/ext/filters/client_channel/proxy_mapper_registry.h
+++ b/src/core/ext/filters/client_channel/proxy_mapper_registry.h
@@ -49,4 +49,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */
diff --git a/src/core/ext/filters/client_channel/resolver_factory.h b/src/core/ext/filters/client_channel/resolver_factory.h
index 6e533e3..c8b2c58 100644
--- a/src/core/ext/filters/client_channel/resolver_factory.h
+++ b/src/core/ext/filters/client_channel/resolver_factory.h
@@ -75,4 +75,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FACTORY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FACTORY_H */
diff --git a/src/core/ext/filters/client_channel/resolver_registry.h b/src/core/ext/filters/client_channel/resolver_registry.h
index eb08d88..06d0b99 100644
--- a/src/core/ext/filters/client_channel/resolver_registry.h
+++ b/src/core/ext/filters/client_channel/resolver_registry.h
@@ -74,4 +74,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */
diff --git a/src/core/ext/filters/client_channel/retry_throttle.h b/src/core/ext/filters/client_channel/retry_throttle.h
index 3b84947..399383d 100644
--- a/src/core/ext/filters/client_channel/retry_throttle.h
+++ b/src/core/ext/filters/client_channel/retry_throttle.h
@@ -55,4 +55,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_THROTTLE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_THROTTLE_H */
diff --git a/src/core/ext/filters/client_channel/subchannel_index.h b/src/core/ext/filters/client_channel/subchannel_index.h
index 09bac35..05c3878 100644
--- a/src/core/ext/filters/client_channel/subchannel_index.h
+++ b/src/core/ext/filters/client_channel/subchannel_index.h
@@ -86,4 +86,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H */
diff --git a/src/core/ext/filters/client_channel/uri_parser.h b/src/core/ext/filters/client_channel/uri_parser.h
index 43e8ae6..e78da59 100644
--- a/src/core/ext/filters/client_channel/uri_parser.h
+++ b/src/core/ext/filters/client_channel/uri_parser.h
@@ -55,4 +55,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_URI_PARSER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_URI_PARSER_H */
diff --git a/src/core/ext/filters/deadline/deadline_filter.h b/src/core/ext/filters/deadline/deadline_filter.h
index 4a80535..e665dc5 100644
--- a/src/core/ext/filters/deadline/deadline_filter.h
+++ b/src/core/ext/filters/deadline/deadline_filter.h
@@ -98,4 +98,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_DEADLINE_DEADLINE_FILTER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_DEADLINE_DEADLINE_FILTER_H */
diff --git a/src/core/ext/filters/workarounds/workaround_utils.h b/src/core/ext/filters/workarounds/workaround_utils.h
index afd5291..3913cae 100644
--- a/src/core/ext/filters/workarounds/workaround_utils.h
+++ b/src/core/ext/filters/workarounds/workaround_utils.h
@@ -42,4 +42,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_FILTERS_WORKAROUNDS_WORKAROUND_UTILS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_FILTERS_WORKAROUNDS_WORKAROUND_UTILS_H */
diff --git a/src/core/ext/transport/chttp2/alpn/alpn.h b/src/core/ext/transport/chttp2/alpn/alpn.h
index 5842204..99b928e 100644
--- a/src/core/ext/transport/chttp2/alpn/alpn.h
+++ b/src/core/ext/transport/chttp2/alpn/alpn.h
@@ -39,4 +39,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_ALPN_ALPN_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_ALPN_ALPN_H */
diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc
index 202bcd4..74839f2 100644
--- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc
+++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc
@@ -115,6 +115,8 @@
     }
     memset(c->result, 0, sizeof(*c->result));
   } else {
+    grpc_endpoint_delete_from_pollset_set(exec_ctx, args->endpoint,
+                                          c->args.interested_parties);
     c->result->transport =
         grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 1);
     GPR_ASSERT(c->result->transport);
@@ -136,6 +138,8 @@
   c->handshake_mgr = grpc_handshake_manager_create();
   grpc_handshakers_add(exec_ctx, HANDSHAKER_CLIENT, c->args.channel_args,
                        c->handshake_mgr);
+  grpc_endpoint_add_to_pollset_set(exec_ctx, c->endpoint,
+                                   c->args.interested_parties);
   grpc_handshake_manager_do_handshake(
       exec_ctx, c->handshake_mgr, c->endpoint, c->args.channel_args,
       c->args.deadline, NULL /* acceptor */, on_handshake_done, c);
diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.h b/src/core/ext/transport/chttp2/server/chttp2_server.h
index e1df28e..2ac1551 100644
--- a/src/core/ext/transport/chttp2/server/chttp2_server.h
+++ b/src/core/ext/transport/chttp2/server/chttp2_server.h
@@ -37,4 +37,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H */
diff --git a/src/core/ext/transport/chttp2/transport/bin_decoder.h b/src/core/ext/transport/chttp2/transport/bin_decoder.h
index f50e0a8..1c0b2b7 100644
--- a/src/core/ext/transport/chttp2/transport/bin_decoder.h
+++ b/src/core/ext/transport/chttp2/transport/bin_decoder.h
@@ -57,4 +57,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H */
diff --git a/src/core/ext/transport/chttp2/transport/bin_encoder.h b/src/core/ext/transport/chttp2/transport/bin_encoder.h
index ae8219c..0be3633 100644
--- a/src/core/ext/transport/chttp2/transport/bin_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/bin_encoder.h
@@ -44,4 +44,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index e4b19a2..02fc531 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -54,7 +54,6 @@
 #include "src/core/lib/transport/transport.h"
 #include "src/core/lib/transport/transport_impl.h"
 
-#define DEFAULT_WINDOW 65535
 #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
 #define MAX_WINDOW 0x7fffffffu
 #define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
@@ -152,10 +151,14 @@
 static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
                               grpc_error *error);
 
+static void schedule_bdp_ping_locked(grpc_exec_ctx *exec_ctx,
+                                     grpc_chttp2_transport *t);
 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 next_bdp_ping_timer_expired_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);
@@ -218,6 +221,9 @@
     t->write_cb_pool = next;
   }
 
+  t->flow_control.Destroy();
+
+  GRPC_ERROR_UNREF(t->closed_with_error);
   gpr_free(t->ping_acks);
   gpr_free(t->peer_string);
   gpr_free(t);
@@ -275,10 +281,6 @@
   t->endpoint_reading = 1;
   t->next_stream_id = is_client ? 1 : 2;
   t->is_client = is_client;
-  t->flow_control.remote_window = DEFAULT_WINDOW;
-  t->flow_control.announced_window = DEFAULT_WINDOW;
-  t->flow_control.target_initial_window_size = DEFAULT_WINDOW;
-  t->flow_control.t = t;
   t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
   t->is_first_frame = true;
   grpc_connectivity_state_init(
@@ -303,6 +305,9 @@
                     grpc_combiner_scheduler(t->combiner));
   GRPC_CLOSURE_INIT(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t,
                     grpc_combiner_scheduler(t->combiner));
+  GRPC_CLOSURE_INIT(&t->next_bdp_ping_timer_expired_locked,
+                    next_bdp_ping_timer_expired_locked, t,
+                    grpc_combiner_scheduler(t->combiner));
   GRPC_CLOSURE_INIT(&t->init_keepalive_ping_locked, init_keepalive_ping_locked,
                     t, grpc_combiner_scheduler(t->combiner));
   GRPC_CLOSURE_INIT(&t->start_keepalive_ping_locked,
@@ -315,8 +320,6 @@
                     keepalive_watchdog_fired_locked, t,
                     grpc_combiner_scheduler(t->combiner));
 
-  grpc_bdp_estimator_init(&t->flow_control.bdp_estimator, t->peer_string);
-
   grpc_chttp2_goaway_parser_init(&t->goaway_parser);
   grpc_chttp2_hpack_parser_init(exec_ctx, &t->hpack_parser);
 
@@ -340,8 +343,7 @@
      window -- this should by rights be 0 */
   t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
   t->sent_local_settings = 0;
-  t->write_buffer_size = DEFAULT_WINDOW;
-  t->flow_control.enable_bdp_probe = true;
+  t->write_buffer_size = grpc_core::chttp2::kDefaultWindow;
 
   if (is_client) {
     grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string(
@@ -386,6 +388,8 @@
 
   t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY;
 
+  bool enable_bdp = true;
+
   if (channel_args) {
     for (i = 0; i < channel_args->num_args; i++) {
       if (0 == strcmp(channel_args->args[i].key,
@@ -446,8 +450,7 @@
             &channel_args->args[i], {0, 0, MAX_WRITE_BUFFER_SIZE});
       } else if (0 ==
                  strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) {
-        t->flow_control.enable_bdp_probe =
-            grpc_channel_arg_get_integer(&channel_args->args[i], {1, 0, 1});
+        enable_bdp = grpc_channel_arg_get_bool(&channel_args->args[i], true);
       } else if (0 == strcmp(channel_args->args[i].key,
                              GRPC_ARG_KEEPALIVE_TIME_MS)) {
         const int value = grpc_channel_arg_get_integer(
@@ -542,6 +545,8 @@
     }
   }
 
+  t->flow_control.Init(exec_ctx, t, enable_bdp);
+
   /* No pings allowed before receiving a header or data frame. */
   t->ping_state.pings_before_data_required = 0;
   t->ping_state.is_delayed_ping_timer_set = false;
@@ -562,10 +567,13 @@
     t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED;
   }
 
-  grpc_chttp2_act_on_flowctl_action(
-      exec_ctx,
-      grpc_chttp2_flowctl_get_action(exec_ctx, &t->flow_control, NULL), t,
-      NULL);
+  if (enable_bdp) {
+    GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping");
+    schedule_bdp_ping_locked(exec_ctx, t);
+
+    grpc_chttp2_act_on_flowctl_action(
+        exec_ctx, t->flow_control->PeriodicUpdate(exec_ctx), t, NULL);
+  }
 
   grpc_chttp2_initiate_write(exec_ctx, t,
                              GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE);
@@ -595,7 +603,9 @@
 static void close_transport_locked(grpc_exec_ctx *exec_ctx,
                                    grpc_chttp2_transport *t,
                                    grpc_error *error) {
-  if (!t->closed) {
+  end_all_the_calls(exec_ctx, t, GRPC_ERROR_REF(error));
+  cancel_pings(exec_ctx, t, GRPC_ERROR_REF(error));
+  if (t->closed_with_error == GRPC_ERROR_NONE) {
     if (!grpc_error_has_clear_grpc_status(error)) {
       error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
                                  GRPC_STATUS_UNAVAILABLE);
@@ -610,13 +620,16 @@
           grpc_error_add_child(t->close_transport_on_writes_finished, error);
       return;
     }
-    t->closed = 1;
+    GPR_ASSERT(error != GRPC_ERROR_NONE);
+    t->closed_with_error = GRPC_ERROR_REF(error);
     connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
                            GRPC_ERROR_REF(error), "close_transport");
-    grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
     if (t->ping_state.is_delayed_ping_timer_set) {
       grpc_timer_cancel(exec_ctx, &t->ping_state.delayed_ping_timer);
     }
+    if (t->have_next_bdp_ping_timer) {
+      grpc_timer_cancel(exec_ctx, &t->next_bdp_ping_timer);
+    }
     switch (t->keepalive_state) {
       case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING:
         grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
@@ -636,8 +649,8 @@
     while (grpc_chttp2_list_pop_writable_stream(t, &s)) {
       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));
+    GPR_ASSERT(t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE);
+    grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
   }
   GRPC_ERROR_UNREF(error);
 }
@@ -698,7 +711,7 @@
     post_destructive_reclaimer(exec_ctx, t);
   }
 
-  s->flow_control.s = s;
+  s->flow_control.Init(t->flow_control.get(), s);
   GPR_TIMER_END("init_stream", 0);
 
   return 0;
@@ -749,7 +762,7 @@
   GRPC_ERROR_UNREF(s->write_closed_error);
   GRPC_ERROR_UNREF(s->byte_stream_error);
 
-  grpc_chttp2_flowctl_destroy_stream(&t->flow_control, &s->flow_control);
+  s->flow_control.Destroy();
 
   GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream");
 
@@ -940,7 +953,8 @@
 void grpc_chttp2_mark_stream_writable(grpc_exec_ctx *exec_ctx,
                                       grpc_chttp2_transport *t,
                                       grpc_chttp2_stream *s) {
-  if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
+  if (t->closed_with_error == GRPC_ERROR_NONE &&
+      grpc_chttp2_list_add_writable_stream(t, s)) {
     GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become");
   }
 }
@@ -993,7 +1007,7 @@
   grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
   GPR_ASSERT(t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE);
   grpc_chttp2_begin_write_result r;
-  if (t->closed) {
+  if (t->closed_with_error != GRPC_ERROR_NONE) {
     r.writing = false;
   } else {
     r = grpc_chttp2_begin_write(exec_ctx, t);
@@ -1456,7 +1470,7 @@
       }
       if (!s->write_closed) {
         if (t->is_client) {
-          if (!t->closed) {
+          if (t->closed_with_error == GRPC_ERROR_NONE) {
             GPR_ASSERT(s->id == 0);
             grpc_chttp2_list_add_waiting_for_concurrency(t, s);
             maybe_start_some_streams(exec_ctx, t);
@@ -1464,7 +1478,8 @@
             grpc_chttp2_cancel_stream(
                 exec_ctx, t, s,
                 grpc_error_set_int(
-                    GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport closed"),
+                    GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+                        "Transport closed", &t->closed_with_error, 1),
                     GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
           }
         } else {
@@ -1616,13 +1631,10 @@
     if (s->id != 0) {
       if (!s->read_closed) {
         already_received = s->frame_storage.length;
-        grpc_chttp2_flowctl_incoming_bs_update(
-            &t->flow_control, &s->flow_control, GRPC_HEADER_SIZE_IN_BYTES,
-            already_received);
-        grpc_chttp2_act_on_flowctl_action(
-            exec_ctx, grpc_chttp2_flowctl_get_action(exec_ctx, &t->flow_control,
-                                                     &s->flow_control),
-            t, s);
+        s->flow_control->IncomingByteStreamUpdate(GRPC_HEADER_SIZE_IN_BYTES,
+                                                  already_received);
+        grpc_chttp2_act_on_flowctl_action(exec_ctx,
+                                          s->flow_control->MakeAction(), t, s);
       }
     }
     grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
@@ -1686,6 +1698,7 @@
   /* callback remaining pings: they're not allowed to call into the transpot,
      and maybe they hold resources that need to be freed */
   grpc_chttp2_ping_queue *pq = &t->ping_queue;
+  GPR_ASSERT(error != GRPC_ERROR_NONE);
   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]);
@@ -1695,6 +1708,12 @@
 
 static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
                              grpc_closure *on_initiate, grpc_closure *on_ack) {
+  if (t->closed_with_error != GRPC_ERROR_NONE) {
+    GRPC_CLOSURE_SCHED(exec_ctx, on_initiate,
+                       GRPC_ERROR_REF(t->closed_with_error));
+    GRPC_CLOSURE_SCHED(exec_ctx, on_ack, GRPC_ERROR_REF(t->closed_with_error));
+    return;
+  }
   grpc_chttp2_ping_queue *pq = &t->ping_queue;
   grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate,
                            GRPC_ERROR_NONE);
@@ -1753,7 +1772,9 @@
                     GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM));
     /*The transport will be closed after the write is done */
     close_transport_locked(
-        exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many pings"));
+        exec_ctx, t, grpc_error_set_int(
+                         GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many pings"),
+                         GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
   }
 }
 
@@ -2389,55 +2410,44 @@
  * INPUT PROCESSING - PARSING
  */
 
-void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
-                                       grpc_chttp2_flowctl_action action,
-                                       grpc_chttp2_transport *t,
-                                       grpc_chttp2_stream *s) {
-  switch (action.send_stream_update) {
-    case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
+template <class F>
+static void WithUrgency(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                        grpc_core::chttp2::FlowControlAction::Urgency urgency,
+                        grpc_chttp2_initiate_write_reason reason, F action) {
+  switch (urgency) {
+    case grpc_core::chttp2::FlowControlAction::Urgency::NO_ACTION_NEEDED:
       break;
-    case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
-      grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
-      grpc_chttp2_initiate_write(
-          exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL);
-      break;
-    case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
-      grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
+    case grpc_core::chttp2::FlowControlAction::Urgency::UPDATE_IMMEDIATELY:
+      grpc_chttp2_initiate_write(exec_ctx, t, reason);
+    // fallthrough
+    case grpc_core::chttp2::FlowControlAction::Urgency::QUEUE_UPDATE:
+      action();
       break;
   }
-  switch (action.send_transport_update) {
-    case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
-      break;
-    case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
-      grpc_chttp2_initiate_write(
-          exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL);
-      break;
-    // this is the same as no action b/c every time the transport enters the
-    // writing path it will maybe do an update
-    case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
-      break;
-  }
-  if (action.send_setting_update != GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED) {
-    if (action.initial_window_size > 0) {
-      queue_setting_update(exec_ctx, t,
-                           GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
-                           (uint32_t)action.initial_window_size);
-    }
-    if (action.max_frame_size > 0) {
-      queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
-                           (uint32_t)action.max_frame_size);
-    }
-    if (action.send_setting_update == GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY) {
-      grpc_chttp2_initiate_write(exec_ctx, t,
-                                 GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS);
-    }
-  }
-  if (action.need_ping) {
-    GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping");
-    grpc_bdp_estimator_schedule_ping(&t->flow_control.bdp_estimator);
-    send_ping_locked(exec_ctx, t, &t->start_bdp_ping_locked,
-                     &t->finish_bdp_ping_locked);
-  }
+}
+
+void grpc_chttp2_act_on_flowctl_action(
+    grpc_exec_ctx *exec_ctx, const grpc_core::chttp2::FlowControlAction &action,
+    grpc_chttp2_transport *t, grpc_chttp2_stream *s) {
+  WithUrgency(
+      exec_ctx, t, action.send_stream_update(),
+      GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL,
+      [exec_ctx, t, s]() { grpc_chttp2_mark_stream_writable(exec_ctx, t, s); });
+  WithUrgency(exec_ctx, t, action.send_transport_update(),
+              GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL, []() {});
+  WithUrgency(exec_ctx, t, action.send_initial_window_update(),
+              GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS,
+              [exec_ctx, t, &action]() {
+                queue_setting_update(exec_ctx, t,
+                                     GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
+                                     action.initial_window_size());
+              });
+  WithUrgency(
+      exec_ctx, t, action.send_max_frame_size_update(),
+      GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS, [exec_ctx, t, &action]() {
+        queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
+                             action.max_frame_size());
+      });
 }
 
 static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
@@ -2487,14 +2497,13 @@
   }
   GPR_SWAP(grpc_error *, err, error);
   GRPC_ERROR_UNREF(err);
-  if (!t->closed) {
+  if (t->closed_with_error == GRPC_ERROR_NONE) {
     GPR_TIMER_BEGIN("reading_action.parse", 0);
     size_t i = 0;
     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++) {
-      grpc_bdp_estimator_add_incoming_bytes(
-          &t->flow_control.bdp_estimator,
+      t->flow_control->bdp_estimator()->AddIncomingBytes(
           (int64_t)GRPC_SLICE_LENGTH(t->read_buffer.slices[i]));
       errors[1] =
           grpc_chttp2_perform_read(exec_ctx, t, t->read_buffer.slices[i]);
@@ -2511,8 +2520,8 @@
     GPR_TIMER_END("reading_action.parse", 0);
 
     GPR_TIMER_BEGIN("post_parse_locked", 0);
-    if (t->flow_control.initial_window_update != 0) {
-      if (t->flow_control.initial_window_update > 0) {
+    if (t->initial_window_update != 0) {
+      if (t->initial_window_update > 0) {
         grpc_chttp2_stream *s;
         while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) {
           grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
@@ -2521,20 +2530,21 @@
               GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING);
         }
       }
-      t->flow_control.initial_window_update = 0;
+      t->initial_window_update = 0;
     }
     GPR_TIMER_END("post_parse_locked", 0);
   }
 
   GPR_TIMER_BEGIN("post_reading_action_locked", 0);
   bool keep_reading = false;
-  if (error == GRPC_ERROR_NONE && t->closed) {
-    error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport closed");
+  if (error == GRPC_ERROR_NONE && t->closed_with_error != GRPC_ERROR_NONE) {
+    error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+        "Transport closed", &t->closed_with_error, 1);
   }
   if (error != GRPC_ERROR_NONE) {
     close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error));
     t->endpoint_reading = 0;
-  } else if (!t->closed) {
+  } else if (t->closed_with_error == GRPC_ERROR_NONE) {
     keep_reading = true;
     GRPC_CHTTP2_REF_TRANSPORT(t, "keep_reading");
   }
@@ -2543,10 +2553,8 @@
   if (keep_reading) {
     grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer,
                        &t->read_action_locked);
-    grpc_chttp2_act_on_flowctl_action(
-        exec_ctx,
-        grpc_chttp2_flowctl_get_action(exec_ctx, &t->flow_control, NULL), t,
-        NULL);
+    grpc_chttp2_act_on_flowctl_action(exec_ctx, t->flow_control->MakeAction(),
+                                      t, NULL);
     GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
   } else {
     GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "reading_action");
@@ -2559,28 +2567,60 @@
   GPR_TIMER_END("reading_action_locked", 0);
 }
 
+// t is reffed prior to calling the first time, and once the callback chain
+// that kicks off finishes, it's unreffed
+static void schedule_bdp_ping_locked(grpc_exec_ctx *exec_ctx,
+                                     grpc_chttp2_transport *t) {
+  t->flow_control->bdp_estimator()->SchedulePing();
+  send_ping_locked(exec_ctx, t, &t->start_bdp_ping_locked,
+                   &t->finish_bdp_ping_locked);
+}
+
 static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
                                   grpc_error *error) {
   grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
   if (GRPC_TRACER_ON(grpc_http_trace)) {
-    gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string);
+    gpr_log(GPR_DEBUG, "%s: Start BDP ping err=%s", t->peer_string,
+            grpc_error_string(error));
   }
   /* Reset the keepalive ping timer */
   if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING) {
     grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
   }
-  grpc_bdp_estimator_start_ping(&t->flow_control.bdp_estimator);
+  t->flow_control->bdp_estimator()->StartPing();
 }
 
 static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
                                    grpc_error *error) {
   grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
   if (GRPC_TRACER_ON(grpc_http_trace)) {
-    gpr_log(GPR_DEBUG, "%s: Complete BDP ping", t->peer_string);
+    gpr_log(GPR_DEBUG, "%s: Complete BDP ping err=%s", t->peer_string,
+            grpc_error_string(error));
   }
-  grpc_bdp_estimator_complete_ping(exec_ctx, &t->flow_control.bdp_estimator);
+  if (error != GRPC_ERROR_NONE) {
+    GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
+    return;
+  }
+  grpc_millis next_ping =
+      t->flow_control->bdp_estimator()->CompletePing(exec_ctx);
+  grpc_chttp2_act_on_flowctl_action(
+      exec_ctx, t->flow_control->PeriodicUpdate(exec_ctx), t, nullptr);
+  GPR_ASSERT(!t->have_next_bdp_ping_timer);
+  t->have_next_bdp_ping_timer = true;
+  grpc_timer_init(exec_ctx, &t->next_bdp_ping_timer, next_ping,
+                  &t->next_bdp_ping_timer_expired_locked);
+}
 
-  GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
+static void next_bdp_ping_timer_expired_locked(grpc_exec_ctx *exec_ctx,
+                                               void *tp, grpc_error *error) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
+  GPR_ASSERT(t->have_next_bdp_ping_timer);
+  t->have_next_bdp_ping_timer = false;
+  if (error != GRPC_ERROR_NONE) {
+    GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
+    return;
+  }
+  schedule_bdp_ping_locked(exec_ctx, t);
 }
 
 void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args,
@@ -2645,7 +2685,7 @@
                                        grpc_error *error) {
   grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
   GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING);
-  if (t->destroying || t->closed) {
+  if (t->destroying || t->closed_with_error != GRPC_ERROR_NONE) {
     t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
   } else if (error == GRPC_ERROR_NONE) {
     if (t->keepalive_permit_without_calls ||
@@ -2703,8 +2743,11 @@
   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_FROM_STATIC_STRING(
-                                              "keepalive watchdog timeout"));
+      close_transport_locked(
+          exec_ctx, t,
+          grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                                 "keepalive watchdog timeout"),
+                             GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL));
     }
   } else {
     /* The watchdog timer should have been cancelled by
@@ -2787,13 +2830,10 @@
 
   size_t cur_length = s->frame_storage.length;
   if (!s->read_closed) {
-    grpc_chttp2_flowctl_incoming_bs_update(&t->flow_control, &s->flow_control,
-                                           bs->next_action.max_size_hint,
-                                           cur_length);
-    grpc_chttp2_act_on_flowctl_action(
-        exec_ctx, grpc_chttp2_flowctl_get_action(exec_ctx, &t->flow_control,
-                                                 &s->flow_control),
-        t, s);
+    s->flow_control->IncomingByteStreamUpdate(bs->next_action.max_size_hint,
+                                              cur_length);
+    grpc_chttp2_act_on_flowctl_action(exec_ctx, s->flow_control->MakeAction(),
+                                      t, s);
   }
   GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0);
   if (s->frame_storage.length > 0) {
diff --git a/src/core/ext/transport/chttp2/transport/flow_control.cc b/src/core/ext/transport/chttp2/transport/flow_control.cc
index 2428e25..dd80036 100644
--- a/src/core/ext/transport/chttp2/transport/flow_control.cc
+++ b/src/core/ext/transport/chttp2/transport/flow_control.cc
@@ -16,7 +16,7 @@
  *
  */
 
-#include "src/core/ext/transport/chttp2/transport/internal.h"
+#include "src/core/ext/transport/chttp2/transport/flow_control.h"
 
 #include <inttypes.h>
 #include <limits.h>
@@ -28,38 +28,15 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
+#include "src/core/ext/transport/chttp2/transport/internal.h"
 #include "src/core/lib/support/string.h"
 
-static uint32_t grpc_chttp2_target_announced_window(
-    const grpc_chttp2_transport_flowctl* tfc);
+namespace grpc_core {
+namespace chttp2 {
 
-#ifndef NDEBUG
+namespace {
 
-typedef struct {
-  int64_t remote_window;
-  int64_t target_window;
-  int64_t announced_window;
-  int64_t remote_window_delta;
-  int64_t local_window_delta;
-  int64_t announced_window_delta;
-  uint32_t local_init_window;
-  uint32_t local_max_frame;
-} shadow_flow_control;
-
-static void pretrace(shadow_flow_control* shadow_fc,
-                     grpc_chttp2_transport_flowctl* tfc,
-                     grpc_chttp2_stream_flowctl* sfc) {
-  shadow_fc->remote_window = tfc->remote_window;
-  shadow_fc->target_window = grpc_chttp2_target_announced_window(tfc);
-  shadow_fc->announced_window = tfc->announced_window;
-  if (sfc != NULL) {
-    shadow_fc->remote_window_delta = sfc->remote_window_delta;
-    shadow_fc->local_window_delta = sfc->local_window_delta;
-    shadow_fc->announced_window_delta = sfc->announced_window_delta;
-  }
-}
-
-#define TRACE_PADDING 30
+static constexpr const int kTracePadding = 30;
 
 static char* fmt_int64_diff_str(int64_t old_val, int64_t new_val) {
   char* str;
@@ -68,7 +45,7 @@
   } else {
     gpr_asprintf(&str, "%" PRId64 "", old_val);
   }
-  char* str_lp = gpr_leftpad(str, ' ', TRACE_PADDING);
+  char* str_lp = gpr_leftpad(str, ' ', kTracePadding);
   gpr_free(str);
   return str_lp;
 }
@@ -80,47 +57,58 @@
   } else {
     gpr_asprintf(&str, "%" PRIu32 "", old_val);
   }
-  char* str_lp = gpr_leftpad(str, ' ', TRACE_PADDING);
+  char* str_lp = gpr_leftpad(str, ' ', kTracePadding);
   gpr_free(str);
   return str_lp;
 }
+}  // namespace
 
-static void posttrace(shadow_flow_control* shadow_fc,
-                      grpc_chttp2_transport_flowctl* tfc,
-                      grpc_chttp2_stream_flowctl* sfc, const char* reason) {
+void FlowControlTrace::Init(const char* reason, TransportFlowControl* tfc,
+                            StreamFlowControl* sfc) {
+  tfc_ = tfc;
+  sfc_ = sfc;
+  reason_ = reason;
+  remote_window_ = tfc->remote_window();
+  target_window_ = tfc->target_window();
+  announced_window_ = tfc->announced_window();
+  if (sfc != nullptr) {
+    remote_window_delta_ = sfc->remote_window_delta();
+    local_window_delta_ = sfc->local_window_delta();
+    announced_window_delta_ = sfc->announced_window_delta();
+  }
+}
+
+void FlowControlTrace::Finish() {
   uint32_t acked_local_window =
-      tfc->t->settings[GRPC_SENT_SETTINGS]
-                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+      tfc_->transport()->settings[GRPC_SENT_SETTINGS]
+                                 [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
   uint32_t remote_window =
-      tfc->t->settings[GRPC_PEER_SETTINGS]
-                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-  char* trw_str =
-      fmt_int64_diff_str(shadow_fc->remote_window, tfc->remote_window);
-  char* tlw_str = fmt_int64_diff_str(shadow_fc->target_window,
-                                     grpc_chttp2_target_announced_window(tfc));
+      tfc_->transport()->settings[GRPC_PEER_SETTINGS]
+                                 [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+  char* trw_str = fmt_int64_diff_str(remote_window_, tfc_->remote_window());
+  char* tlw_str = fmt_int64_diff_str(target_window_, tfc_->target_window());
   char* taw_str =
-      fmt_int64_diff_str(shadow_fc->announced_window, tfc->announced_window);
+      fmt_int64_diff_str(announced_window_, tfc_->announced_window());
   char* srw_str;
   char* slw_str;
   char* saw_str;
-  if (sfc != NULL) {
-    srw_str = fmt_int64_diff_str(shadow_fc->remote_window_delta + remote_window,
-                                 sfc->remote_window_delta + remote_window);
-    slw_str =
-        fmt_int64_diff_str(shadow_fc->local_window_delta + acked_local_window,
-                           sfc->local_window_delta + acked_local_window);
-    saw_str = fmt_int64_diff_str(
-        shadow_fc->announced_window_delta + acked_local_window,
-        sfc->announced_window_delta + acked_local_window);
+  if (sfc_ != nullptr) {
+    srw_str = fmt_int64_diff_str(remote_window_delta_ + remote_window,
+                                 sfc_->remote_window_delta() + remote_window);
+    slw_str = fmt_int64_diff_str(local_window_delta_ + acked_local_window,
+                                 local_window_delta_ + acked_local_window);
+    saw_str = fmt_int64_diff_str(announced_window_delta_ + acked_local_window,
+                                 announced_window_delta_ + acked_local_window);
   } else {
-    srw_str = gpr_leftpad("", ' ', TRACE_PADDING);
-    slw_str = gpr_leftpad("", ' ', TRACE_PADDING);
-    saw_str = gpr_leftpad("", ' ', TRACE_PADDING);
+    srw_str = gpr_leftpad("", ' ', kTracePadding);
+    slw_str = gpr_leftpad("", ' ', kTracePadding);
+    saw_str = gpr_leftpad("", ' ', kTracePadding);
   }
   gpr_log(GPR_DEBUG,
           "%p[%u][%s] | %s | trw:%s, ttw:%s, taw:%s, srw:%s, slw:%s, saw:%s",
-          tfc, sfc != NULL ? sfc->s->id : 0, tfc->t->is_client ? "cli" : "svr",
-          reason, trw_str, tlw_str, taw_str, srw_str, slw_str, saw_str);
+          tfc_, sfc_ != nullptr ? sfc_->stream()->id : 0,
+          tfc_->transport()->is_client ? "cli" : "svr", reason_, trw_str,
+          tlw_str, taw_str, srw_str, slw_str, saw_str);
   gpr_free(trw_str);
   gpr_free(tlw_str);
   gpr_free(taw_str);
@@ -129,13 +117,13 @@
   gpr_free(saw_str);
 }
 
-static const char* urgency_to_string(grpc_chttp2_flowctl_urgency urgency) {
-  switch (urgency) {
-    case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
+const char* FlowControlAction::UrgencyString(Urgency u) {
+  switch (u) {
+    case Urgency::NO_ACTION_NEEDED:
       return "no action";
-    case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
+    case Urgency::UPDATE_IMMEDIATELY:
       return "update immediately";
-    case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
+    case Urgency::QUEUE_UPDATE:
       return "queue update";
     default:
       GPR_UNREACHABLE_CODE(return "unknown");
@@ -143,209 +131,132 @@
   GPR_UNREACHABLE_CODE(return "unknown");
 }
 
-static void trace_action(grpc_chttp2_transport_flowctl* tfc,
-                         grpc_chttp2_flowctl_action action) {
+void FlowControlAction::Trace(grpc_chttp2_transport* t) const {
   char* iw_str = fmt_uint32_diff_str(
-      tfc->t->settings[GRPC_SENT_SETTINGS]
-                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
-      action.initial_window_size);
+      t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
+      initial_window_size_);
   char* mf_str = fmt_uint32_diff_str(
-      tfc->t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
-      action.max_frame_size);
-  gpr_log(GPR_DEBUG, "t[%s],  s[%s], settings[%s] iw:%s mf:%s",
-          urgency_to_string(action.send_transport_update),
-          urgency_to_string(action.send_stream_update),
-          urgency_to_string(action.send_setting_update), iw_str, mf_str);
+      t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
+      max_frame_size_);
+  gpr_log(GPR_DEBUG, "t[%s],  s[%s], iw:%s:%s mf:%s:%s",
+          UrgencyString(send_transport_update_),
+          UrgencyString(send_stream_update_),
+          UrgencyString(send_initial_window_update_), iw_str,
+          UrgencyString(send_max_frame_size_update_), mf_str);
   gpr_free(iw_str);
   gpr_free(mf_str);
 }
 
-#define PRETRACE(tfc, sfc)       \
-  shadow_flow_control shadow_fc; \
-  GRPC_FLOW_CONTROL_IF_TRACING(pretrace(&shadow_fc, tfc, sfc))
-#define POSTTRACE(tfc, sfc, reason) \
-  GRPC_FLOW_CONTROL_IF_TRACING(posttrace(&shadow_fc, tfc, sfc, reason))
-#define TRACEACTION(tfc, action) \
-  GRPC_FLOW_CONTROL_IF_TRACING(trace_action(tfc, action))
-#else
-#define PRETRACE(tfc, sfc)
-#define POSTTRACE(tfc, sfc, reason)
-#define TRACEACTION(tfc, action)
-#endif
+TransportFlowControl::TransportFlowControl(grpc_exec_ctx* exec_ctx,
+                                           const grpc_chttp2_transport* t,
+                                           bool enable_bdp_probe)
+    : t_(t),
+      enable_bdp_probe_(enable_bdp_probe),
+      bdp_estimator_(t->peer_string),
+      pid_controller_(grpc_core::PidController::Args()
+                          .set_gain_p(4)
+                          .set_gain_i(8)
+                          .set_gain_d(0)
+                          .set_initial_control_value(TargetLogBdp())
+                          .set_min_control_value(-1)
+                          .set_max_control_value(25)
+                          .set_integral_range(10)),
+      last_pid_update_(grpc_exec_ctx_now(exec_ctx)) {}
 
-/* How many bytes of incoming flow control would we like to advertise */
-static uint32_t grpc_chttp2_target_announced_window(
-    const grpc_chttp2_transport_flowctl* tfc) {
-  return (uint32_t)GPR_MIN((int64_t)((1u << 31) - 1),
-                           tfc->announced_stream_total_over_incoming_window +
-                               tfc->target_initial_window_size);
-}
-
-// we have sent data on the wire, we must track this in our bookkeeping for the
-// remote peer's flow control.
-void grpc_chttp2_flowctl_sent_data(grpc_chttp2_transport_flowctl* tfc,
-                                   grpc_chttp2_stream_flowctl* sfc,
-                                   int64_t size) {
-  PRETRACE(tfc, sfc);
-  tfc->remote_window -= size;
-  sfc->remote_window_delta -= size;
-  POSTTRACE(tfc, sfc, "  data sent");
-}
-
-static void announced_window_delta_preupdate(grpc_chttp2_transport_flowctl* tfc,
-                                             grpc_chttp2_stream_flowctl* sfc) {
-  if (sfc->announced_window_delta > 0) {
-    tfc->announced_stream_total_over_incoming_window -=
-        sfc->announced_window_delta;
-  } else {
-    tfc->announced_stream_total_under_incoming_window +=
-        -sfc->announced_window_delta;
+uint32_t TransportFlowControl::MaybeSendUpdate(bool writing_anyway) {
+  FlowControlTrace trace("t updt sent", this, nullptr);
+  const uint32_t target_announced_window = target_window();
+  if ((writing_anyway || announced_window_ <= target_announced_window / 2) &&
+      announced_window_ != target_announced_window) {
+    const uint32_t announce = (uint32_t)GPR_CLAMP(
+        target_announced_window - announced_window_, 0, UINT32_MAX);
+    announced_window_ += announce;
+    return announce;
   }
+  return 0;
 }
 
-static void announced_window_delta_postupdate(
-    grpc_chttp2_transport_flowctl* tfc, grpc_chttp2_stream_flowctl* sfc) {
-  if (sfc->announced_window_delta > 0) {
-    tfc->announced_stream_total_over_incoming_window +=
-        sfc->announced_window_delta;
-  } else {
-    tfc->announced_stream_total_under_incoming_window -=
-        -sfc->announced_window_delta;
-  }
-}
-
-// We have received data from the wire. We must track this in our own flow
-// control bookkeeping.
-// Returns an error if the incoming frame violates our flow control.
-grpc_error* grpc_chttp2_flowctl_recv_data(grpc_chttp2_transport_flowctl* tfc,
-                                          grpc_chttp2_stream_flowctl* sfc,
-                                          int64_t incoming_frame_size) {
-  uint32_t sent_init_window =
-      tfc->t->settings[GRPC_SENT_SETTINGS]
-                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-  uint32_t acked_init_window =
-      tfc->t->settings[GRPC_ACKED_SETTINGS]
-                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-  PRETRACE(tfc, sfc);
-  if (incoming_frame_size > tfc->announced_window) {
+grpc_error* TransportFlowControl::ValidateRecvData(
+    int64_t incoming_frame_size) {
+  if (incoming_frame_size > announced_window_) {
     char* msg;
     gpr_asprintf(&msg,
                  "frame of size %" PRId64 " overflows local window of %" PRId64,
-                 incoming_frame_size, tfc->announced_window);
+                 incoming_frame_size, announced_window_);
     grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
     gpr_free(msg);
     return err;
   }
-
-  if (sfc != NULL) {
-    int64_t acked_stream_window =
-        sfc->announced_window_delta + acked_init_window;
-    int64_t sent_stream_window = sfc->announced_window_delta + sent_init_window;
-    if (incoming_frame_size > acked_stream_window) {
-      if (incoming_frame_size <= sent_stream_window) {
-        gpr_log(
-            GPR_ERROR,
-            "Incoming frame of size %" PRId64
-            " exceeds local window size of %" PRId64
-            ".\n"
-            "The (un-acked, future) window size would be %" PRId64
-            " which is not exceeded.\n"
-            "This would usually cause a disconnection, but allowing it due to"
-            "broken HTTP2 implementations in the wild.\n"
-            "See (for example) https://github.com/netty/netty/issues/6520.",
-            incoming_frame_size, acked_stream_window, sent_stream_window);
-      } else {
-        char* msg;
-        gpr_asprintf(&msg, "frame of size %" PRId64
-                           " overflows local window of %" PRId64,
-                     incoming_frame_size, acked_stream_window);
-        grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
-        gpr_free(msg);
-        return err;
-      }
-    }
-
-    announced_window_delta_preupdate(tfc, sfc);
-    sfc->announced_window_delta -= incoming_frame_size;
-    announced_window_delta_postupdate(tfc, sfc);
-    sfc->local_window_delta -= incoming_frame_size;
-  }
-
-  tfc->announced_window -= incoming_frame_size;
-
-  POSTTRACE(tfc, sfc, "  data recv");
   return GRPC_ERROR_NONE;
 }
 
-// Returns a non zero announce integer if we should send a transport window
-// update
-uint32_t grpc_chttp2_flowctl_maybe_send_transport_update(
-    grpc_chttp2_transport_flowctl* tfc, bool writing_anyway) {
-  PRETRACE(tfc, NULL);
-  uint32_t target_announced_window = grpc_chttp2_target_announced_window(tfc);
-  uint32_t threshold_to_send_transport_window_update =
-      tfc->t->outbuf.count > 0 ? 3 * target_announced_window / 4
-                               : target_announced_window / 2;
-  if ((writing_anyway ||
-       tfc->announced_window <= threshold_to_send_transport_window_update) &&
-      tfc->announced_window != target_announced_window) {
+StreamFlowControl::StreamFlowControl(TransportFlowControl* tfc,
+                                     const grpc_chttp2_stream* s)
+    : tfc_(tfc), s_(s) {}
+
+grpc_error* StreamFlowControl::RecvData(int64_t incoming_frame_size) {
+  FlowControlTrace trace("  data recv", tfc_, this);
+
+  grpc_error* error = GRPC_ERROR_NONE;
+  error = tfc_->ValidateRecvData(incoming_frame_size);
+  if (error != GRPC_ERROR_NONE) return error;
+
+  uint32_t sent_init_window =
+      tfc_->transport()->settings[GRPC_SENT_SETTINGS]
+                                 [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+  uint32_t acked_init_window =
+      tfc_->transport()->settings[GRPC_ACKED_SETTINGS]
+                                 [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+
+  int64_t acked_stream_window = announced_window_delta_ + acked_init_window;
+  int64_t sent_stream_window = announced_window_delta_ + sent_init_window;
+  if (incoming_frame_size > acked_stream_window) {
+    if (incoming_frame_size <= sent_stream_window) {
+      gpr_log(GPR_ERROR,
+              "Incoming frame of size %" PRId64
+              " exceeds local window size of %" PRId64
+              ".\n"
+              "The (un-acked, future) window size would be %" PRId64
+              " which is not exceeded.\n"
+              "This would usually cause a disconnection, but allowing it due to"
+              "broken HTTP2 implementations in the wild.\n"
+              "See (for example) https://github.com/netty/netty/issues/6520.",
+              incoming_frame_size, acked_stream_window, sent_stream_window);
+    } else {
+      char* msg;
+      gpr_asprintf(&msg, "frame of size %" PRId64
+                         " overflows local window of %" PRId64,
+                   incoming_frame_size, acked_stream_window);
+      grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+      gpr_free(msg);
+      return err;
+    }
+  }
+
+  UpdateAnnouncedWindowDelta(tfc_, -incoming_frame_size);
+  local_window_delta_ -= incoming_frame_size;
+  tfc_->CommitRecvData(incoming_frame_size);
+  return GRPC_ERROR_NONE;
+}
+
+uint32_t StreamFlowControl::MaybeSendUpdate() {
+  FlowControlTrace trace("s updt sent", tfc_, this);
+  if (local_window_delta_ > announced_window_delta_) {
     uint32_t announce = (uint32_t)GPR_CLAMP(
-        target_announced_window - tfc->announced_window, 0, UINT32_MAX);
-    tfc->announced_window += announce;
-    POSTTRACE(tfc, NULL, "t updt sent");
+        local_window_delta_ - announced_window_delta_, 0, UINT32_MAX);
+    UpdateAnnouncedWindowDelta(tfc_, announce);
     return announce;
   }
-  GRPC_FLOW_CONTROL_IF_TRACING(
-      gpr_log(GPR_DEBUG, "%p[0][%s] will not send transport update", tfc,
-              tfc->t->is_client ? "cli" : "svr"));
   return 0;
 }
 
-// Returns a non zero announce integer if we should send a stream window update
-uint32_t grpc_chttp2_flowctl_maybe_send_stream_update(
-    grpc_chttp2_transport_flowctl* tfc, grpc_chttp2_stream_flowctl* sfc) {
-  PRETRACE(tfc, sfc);
-  if (sfc->local_window_delta > sfc->announced_window_delta) {
-    uint32_t announce = (uint32_t)GPR_CLAMP(
-        sfc->local_window_delta - sfc->announced_window_delta, 0, UINT32_MAX);
-    announced_window_delta_preupdate(tfc, sfc);
-    sfc->announced_window_delta += announce;
-    announced_window_delta_postupdate(tfc, sfc);
-    POSTTRACE(tfc, sfc, "s updt sent");
-    return announce;
-  }
-  GRPC_FLOW_CONTROL_IF_TRACING(
-      gpr_log(GPR_DEBUG, "%p[%u][%s] will not send stream update", tfc,
-              sfc->s->id, tfc->t->is_client ? "cli" : "svr"));
-  return 0;
-}
-
-// we have received a WINDOW_UPDATE frame for a transport
-void grpc_chttp2_flowctl_recv_transport_update(
-    grpc_chttp2_transport_flowctl* tfc, uint32_t size) {
-  PRETRACE(tfc, NULL);
-  tfc->remote_window += size;
-  POSTTRACE(tfc, NULL, "t updt recv");
-}
-
-// we have received a WINDOW_UPDATE frame for a stream
-void grpc_chttp2_flowctl_recv_stream_update(grpc_chttp2_transport_flowctl* tfc,
-                                            grpc_chttp2_stream_flowctl* sfc,
-                                            uint32_t size) {
-  PRETRACE(tfc, sfc);
-  sfc->remote_window_delta += size;
-  POSTTRACE(tfc, sfc, "s updt recv");
-}
-
-void grpc_chttp2_flowctl_incoming_bs_update(grpc_chttp2_transport_flowctl* tfc,
-                                            grpc_chttp2_stream_flowctl* sfc,
-                                            size_t max_size_hint,
-                                            size_t have_already) {
-  PRETRACE(tfc, sfc);
+void StreamFlowControl::IncomingByteStreamUpdate(size_t max_size_hint,
+                                                 size_t have_already) {
+  FlowControlTrace trace("app st recv", tfc_, this);
   uint32_t max_recv_bytes;
   uint32_t sent_init_window =
-      tfc->t->settings[GRPC_SENT_SETTINGS]
-                      [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+      tfc_->transport()->settings[GRPC_SENT_SETTINGS]
+                                 [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
 
   /* clamp max recv hint to an allowable size */
   if (max_size_hint >= UINT32_MAX - sent_init_window) {
@@ -363,68 +274,18 @@
 
   /* add some small lookahead to keep pipelines flowing */
   GPR_ASSERT(max_recv_bytes <= UINT32_MAX - sent_init_window);
-  if (sfc->local_window_delta < max_recv_bytes) {
+  if (local_window_delta_ < max_recv_bytes) {
     uint32_t add_max_recv_bytes =
-        (uint32_t)(max_recv_bytes - sfc->local_window_delta);
-    sfc->local_window_delta += add_max_recv_bytes;
+        (uint32_t)(max_recv_bytes - local_window_delta_);
+    local_window_delta_ += add_max_recv_bytes;
   }
-  POSTTRACE(tfc, sfc, "app st recv");
-}
-
-void grpc_chttp2_flowctl_destroy_stream(grpc_chttp2_transport_flowctl* tfc,
-                                        grpc_chttp2_stream_flowctl* sfc) {
-  announced_window_delta_preupdate(tfc, sfc);
-}
-
-// Returns an urgency with which to make an update
-static grpc_chttp2_flowctl_urgency delta_is_significant(
-    const grpc_chttp2_transport_flowctl* tfc, int32_t value,
-    grpc_chttp2_setting_id setting_id) {
-  int64_t delta = (int64_t)value -
-                  (int64_t)tfc->t->settings[GRPC_LOCAL_SETTINGS][setting_id];
-  // TODO(ncteisen): tune this
-  if (delta != 0 && (delta <= -value / 5 || delta >= value / 5)) {
-    return GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE;
-  } else {
-    return GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED;
-  }
-}
-
-// Takes in a target and uses the pid controller to return a stabilized
-// guess at the new bdp.
-static double get_pid_controller_guess(grpc_exec_ctx* exec_ctx,
-                                       grpc_chttp2_transport_flowctl* tfc,
-                                       double target) {
-  grpc_millis now = grpc_exec_ctx_now(exec_ctx);
-  if (!tfc->pid_controller_initialized) {
-    tfc->last_pid_update = now;
-    tfc->pid_controller_initialized = true;
-    grpc_pid_controller_args args;
-    memset(&args, 0, sizeof(args));
-    args.gain_p = 4;
-    args.gain_i = 8;
-    args.gain_d = 0;
-    args.initial_control_value = target;
-    args.min_control_value = -1;
-    args.max_control_value = 25;
-    args.integral_range = 10;
-    grpc_pid_controller_init(&tfc->pid_controller, args);
-    return pow(2, target);
-  }
-  double bdp_error = target - grpc_pid_controller_last(&tfc->pid_controller);
-  double dt = (double)(now - tfc->last_pid_update) * 1e-3;
-  double log2_bdp_guess =
-      grpc_pid_controller_update(&tfc->pid_controller, bdp_error, dt);
-  tfc->last_pid_update = now;
-  return pow(2, log2_bdp_guess);
 }
 
 // Take in a target and modifies it based on the memory pressure of the system
-static double get_target_under_memory_pressure(
-    grpc_chttp2_transport_flowctl* tfc, double target) {
+static double AdjustForMemoryPressure(grpc_resource_quota* quota,
+                                      double target) {
   // do not increase window under heavy memory pressure.
-  double memory_pressure = grpc_resource_quota_get_memory_pressure(
-      grpc_resource_user_quota(grpc_endpoint_get_resource_user(tfc->t->ep)));
+  double memory_pressure = grpc_resource_quota_get_memory_pressure(quota);
   static const double kLowMemPressure = 0.1;
   static const double kZeroTarget = 22;
   static const double kHighMemPressure = 0.8;
@@ -439,78 +300,82 @@
   return target;
 }
 
-grpc_chttp2_flowctl_action grpc_chttp2_flowctl_get_action(
-    grpc_exec_ctx* exec_ctx, grpc_chttp2_transport_flowctl* tfc,
-    grpc_chttp2_stream_flowctl* sfc) {
-  grpc_chttp2_flowctl_action action;
-  memset(&action, 0, sizeof(action));
+double TransportFlowControl::TargetLogBdp() {
+  return AdjustForMemoryPressure(
+      grpc_resource_user_quota(grpc_endpoint_get_resource_user(t_->ep)),
+      1 + log2(bdp_estimator_.EstimateBdp()));
+}
+
+double TransportFlowControl::SmoothLogBdp(grpc_exec_ctx* exec_ctx,
+                                          double value) {
+  grpc_millis now = grpc_exec_ctx_now(exec_ctx);
+  double bdp_error = value - pid_controller_.last_control_value();
+  const double dt = (double)(now - last_pid_update_) * 1e-3;
+  last_pid_update_ = now;
+  return pid_controller_.Update(bdp_error, dt);
+}
+
+FlowControlAction::Urgency TransportFlowControl::DeltaUrgency(
+    int32_t value, grpc_chttp2_setting_id setting_id) {
+  int64_t delta =
+      (int64_t)value - (int64_t)t_->settings[GRPC_LOCAL_SETTINGS][setting_id];
   // TODO(ncteisen): tune this
-  if (sfc != NULL && !sfc->s->read_closed) {
-    uint32_t sent_init_window =
-        tfc->t->settings[GRPC_SENT_SETTINGS]
-                        [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
-    if ((int64_t)sfc->local_window_delta >
-            (int64_t)sfc->announced_window_delta &&
-        (int64_t)sfc->announced_window_delta + sent_init_window <=
-            sent_init_window / 2) {
-      action.send_stream_update = GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY;
-    } else if (sfc->local_window_delta > sfc->announced_window_delta) {
-      action.send_stream_update = GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE;
-    }
+  if (delta != 0 && (delta <= -value / 5 || delta >= value / 5)) {
+    return FlowControlAction::Urgency::QUEUE_UPDATE;
+  } else {
+    return FlowControlAction::Urgency::NO_ACTION_NEEDED;
   }
-  if (tfc->enable_bdp_probe) {
-    action.need_ping =
-        grpc_bdp_estimator_need_ping(exec_ctx, &tfc->bdp_estimator);
+}
 
+FlowControlAction TransportFlowControl::PeriodicUpdate(
+    grpc_exec_ctx* exec_ctx) {
+  FlowControlAction action;
+  if (enable_bdp_probe_) {
     // get bdp estimate and update initial_window accordingly.
-    int64_t estimate = -1;
-    if (grpc_bdp_estimator_get_estimate(&tfc->bdp_estimator, &estimate)) {
-      double target = 1 + log2((double)estimate);
+    // target might change based on how much memory pressure we are under
+    // TODO(ncteisen): experiment with setting target to be huge under low
+    // memory pressure.
+    const double target = pow(2, SmoothLogBdp(exec_ctx, TargetLogBdp()));
 
-      // target might change based on how much memory pressure we are under
-      // TODO(ncteisen): experiment with setting target to be huge under low
-      // memory pressure.
-      target = get_target_under_memory_pressure(tfc, target);
+    // Though initial window 'could' drop to 0, we keep the floor at 128
+    target_initial_window_size_ = (int32_t)GPR_CLAMP(target, 128, INT32_MAX);
 
-      // run our target through the pid controller to stabilize change.
-      // TODO(ncteisen): experiment with other controllers here.
-      double bdp_guess = get_pid_controller_guess(exec_ctx, tfc, target);
-
-      // Though initial window 'could' drop to 0, we keep the floor at 128
-      tfc->target_initial_window_size =
-          (int32_t)GPR_CLAMP(bdp_guess, 128, INT32_MAX);
-
-      grpc_chttp2_flowctl_urgency init_window_update_urgency =
-          delta_is_significant(tfc, tfc->target_initial_window_size,
-                               GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE);
-      if (init_window_update_urgency != GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED) {
-        action.send_setting_update = init_window_update_urgency;
-        action.initial_window_size = (uint32_t)tfc->target_initial_window_size;
-      }
-    }
+    action.set_send_initial_window_update(
+        DeltaUrgency(target_initial_window_size_,
+                     GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE),
+        target_initial_window_size_);
 
     // get bandwidth estimate and update max_frame accordingly.
-    double bw_dbl = -1;
-    if (grpc_bdp_estimator_get_bw(&tfc->bdp_estimator, &bw_dbl)) {
-      // we target the max of BDP or bandwidth in microseconds.
-      int32_t frame_size = (int32_t)GPR_CLAMP(
-          GPR_MAX((int32_t)GPR_CLAMP(bw_dbl, 0, INT_MAX) / 1000,
-                  tfc->target_initial_window_size),
-          16384, 16777215);
-      grpc_chttp2_flowctl_urgency frame_size_urgency = delta_is_significant(
-          tfc, frame_size, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE);
-      if (frame_size_urgency != GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED) {
-        if (frame_size_urgency > action.send_setting_update) {
-          action.send_setting_update = frame_size_urgency;
-        }
-        action.max_frame_size = (uint32_t)frame_size;
-      }
+    double bw_dbl = bdp_estimator_.EstimateBandwidth();
+    // we target the max of BDP or bandwidth in microseconds.
+    int32_t frame_size = (int32_t)GPR_CLAMP(
+        GPR_MAX((int32_t)GPR_CLAMP(bw_dbl, 0, INT_MAX) / 1000,
+                target_initial_window_size_),
+        16384, 16777215);
+    action.set_send_max_frame_size_update(
+        DeltaUrgency(frame_size, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE),
+        frame_size);
+  }
+  return UpdateAction(action);
+}
+
+FlowControlAction StreamFlowControl::UpdateAction(FlowControlAction action) {
+  // TODO(ncteisen): tune this
+  if (!s_->read_closed) {
+    uint32_t sent_init_window =
+        tfc_->transport()->settings[GRPC_SENT_SETTINGS]
+                                   [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+    if (local_window_delta_ > announced_window_delta_ &&
+        announced_window_delta_ + sent_init_window <= sent_init_window / 2) {
+      action.set_send_stream_update(
+          FlowControlAction::Urgency::UPDATE_IMMEDIATELY);
+    } else if (local_window_delta_ > announced_window_delta_) {
+      action.set_send_stream_update(FlowControlAction::Urgency::QUEUE_UPDATE);
     }
   }
-  uint32_t target_announced_window = grpc_chttp2_target_announced_window(tfc);
-  if (tfc->announced_window < target_announced_window / 2) {
-    action.send_transport_update = GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY;
-  }
-  TRACEACTION(tfc, action);
+
   return action;
 }
+
+}  // namespace chttp2
+}  // namespace grpc_core
diff --git a/src/core/ext/transport/chttp2/transport/flow_control.h b/src/core/ext/transport/chttp2/transport/flow_control.h
new file mode 100644
index 0000000..d5107d4
--- /dev/null
+++ b/src/core/ext/transport/chttp2/transport/flow_control.h
@@ -0,0 +1,328 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FLOW_CONTROL_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FLOW_CONTROL_H
+
+#include <stdint.h>
+
+#include <grpc/support/useful.h>
+#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
+#include "src/core/lib/support/manual_constructor.h"
+#include "src/core/lib/transport/bdp_estimator.h"
+#include "src/core/lib/transport/pid_controller.h"
+
+struct grpc_chttp2_transport;
+struct grpc_chttp2_stream;
+
+extern "C" grpc_tracer_flag grpc_flowctl_trace;
+
+namespace grpc_core {
+namespace chttp2 {
+
+static constexpr uint32_t kDefaultWindow = 65535;
+
+class TransportFlowControl;
+class StreamFlowControl;
+
+class FlowControlAction {
+ public:
+  enum class Urgency : uint8_t {
+    // Nothing to be done.
+    NO_ACTION_NEEDED = 0,
+    // Initiate a write to update the initial window immediately.
+    UPDATE_IMMEDIATELY,
+    // Push the flow control update into a send buffer, to be sent
+    // out the next time a write is initiated.
+    QUEUE_UPDATE,
+  };
+
+  Urgency send_stream_update() const { return send_stream_update_; }
+  Urgency send_transport_update() const { return send_transport_update_; }
+  Urgency send_initial_window_update() const {
+    return send_initial_window_update_;
+  }
+  Urgency send_max_frame_size_update() const {
+    return send_max_frame_size_update_;
+  }
+  uint32_t initial_window_size() const { return initial_window_size_; }
+  uint32_t max_frame_size() const { return max_frame_size_; }
+
+  FlowControlAction& set_send_stream_update(Urgency u) {
+    send_stream_update_ = u;
+    return *this;
+  }
+  FlowControlAction& set_send_transport_update(Urgency u) {
+    send_transport_update_ = u;
+    return *this;
+  }
+  FlowControlAction& set_send_initial_window_update(Urgency u,
+                                                    uint32_t update) {
+    send_initial_window_update_ = u;
+    initial_window_size_ = update;
+    return *this;
+  }
+  FlowControlAction& set_send_max_frame_size_update(Urgency u,
+                                                    uint32_t update) {
+    send_max_frame_size_update_ = u;
+    max_frame_size_ = update;
+    return *this;
+  }
+
+  static const char* UrgencyString(Urgency u);
+  void Trace(grpc_chttp2_transport* t) const;
+
+ private:
+  Urgency send_stream_update_ = Urgency::NO_ACTION_NEEDED;
+  Urgency send_transport_update_ = Urgency::NO_ACTION_NEEDED;
+  Urgency send_initial_window_update_ = Urgency::NO_ACTION_NEEDED;
+  Urgency send_max_frame_size_update_ = Urgency::NO_ACTION_NEEDED;
+  uint32_t initial_window_size_ = 0;
+  uint32_t max_frame_size_ = 0;
+};
+
+class FlowControlTrace {
+ public:
+  FlowControlTrace(const char* reason, TransportFlowControl* tfc,
+                   StreamFlowControl* sfc) {
+    if (enabled_) Init(reason, tfc, sfc);
+  }
+
+  ~FlowControlTrace() {
+    if (enabled_) Finish();
+  }
+
+ private:
+  void Init(const char* reason, TransportFlowControl* tfc,
+            StreamFlowControl* sfc);
+  void Finish();
+
+  const bool enabled_ = GRPC_TRACER_ON(grpc_flowctl_trace);
+
+  TransportFlowControl* tfc_;
+  StreamFlowControl* sfc_;
+  const char* reason_;
+  int64_t remote_window_;
+  int64_t target_window_;
+  int64_t announced_window_;
+  int64_t remote_window_delta_;
+  int64_t local_window_delta_;
+  int64_t announced_window_delta_;
+};
+
+class TransportFlowControl {
+ public:
+  TransportFlowControl(grpc_exec_ctx* exec_ctx, const grpc_chttp2_transport* t,
+                       bool enable_bdp_probe);
+  ~TransportFlowControl() {}
+
+  bool bdp_probe() const { return enable_bdp_probe_; }
+
+  // returns an announce if we should send a transport update to our peer,
+  // else returns zero; writing_anyway indicates if a write would happen
+  // regardless of the send - if it is false and this function returns non-zero,
+  // this announce will cause a write to occur
+  uint32_t MaybeSendUpdate(bool writing_anyway);
+
+  // Reads the flow control data and returns and actionable struct that will
+  // tell chttp2 exactly what it needs to do
+  FlowControlAction MakeAction() { return UpdateAction(FlowControlAction()); }
+
+  // Call periodically (at a low-ish rate, 100ms - 10s makes sense)
+  // to perform more complex flow control calculations and return an action
+  // to let chttp2 change its parameters
+  FlowControlAction PeriodicUpdate(grpc_exec_ctx* exec_ctx);
+
+  void StreamSentData(int64_t size) { remote_window_ -= size; }
+
+  grpc_error* ValidateRecvData(int64_t incoming_frame_size);
+  void CommitRecvData(int64_t incoming_frame_size) {
+    announced_window_ -= incoming_frame_size;
+  }
+
+  grpc_error* RecvData(int64_t incoming_frame_size) {
+    FlowControlTrace trace("  data recv", this, nullptr);
+    grpc_error* error = ValidateRecvData(incoming_frame_size);
+    if (error != GRPC_ERROR_NONE) return error;
+    CommitRecvData(incoming_frame_size);
+    return GRPC_ERROR_NONE;
+  }
+
+  // we have received a WINDOW_UPDATE frame for a transport
+  void RecvUpdate(uint32_t size) {
+    FlowControlTrace trace("t updt recv", this, nullptr);
+    remote_window_ += size;
+  }
+
+  int64_t remote_window() const { return remote_window_; }
+  int64_t target_window() const {
+    return (uint32_t)GPR_MIN((int64_t)((1u << 31) - 1),
+                             announced_stream_total_over_incoming_window_ +
+                                 target_initial_window_size_);
+  }
+  int64_t announced_window() const { return announced_window_; }
+
+  const grpc_chttp2_transport* transport() const { return t_; }
+
+  void PreUpdateAnnouncedWindowOverIncomingWindow(int64_t delta) {
+    if (delta > 0) {
+      announced_stream_total_over_incoming_window_ -= delta;
+    } else {
+      announced_stream_total_under_incoming_window_ += -delta;
+    }
+  }
+
+  void PostUpdateAnnouncedWindowOverIncomingWindow(int64_t delta) {
+    if (delta > 0) {
+      announced_stream_total_over_incoming_window_ += delta;
+    } else {
+      announced_stream_total_under_incoming_window_ -= -delta;
+    }
+  }
+
+  BdpEstimator* bdp_estimator() { return &bdp_estimator_; }
+
+  void TestOnlyForceHugeWindow() {
+    announced_window_ = 1024 * 1024 * 1024;
+    remote_window_ = 1024 * 1024 * 1024;
+  }
+
+ private:
+  double TargetLogBdp();
+  double SmoothLogBdp(grpc_exec_ctx* exec_ctx, double value);
+  FlowControlAction::Urgency DeltaUrgency(int32_t value,
+                                          grpc_chttp2_setting_id setting_id);
+
+  FlowControlAction UpdateAction(FlowControlAction action) {
+    if (announced_window_ < target_window() / 2) {
+      action.set_send_transport_update(
+          FlowControlAction::Urgency::UPDATE_IMMEDIATELY);
+    }
+    return action;
+  }
+
+  const grpc_chttp2_transport* const t_;
+
+  /** Our bookkeeping for the remote peer's available window */
+  int64_t remote_window_ = kDefaultWindow;
+
+  /** calculating what we should give for local 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 announced_stream_total_over_incoming_window_ = 0;
+  int64_t announced_stream_total_under_incoming_window_ = 0;
+
+  /** This is out window according to what we have sent to our remote peer. The
+   * difference between this and target window is what we use to decide when
+   * to send WINDOW_UPDATE frames. */
+  int64_t announced_window_ = kDefaultWindow;
+
+  int32_t target_initial_window_size_ = kDefaultWindow;
+
+  /** should we probe bdp? */
+  const bool enable_bdp_probe_;
+
+  /* bdp estimation */
+  grpc_core::BdpEstimator bdp_estimator_;
+
+  /* pid controller */
+  grpc_core::PidController pid_controller_;
+  grpc_millis last_pid_update_ = 0;
+};
+
+class StreamFlowControl {
+ public:
+  StreamFlowControl(TransportFlowControl* tfc, const grpc_chttp2_stream* s);
+  ~StreamFlowControl() {
+    tfc_->PreUpdateAnnouncedWindowOverIncomingWindow(announced_window_delta_);
+  }
+
+  FlowControlAction UpdateAction(FlowControlAction action);
+  FlowControlAction MakeAction() { return UpdateAction(tfc_->MakeAction()); }
+
+  // we have sent data on the wire, we must track this in our bookkeeping for
+  // the remote peer's flow control.
+  void SentData(int64_t outgoing_frame_size) {
+    FlowControlTrace tracer("  data sent", tfc_, this);
+    tfc_->StreamSentData(outgoing_frame_size);
+    remote_window_delta_ -= outgoing_frame_size;
+  }
+
+  // we have received data from the wire
+  grpc_error* RecvData(int64_t incoming_frame_size);
+
+  // returns an announce if we should send a stream update to our peer, else
+  // returns zero
+  uint32_t MaybeSendUpdate();
+
+  // we have received a WINDOW_UPDATE frame for a stream
+  void RecvUpdate(uint32_t size) {
+    FlowControlTrace trace("s updt recv", tfc_, this);
+    remote_window_delta_ += size;
+  }
+
+  // the application is asking for a certain amount of bytes
+  void IncomingByteStreamUpdate(size_t max_size_hint, size_t have_already);
+
+  int64_t remote_window_delta() const { return remote_window_delta_; }
+  int64_t local_window_delta() const { return local_window_delta_; }
+  int64_t announced_window_delta() const { return announced_window_delta_; }
+
+  const grpc_chttp2_stream* stream() const { return s_; }
+
+  void TestOnlyForceHugeWindow() {
+    announced_window_delta_ = 1024 * 1024 * 1024;
+    local_window_delta_ = 1024 * 1024 * 1024;
+    remote_window_delta_ = 1024 * 1024 * 1024;
+  }
+
+ private:
+  TransportFlowControl* const tfc_;
+  const grpc_chttp2_stream* const s_;
+
+  void UpdateAnnouncedWindowDelta(TransportFlowControl* tfc, int64_t change) {
+    tfc->PreUpdateAnnouncedWindowOverIncomingWindow(announced_window_delta_);
+    announced_window_delta_ += change;
+    tfc->PostUpdateAnnouncedWindowOverIncomingWindow(announced_window_delta_);
+  }
+
+  /** window available for us to send to peer, over or under the initial
+   * window
+   * size of the transport... ie:
+   * remote_window = remote_window_delta + transport.initial_window_size */
+  int64_t remote_window_delta_ = 0;
+
+  /** window available for peer to send to us (as a delta on
+   * transport.initial_window_size)
+   * local_window = local_window_delta + transport.initial_window_size */
+  int64_t local_window_delta_ = 0;
+
+  /** window available for peer to send to us over this stream that we have
+   * announced to the peer */
+  int64_t announced_window_delta_ = 0;
+};
+
+}  // namespace chttp2
+}  // namespace grpc_core
+
+#endif
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.h b/src/core/ext/transport/chttp2/transport/frame_data.h
index 2df99cc..81ec536 100644
--- a/src/core/ext/transport/chttp2/transport/frame_data.h
+++ b/src/core/ext/transport/chttp2/transport/frame_data.h
@@ -88,4 +88,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_DATA_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.h b/src/core/ext/transport/chttp2/transport/frame_goaway.h
index ce6f18b..7b3aa45 100644
--- a/src/core/ext/transport/chttp2/transport/frame_goaway.h
+++ b/src/core/ext/transport/chttp2/transport/frame_goaway.h
@@ -68,4 +68,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_GOAWAY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_GOAWAY_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.h b/src/core/ext/transport/chttp2/transport/frame_ping.h
index 91f16f0..ffc2f0c 100644
--- a/src/core/ext/transport/chttp2/transport/frame_ping.h
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.h
@@ -49,4 +49,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
index bdca064..102ffdb 100644
--- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
@@ -48,4 +48,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.cc b/src/core/ext/transport/chttp2/transport/frame_settings.cc
index 2995bf7..db0245b 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.cc
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.cc
@@ -202,13 +202,13 @@
           }
           if (id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
               parser->incoming_settings[id] != parser->value) {
-            t->flow_control.initial_window_update +=
+            t->initial_window_update +=
                 (int64_t)parser->value - parser->incoming_settings[id];
             if (GRPC_TRACER_ON(grpc_http_trace) ||
                 GRPC_TRACER_ON(grpc_flowctl_trace)) {
               gpr_log(GPR_DEBUG, "%p[%s] adding %d for initial_window change",
                       t, t->is_client ? "cli" : "svr",
-                      (int)t->flow_control.initial_window_update);
+                      (int)t->initial_window_update);
             }
           }
           parser->incoming_settings[id] = parser->value;
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.h b/src/core/ext/transport/chttp2/transport/frame_settings.h
index f0793f0..3364da1 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.h
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.h
@@ -66,4 +66,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H */
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.cc b/src/core/ext/transport/chttp2/transport/frame_window_update.cc
index c9ab8d1..15eaf59 100644
--- a/src/core/ext/transport/chttp2/transport/frame_window_update.cc
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.cc
@@ -96,8 +96,7 @@
 
     if (t->incoming_stream_id != 0) {
       if (s != NULL) {
-        grpc_chttp2_flowctl_recv_stream_update(
-            &t->flow_control, &s->flow_control, received_update);
+        s->flow_control->RecvUpdate(received_update);
         if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) {
           grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
           grpc_chttp2_initiate_write(
@@ -106,10 +105,9 @@
         }
       }
     } else {
-      bool was_zero = t->flow_control.remote_window <= 0;
-      grpc_chttp2_flowctl_recv_transport_update(&t->flow_control,
-                                                received_update);
-      bool is_zero = t->flow_control.remote_window <= 0;
+      bool was_zero = t->flow_control->remote_window() <= 0;
+      t->flow_control->RecvUpdate(received_update);
+      bool is_zero = t->flow_control->remote_window() <= 0;
       if (was_zero && !is_zero) {
         grpc_chttp2_initiate_write(
             exec_ctx, t,
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.h b/src/core/ext/transport/chttp2/transport/frame_window_update.h
index 29cf0cc..400f9f5 100644
--- a/src/core/ext/transport/chttp2/transport/frame_window_update.h
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.h
@@ -47,4 +47,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
index 17b8c4a..0ea50e3 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
@@ -178,24 +178,19 @@
   c->table_elems--;
 }
 
-/* add an element to the decoder table */
-static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
-                     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);
+// Reserve space in table for the new element, evict entries if needed.
+// Return the new index of the element. Return 0 to indicate not adding to
+// table.
+static uint32_t prepare_space_for_new_elem(grpc_chttp2_hpack_compressor *c,
+                                           size_t elem_size) {
   uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
-  size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
-
   GPR_ASSERT(elem_size < 65536);
 
   if (elem_size > c->max_table_size) {
     while (c->table_size > 0) {
       evict_entry(c);
     }
-    return;
+    return 0;
   }
 
   /* Reserve space for this element in the remote table: if this overflows
@@ -209,37 +204,26 @@
   c->table_size = (uint16_t)(c->table_size + elem_size);
   c->table_elems++;
 
-  /* Store this element into {entries,indices}_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 (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 (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 (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;
-  } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] <
-             c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) {
-    /* not there: replace oldest */
-    GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[HASH_FRAGMENT_2(elem_hash)]);
-    c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
-    c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
-  } else {
-    /* not there: replace oldest */
-    GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[HASH_FRAGMENT_3(elem_hash)]);
-    c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
-    c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+  return new_index;
+}
+
+/* dummy function */
+static void add_nothing(grpc_exec_ctx *exec_ctx,
+                        grpc_chttp2_hpack_compressor *c, grpc_mdelem elem,
+                        size_t elem_size) {}
+
+// Add a key to the dynamic table. Both key and value will be added to table at
+// the decoder.
+static void add_key_with_index(grpc_exec_ctx *exec_ctx,
+                               grpc_chttp2_hpack_compressor *c,
+                               grpc_mdelem elem, uint32_t new_index) {
+  if (new_index == 0) {
+    return;
   }
 
-  /* do exactly the same for the key (so we can find by that again too) */
+  uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
 
+  /* Store the key into {entries,indices}_keys */
   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;
@@ -272,6 +256,63 @@
   }
 }
 
+/* add an element to the decoder table */
+static void add_elem_with_index(grpc_exec_ctx *exec_ctx,
+                                grpc_chttp2_hpack_compressor *c,
+                                grpc_mdelem elem, uint32_t new_index) {
+  if (new_index == 0) {
+    return;
+  }
+  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);
+
+  /* Store this element into {entries,indices}_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 (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 (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 (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;
+  } else if (c->indices_elems[HASH_FRAGMENT_2(elem_hash)] <
+             c->indices_elems[HASH_FRAGMENT_3(elem_hash)]) {
+    /* not there: replace oldest */
+    GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[HASH_FRAGMENT_2(elem_hash)]);
+    c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
+    c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
+  } else {
+    /* not there: replace oldest */
+    GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[HASH_FRAGMENT_3(elem_hash)]);
+    c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
+    c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
+  }
+
+  add_key_with_index(exec_ctx, c, elem, new_index);
+}
+
+static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
+                     grpc_mdelem elem, size_t elem_size) {
+  uint32_t new_index = prepare_space_for_new_elem(c, elem_size);
+  add_elem_with_index(exec_ctx, c, elem, new_index);
+}
+
+static void add_key(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
+                    grpc_mdelem elem, size_t elem_size) {
+  uint32_t new_index = prepare_space_for_new_elem(c, elem_size);
+  add_key_with_index(exec_ctx, c, elem, new_index);
+}
+
 static void emit_indexed(grpc_exec_ctx *exec_ctx,
                          grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
                          framer_state *st) {
@@ -363,7 +404,9 @@
 
 static void emit_lithdr_incidx_v(grpc_exec_ctx *exec_ctx,
                                  grpc_chttp2_hpack_compressor *c,
-                                 grpc_mdelem elem, framer_state *st) {
+                                 uint32_t unused_index, grpc_mdelem elem,
+                                 framer_state *st) {
+  GPR_ASSERT(unused_index == 0);
   GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V(exec_ctx);
   GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(exec_ctx);
   uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
@@ -385,7 +428,9 @@
 
 static void emit_lithdr_noidx_v(grpc_exec_ctx *exec_ctx,
                                 grpc_chttp2_hpack_compressor *c,
-                                grpc_mdelem elem, framer_state *st) {
+                                uint32_t unused_index, grpc_mdelem elem,
+                                framer_state *st) {
+  GPR_ASSERT(unused_index == 0);
   GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V(exec_ctx);
   GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(exec_ctx);
   uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
@@ -430,9 +475,14 @@
         "Reserved header (colon-prefixed) happening after regular ones.");
   }
 
-  if (GRPC_TRACER_ON(grpc_http_trace) && !GRPC_MDELEM_IS_INTERNED(elem)) {
+  if (GRPC_TRACER_ON(grpc_http_trace)) {
     char *k = grpc_slice_to_c_string(GRPC_MDKEY(elem));
-    char *v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
+    char *v = NULL;
+    if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
+      v = grpc_dump_slice(GRPC_MDVALUE(elem), GPR_DUMP_HEX);
+    } else {
+      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",
@@ -442,64 +492,70 @@
     gpr_free(k);
     gpr_free(v);
   }
-  if (!GRPC_MDELEM_IS_INTERNED(elem)) {
-    emit_lithdr_noidx_v(exec_ctx, c, elem, st);
+
+  bool elem_interned = GRPC_MDELEM_IS_INTERNED(elem);
+  bool key_interned = elem_interned || grpc_slice_is_interned(GRPC_MDKEY(elem));
+
+  // Key is not interned, emit literals.
+  if (!key_interned) {
+    emit_lithdr_noidx_v(exec_ctx, c, 0, elem, st);
     return;
   }
 
-  uint32_t key_hash;
-  uint32_t value_hash;
-  uint32_t elem_hash;
-  size_t decoder_space_usage;
+  uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
+  uint32_t elem_hash = 0;
+
+  if (elem_interned) {
+    uint32_t 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 (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(exec_ctx, c,
+                   dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]), st);
+      return;
+    }
+
+    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(exec_ctx, c,
+                   dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]), st);
+      return;
+    }
+  }
+
   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 (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(exec_ctx, c,
-                 dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]), st);
-    return;
-  }
-
-  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(exec_ctx, c,
-                 dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]), st);
-    return;
-  }
 
   /* should this elem be in the table? */
-  decoder_space_usage = grpc_mdelem_get_size_in_hpack_table(elem);
-  should_add_elem = decoder_space_usage < MAX_DECODER_SPACE_USAGE &&
-                    c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
-                        c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
+  size_t decoder_space_usage =
+      grpc_mdelem_get_size_in_hpack_table(elem, st->use_true_binary_metadata);
+  bool should_add_elem = elem_interned &&
+                         decoder_space_usage < MAX_DECODER_SPACE_USAGE &&
+                         c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
+                             c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
+  void (*maybe_add)(grpc_exec_ctx *, grpc_chttp2_hpack_compressor *,
+                    grpc_mdelem, size_t) =
+      should_add_elem ? add_elem : add_nothing;
+  void (*emit)(grpc_exec_ctx *, grpc_chttp2_hpack_compressor *, uint32_t,
+               grpc_mdelem, framer_state *) =
+      should_add_elem ? emit_lithdr_incidx : emit_lithdr_noidx;
 
   /* no hits for the elem... maybe there's a key? */
-
   indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
   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) {
-      emit_lithdr_incidx(exec_ctx, c, dynidx(c, indices_key), elem, st);
-      add_elem(exec_ctx, c, elem);
-      return;
-    } else {
-      emit_lithdr_noidx(exec_ctx, c, dynidx(c, indices_key), elem, st);
-      return;
-    }
-    GPR_UNREACHABLE_CODE(return );
+    emit(exec_ctx, c, dynidx(c, indices_key), elem, st);
+    maybe_add(exec_ctx, c, elem, decoder_space_usage);
+    return;
   }
 
   indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
@@ -507,28 +563,20 @@
                     GRPC_MDKEY(elem)) &&
       indices_key > c->tail_remote_index) {
     /* HIT: key (first cuckoo hash) */
-    if (should_add_elem) {
-      emit_lithdr_incidx(exec_ctx, c, dynidx(c, indices_key), elem, st);
-      add_elem(exec_ctx, c, elem);
-      return;
-    } else {
-      emit_lithdr_noidx(exec_ctx, c, dynidx(c, indices_key), elem, st);
-      return;
-    }
-    GPR_UNREACHABLE_CODE(return );
+    emit(exec_ctx, c, dynidx(c, indices_key), elem, st);
+    maybe_add(exec_ctx, c, elem, decoder_space_usage);
+    return;
   }
 
   /* no elem, key in the table... fall back to literal emission */
-
-  if (should_add_elem) {
-    emit_lithdr_incidx_v(exec_ctx, c, elem, st);
-    add_elem(exec_ctx, c, elem);
-    return;
-  } else {
-    emit_lithdr_noidx_v(exec_ctx, c, elem, st);
-    return;
-  }
-  GPR_UNREACHABLE_CODE(return );
+  bool should_add_key =
+      !elem_interned && decoder_space_usage < MAX_DECODER_SPACE_USAGE;
+  emit = (should_add_elem || should_add_key) ? emit_lithdr_incidx_v
+                                             : emit_lithdr_noidx_v;
+  maybe_add =
+      should_add_elem ? add_elem : (should_add_key ? add_key : add_nothing);
+  emit(exec_ctx, c, 0, elem, st);
+  maybe_add(exec_ctx, c, elem, decoder_space_usage);
 }
 
 #define STRLEN_LIT(x) (sizeof(x) - 1)
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
index dc28b55..16316b6 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
@@ -99,4 +99,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_H */
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/src/core/ext/transport/chttp2/transport/hpack_parser.cc
index 3d1df19..7c17229 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.cc
@@ -33,6 +33,7 @@
 #include "src/core/lib/debug/stats.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/http2_errors.h"
 
@@ -650,9 +651,14 @@
 /* emission helpers */
 static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p,
                           grpc_mdelem md, int add_to_table) {
-  if (GRPC_TRACER_ON(grpc_http_trace) && !GRPC_MDELEM_IS_INTERNED(md)) {
+  if (GRPC_TRACER_ON(grpc_http_trace)) {
     char *k = grpc_slice_to_c_string(GRPC_MDKEY(md));
-    char *v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+    char *v = NULL;
+    if (grpc_is_binary_header(GRPC_MDKEY(md))) {
+      v = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX);
+    } else {
+      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",
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.h b/src/core/ext/transport/chttp2/transport/hpack_parser.h
index 6c36ebd..5201417 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.h
@@ -119,4 +119,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H */
diff --git a/src/core/ext/transport/chttp2/transport/http2_settings.h b/src/core/ext/transport/chttp2/transport/http2_settings.h
index 01e80b8..0f76106 100644
--- a/src/core/ext/transport/chttp2/transport/http2_settings.h
+++ b/src/core/ext/transport/chttp2/transport/http2_settings.h
@@ -64,4 +64,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H */
diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/src/core/ext/transport/chttp2/transport/incoming_metadata.h
index 995e800..a0e01f2 100644
--- a/src/core/ext/transport/chttp2/transport/incoming_metadata.h
+++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.h
@@ -53,4 +53,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INCOMING_METADATA_H */
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
index b51854f..9e0796e 100644
--- a/src/core/ext/transport/chttp2/transport/internal.h
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include <stdbool.h>
 
+#include "src/core/ext/transport/chttp2/transport/flow_control.h"
 #include "src/core/ext/transport/chttp2/transport/frame.h"
 #include "src/core/ext/transport/chttp2/transport/frame_data.h"
 #include "src/core/ext/transport/chttp2/transport/frame_goaway.h"
@@ -37,9 +38,8 @@
 #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/support/manual_constructor.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"
 
 #ifdef __cplusplus
@@ -237,48 +237,6 @@
   GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED,
 } grpc_chttp2_keepalive_state;
 
-typedef struct {
-  /** initial window change. This is tracked as we parse settings frames from
-   * the remote peer. If there is a positive delta, then we will make all
-   * streams readable since they may have become unstalled */
-  int64_t initial_window_update;
-
-  /** Our bookkeeping for the remote peer's available window */
-  int64_t remote_window;
-
-  /** calculating what we should give for local 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 announced_stream_total_over_incoming_window;
-  int64_t announced_stream_total_under_incoming_window;
-
-  /** This is out window according to what we have sent to our remote peer. The
-   * difference between this and target window is what we use to decide when
-   * to send WINDOW_UPDATE frames. */
-  int64_t announced_window;
-
-  int32_t target_initial_window_size;
-
-  /** should we probe bdp? */
-  bool enable_bdp_probe;
-
-  /* bdp estimation */
-  grpc_bdp_estimator bdp_estimator;
-
-  /* pid controller */
-  bool pid_controller_initialized;
-  grpc_pid_controller pid_controller;
-  grpc_millis last_pid_update;
-
-  // pointer back to transport for tracing
-  const grpc_chttp2_transport *t;
-} grpc_chttp2_transport_flowctl;
-
 struct grpc_chttp2_transport {
   grpc_transport base; /* must be first */
   gpr_refcount refs;
@@ -297,7 +255,7 @@
   /** is the transport destroying itself? */
   uint8_t destroying;
   /** has the upper layer closed the transport? */
-  uint8_t closed;
+  grpc_error *closed_with_error;
 
   /** is there a read request to the endpoint outstanding? */
   uint8_t endpoint_reading;
@@ -339,7 +297,7 @@
   /** hpack encoding */
   grpc_chttp2_hpack_compressor hpack_compressor;
   /** is this a client? */
-  uint8_t is_client;
+  bool is_client;
 
   /** data to write next write */
   grpc_slice_buffer qbuf;
@@ -349,14 +307,14 @@
   uint32_t write_buffer_size;
 
   /** have we seen a goaway */
-  uint8_t seen_goaway;
+  bool seen_goaway;
   /** have we sent a goaway */
   grpc_chttp2_sent_goaway_state sent_goaway_state;
 
   /** are the local settings dirty and need to be sent? */
-  uint8_t dirtied_local_settings;
+  bool dirtied_local_settings;
   /** have local settings been sent? */
-  uint8_t sent_local_settings;
+  bool sent_local_settings;
   /** bitmask of setting indexes to send out */
   uint32_t force_send_settings;
   /** settings values */
@@ -394,7 +352,12 @@
   /** parser for goaway frames */
   grpc_chttp2_goaway_parser goaway_parser;
 
-  grpc_chttp2_transport_flowctl flow_control;
+  grpc_core::ManualConstructor<grpc_core::chttp2::TransportFlowControl>
+      flow_control;
+  /** initial window change. This is tracked as we parse settings frames from
+   * the remote peer. If there is a positive delta, then we will make all
+   * streams readable since they may have become unstalled */
+  int64_t initial_window_update = 0;
 
   /* deframing */
   grpc_chttp2_deframe_transport_state deframe_state;
@@ -421,6 +384,7 @@
   grpc_chttp2_write_cb *write_cb_pool;
 
   /* bdp estimator */
+  grpc_closure next_bdp_ping_timer_expired_locked;
   grpc_closure start_bdp_ping_locked;
   grpc_closure finish_bdp_ping_locked;
 
@@ -441,6 +405,10 @@
   /** destructive cleanup closure */
   grpc_closure destructive_reclaimer_locked;
 
+  /* next bdp ping timer */
+  bool have_next_bdp_ping_timer;
+  grpc_timer next_bdp_ping_timer;
+
   /* keep-alive ping support */
   /** Closure to initialize a keepalive ping */
   grpc_closure init_keepalive_ping_locked;
@@ -471,25 +439,6 @@
   GPRC_METADATA_PUBLISHED_AT_CLOSE
 } grpc_published_metadata_method;
 
-typedef struct {
-  /** window available for us to send to peer, over or under the initial window
-   * size of the transport... ie:
-   * remote_window = remote_window_delta + transport.initial_window_size */
-  int64_t remote_window_delta;
-
-  /** window available for peer to send to us (as a delta on
-   * transport.initial_window_size)
-   * local_window = local_window_delta + transport.initial_window_size */
-  int64_t local_window_delta;
-
-  /** window available for peer to send to us over this stream that we have
-   * announced to the peer */
-  int64_t announced_window_delta;
-
-  // read only pointer back to stream for data
-  const grpc_chttp2_stream *s;
-} grpc_chttp2_stream_flowctl;
-
 struct grpc_chttp2_stream {
   grpc_chttp2_transport *t;
   grpc_stream_refcount *refcount;
@@ -583,7 +532,8 @@
   bool sent_initial_metadata;
   bool sent_trailing_metadata;
 
-  grpc_chttp2_stream_flowctl flow_control;
+  grpc_core::ManualConstructor<grpc_core::chttp2::StreamFlowControl>
+      flow_control;
 
   grpc_slice_buffer flow_controlled_buffer;
 
@@ -657,8 +607,8 @@
     returns non-zero if there was a stream available */
 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_remove_writable_stream(grpc_chttp2_transport *t,
+                                             grpc_chttp2_stream *s);
 
 bool grpc_chttp2_list_add_writing_stream(grpc_chttp2_transport *t,
                                          grpc_chttp2_stream *s);
@@ -694,74 +644,10 @@
 
 /********* Flow Control ***************/
 
-// we have sent data on the wire
-void grpc_chttp2_flowctl_sent_data(grpc_chttp2_transport_flowctl *tfc,
-                                   grpc_chttp2_stream_flowctl *sfc,
-                                   int64_t size);
-
-// we have received data from the wire
-grpc_error *grpc_chttp2_flowctl_recv_data(grpc_chttp2_transport_flowctl *tfc,
-                                          grpc_chttp2_stream_flowctl *sfc,
-                                          int64_t incoming_frame_size);
-
-// returns an announce if we should send a transport update to our peer,
-// else returns zero
-uint32_t grpc_chttp2_flowctl_maybe_send_transport_update(
-    grpc_chttp2_transport_flowctl *tfc, bool writing_anyway);
-
-// returns an announce if we should send a stream update to our peer, else
-// returns zero
-uint32_t grpc_chttp2_flowctl_maybe_send_stream_update(
-    grpc_chttp2_transport_flowctl *tfc, grpc_chttp2_stream_flowctl *sfc);
-
-// we have received a WINDOW_UPDATE frame for a transport
-void grpc_chttp2_flowctl_recv_transport_update(
-    grpc_chttp2_transport_flowctl *tfc, uint32_t size);
-
-// we have received a WINDOW_UPDATE frame for a stream
-void grpc_chttp2_flowctl_recv_stream_update(grpc_chttp2_transport_flowctl *tfc,
-                                            grpc_chttp2_stream_flowctl *sfc,
-                                            uint32_t size);
-
-// the application is asking for a certain amount of bytes
-void grpc_chttp2_flowctl_incoming_bs_update(grpc_chttp2_transport_flowctl *tfc,
-                                            grpc_chttp2_stream_flowctl *sfc,
-                                            size_t max_size_hint,
-                                            size_t have_already);
-
-void grpc_chttp2_flowctl_destroy_stream(grpc_chttp2_transport_flowctl *tfc,
-                                        grpc_chttp2_stream_flowctl *sfc);
-
-typedef enum {
-  // Nothing to be done.
-  GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED = 0,
-  // Initiate a write to update the initial window immediately.
-  GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY,
-  // Push the flow control update into a send buffer, to be sent
-  // out the next time a write is initiated.
-  GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE,
-} grpc_chttp2_flowctl_urgency;
-
-typedef struct {
-  grpc_chttp2_flowctl_urgency send_stream_update;
-  grpc_chttp2_flowctl_urgency send_transport_update;
-  grpc_chttp2_flowctl_urgency send_setting_update;
-  uint32_t initial_window_size;
-  uint32_t max_frame_size;
-  bool need_ping;
-} grpc_chttp2_flowctl_action;
-
-// Reads the flow control data and returns and actionable struct that will tell
-// chttp2 exactly what it needs to do
-grpc_chttp2_flowctl_action grpc_chttp2_flowctl_get_action(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_flowctl *tfc,
-    grpc_chttp2_stream_flowctl *sfc);
-
 // Takes in a flow control action and performs all the needed operations.
-void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
-                                       grpc_chttp2_flowctl_action action,
-                                       grpc_chttp2_transport *t,
-                                       grpc_chttp2_stream *s);
+void grpc_chttp2_act_on_flowctl_action(
+    grpc_exec_ctx *exec_ctx, const grpc_core::chttp2::FlowControlAction &action,
+    grpc_chttp2_transport *t, grpc_chttp2_stream *s);
 
 /********* End of Flow Control ***************/
 
@@ -795,16 +681,6 @@
 extern grpc_tracer_flag grpc_http_trace;
 extern grpc_tracer_flag grpc_flowctl_trace;
 
-#ifndef NDEBUG
-#define GRPC_FLOW_CONTROL_IF_TRACING(stmt)   \
-  if (!(GRPC_TRACER_ON(grpc_flowctl_trace))) \
-    ;                                        \
-  else                                       \
-  stmt
-#else
-#define GRPC_FLOW_CONTROL_IF_TRACING(stmt)
-#endif
-
 #define GRPC_CHTTP2_IF_TRACING(stmt)      \
   if (!(GRPC_TRACER_ON(grpc_http_trace))) \
     ;                                     \
diff --git a/src/core/ext/transport/chttp2/transport/parsing.cc b/src/core/ext/transport/chttp2/transport/parsing.cc
index 78886b4..efa5791 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.cc
+++ b/src/core/ext/transport/chttp2/transport/parsing.cc
@@ -355,14 +355,15 @@
   grpc_chttp2_stream *s =
       grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
   grpc_error *err = GRPC_ERROR_NONE;
-  err = grpc_chttp2_flowctl_recv_data(&t->flow_control,
-                                      s == NULL ? NULL : &s->flow_control,
-                                      t->incoming_frame_size);
-  grpc_chttp2_act_on_flowctl_action(
-      exec_ctx,
-      grpc_chttp2_flowctl_get_action(exec_ctx, &t->flow_control,
-                                     s == NULL ? NULL : &s->flow_control),
-      t, s);
+  grpc_core::chttp2::FlowControlAction action;
+  if (s == nullptr) {
+    err = t->flow_control->RecvData(t->incoming_frame_size);
+    action = t->flow_control->MakeAction();
+  } else {
+    err = s->flow_control->RecvData(t->incoming_frame_size);
+    action = s->flow_control->MakeAction();
+  }
+  grpc_chttp2_act_on_flowctl_action(exec_ctx, action, t, s);
   if (err != GRPC_ERROR_NONE) {
     goto error_handler;
   }
@@ -434,19 +435,21 @@
     grpc_millis *cached_timeout =
         static_cast<grpc_millis *>(grpc_mdelem_get_user_data(md, free_timeout));
     grpc_millis timeout;
-    if (cached_timeout == NULL) {
-      /* not already parsed: parse it now, and store the result away */
-      cached_timeout = (grpc_millis *)gpr_malloc(sizeof(grpc_millis));
-      if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), cached_timeout)) {
+    if (cached_timeout != NULL) {
+      timeout = *cached_timeout;
+    } else {
+      if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), &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 = GRPC_MILLIS_INF_FUTURE;
+        timeout = GRPC_MILLIS_INF_FUTURE;
       }
-      timeout = *cached_timeout;
-      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
-    } else {
-      timeout = *cached_timeout;
+      if (GRPC_MDELEM_IS_INTERNED(md)) {
+        /* store the result */
+        cached_timeout = (grpc_millis *)gpr_malloc(sizeof(grpc_millis));
+        *cached_timeout = timeout;
+        grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+      }
     }
     if (timeout != GRPC_MILLIS_INF_FUTURE) {
       grpc_chttp2_incoming_metadata_buffer_set_deadline(
diff --git a/src/core/ext/transport/chttp2/transport/stream_map.h b/src/core/ext/transport/chttp2/transport/stream_map.h
index 364d37c..7ab6a4f 100644
--- a/src/core/ext/transport/chttp2/transport/stream_map.h
+++ b/src/core/ext/transport/chttp2/transport/stream_map.h
@@ -73,4 +73,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STREAM_MAP_H */
\ No newline at end of file
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STREAM_MAP_H */
diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc
index 4134890..ff76a5f 100644
--- a/src/core/ext/transport/chttp2/transport/writing.cc
+++ b/src/core/ext/transport/chttp2/transport/writing.cc
@@ -146,13 +146,13 @@
       s->flow_controlled_bytes_flowed,
       t->settings[GRPC_ACKED_SETTINGS]
                  [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
-      t->flow_control.remote_window,
+      t->flow_control->remote_window(),
       (uint32_t)GPR_MAX(
           0,
-          s->flow_control.remote_window_delta +
+          s->flow_control->remote_window_delta() +
               (int64_t)t->settings[GRPC_PEER_SETTINGS]
                                   [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]),
-      s->flow_control.remote_window_delta);
+      s->flow_control->remote_window_delta());
 }
 
 static bool stream_ref_if_not_destroyed(gpr_refcount *r) {
@@ -174,343 +174,449 @@
   return initial_metadata->list.default_count == initial_metadata->list.count;
 }
 
-grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
-    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
-  grpc_chttp2_stream *s;
+namespace {
+class StreamWriteContext;
+
+class WriteContext {
+ public:
+  WriteContext(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) : t_(t) {
+    GRPC_STATS_INC_HTTP2_WRITES_BEGUN(exec_ctx);
+    GPR_TIMER_BEGIN("grpc_chttp2_begin_write", 0);
+  }
+
+  // TODO(ctiller): make this the destructor
+  void FlushStats(grpc_exec_ctx *exec_ctx) {
+    GRPC_STATS_INC_HTTP2_SEND_INITIAL_METADATA_PER_WRITE(
+        exec_ctx, initial_metadata_writes_);
+    GRPC_STATS_INC_HTTP2_SEND_MESSAGE_PER_WRITE(exec_ctx, message_writes_);
+    GRPC_STATS_INC_HTTP2_SEND_TRAILING_METADATA_PER_WRITE(
+        exec_ctx, trailing_metadata_writes_);
+    GRPC_STATS_INC_HTTP2_SEND_FLOWCTL_PER_WRITE(exec_ctx, flow_control_writes_);
+  }
+
+  void FlushSettings(grpc_exec_ctx *exec_ctx) {
+    if (t_->dirtied_local_settings && !t_->sent_local_settings) {
+      grpc_slice_buffer_add(
+          &t_->outbuf, grpc_chttp2_settings_create(
+                           t_->settings[GRPC_SENT_SETTINGS],
+                           t_->settings[GRPC_LOCAL_SETTINGS],
+                           t_->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS));
+      t_->force_send_settings = false;
+      t_->dirtied_local_settings = false;
+      t_->sent_local_settings = true;
+      GRPC_STATS_INC_HTTP2_SETTINGS_WRITES(exec_ctx);
+    }
+  }
+
+  void FlushQueuedBuffers(grpc_exec_ctx *exec_ctx) {
+    /* simple writes are queued to qbuf, and flushed here */
+    grpc_slice_buffer_move_into(&t_->qbuf, &t_->outbuf);
+    GPR_ASSERT(t_->qbuf.count == 0);
+  }
+
+  void FlushWindowUpdates(grpc_exec_ctx *exec_ctx) {
+    uint32_t transport_announce =
+        t_->flow_control->MaybeSendUpdate(t_->outbuf.count > 0);
+    if (transport_announce) {
+      grpc_transport_one_way_stats throwaway_stats;
+      grpc_slice_buffer_add(
+          &t_->outbuf, grpc_chttp2_window_update_create(0, transport_announce,
+                                                        &throwaway_stats));
+      ResetPingRecvClock();
+    }
+  }
+
+  void FlushPingAcks() {
+    for (size_t i = 0; i < t_->ping_ack_count; i++) {
+      grpc_slice_buffer_add(&t_->outbuf,
+                            grpc_chttp2_ping_create(true, t_->ping_acks[i]));
+    }
+    t_->ping_ack_count = 0;
+  }
+
+  void EnactHpackSettings(grpc_exec_ctx *exec_ctx) {
+    grpc_chttp2_hpack_compressor_set_max_table_size(
+        &t_->hpack_compressor,
+        t_->settings[GRPC_PEER_SETTINGS]
+                    [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
+  }
+
+  void UpdateStreamsNoLongerStalled() {
+    grpc_chttp2_stream *s;
+    while (grpc_chttp2_list_pop_stalled_by_transport(t_, &s)) {
+      if (t_->closed_with_error == GRPC_ERROR_NONE &&
+          grpc_chttp2_list_add_writable_stream(t_, s)) {
+        if (!stream_ref_if_not_destroyed(&s->refcount->refs)) {
+          grpc_chttp2_list_remove_writable_stream(t_, s);
+        }
+      }
+    }
+  }
+
+  grpc_chttp2_stream *NextStream() {
+    if (t_->outbuf.length > target_write_size(t_)) {
+      result_.partial = true;
+      return nullptr;
+    }
+
+    grpc_chttp2_stream *s;
+    if (!grpc_chttp2_list_pop_writable_stream(t_, &s)) {
+      return nullptr;
+    }
+
+    return s;
+  }
+
+  void ResetPingRecvClock() {
+    if (!t_->is_client) {
+      t_->ping_recv_state.last_ping_recv_time = GRPC_MILLIS_INF_PAST;
+      t_->ping_recv_state.ping_strikes = 0;
+    }
+  }
+
+  void IncInitialMetadataWrites() { ++initial_metadata_writes_; }
+  void IncWindowUpdateWrites() { ++flow_control_writes_; }
+  void IncMessageWrites() { ++message_writes_; }
+  void IncTrailingMetadataWrites() { ++trailing_metadata_writes_; }
+
+  void NoteScheduledResults() { result_.early_results_scheduled = true; }
+
+  grpc_chttp2_transport *transport() const { return t_; }
+
+  grpc_chttp2_begin_write_result Result() {
+    result_.writing = t_->outbuf.count > 0;
+    return result_;
+  }
+
+ private:
+  grpc_chttp2_transport *const t_;
 
   /* stats histogram counters: we increment these throughout this function,
      and at the end publish to the central stats histograms */
-  int flow_control_writes = 0;
-  int initial_metadata_writes = 0;
-  int trailing_metadata_writes = 0;
-  int message_writes = 0;
+  int flow_control_writes_ = 0;
+  int initial_metadata_writes_ = 0;
+  int trailing_metadata_writes_ = 0;
+  int message_writes_ = 0;
+  grpc_chttp2_begin_write_result result_ = {false, false, false};
+};
 
-  GRPC_STATS_INC_HTTP2_WRITES_BEGUN(exec_ctx);
+class DataSendContext {
+ public:
+  DataSendContext(WriteContext *write_context, grpc_chttp2_transport *t,
+                  grpc_chttp2_stream *s)
+      : write_context_(write_context),
+        t_(t),
+        s_(s),
+        sending_bytes_before_(s_->sending_bytes) {}
 
-  GPR_TIMER_BEGIN("grpc_chttp2_begin_write", 0);
-
-  if (t->dirtied_local_settings && !t->sent_local_settings) {
-    grpc_slice_buffer_add(
-        &t->outbuf,
-        grpc_chttp2_settings_create(
-            t->settings[GRPC_SENT_SETTINGS], t->settings[GRPC_LOCAL_SETTINGS],
-            t->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS));
-    t->force_send_settings = 0;
-    t->dirtied_local_settings = 0;
-    t->sent_local_settings = 1;
-    GRPC_STATS_INC_HTTP2_SETTINGS_WRITES(exec_ctx);
+  uint32_t stream_remote_window() const {
+    return (uint32_t)GPR_MAX(
+        0, s_->flow_control->remote_window_delta() +
+               (int64_t)t_->settings[GRPC_PEER_SETTINGS]
+                                    [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
   }
 
-  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]));
+  uint32_t max_outgoing() const {
+    return (uint32_t)GPR_MIN(
+        t_->settings[GRPC_PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
+        GPR_MIN(stream_remote_window(), t_->flow_control->remote_window()));
   }
-  t->ping_ack_count = 0;
 
-  /* simple writes are queued to qbuf, and flushed here */
-  grpc_slice_buffer_move_into(&t->qbuf, &t->outbuf);
-  GPR_ASSERT(t->qbuf.count == 0);
+  bool AnyOutgoing() const { return max_outgoing() != 0; }
 
-  grpc_chttp2_hpack_compressor_set_max_table_size(
-      &t->hpack_compressor,
-      t->settings[GRPC_PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
-
-  if (t->flow_control.remote_window > 0) {
-    while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) {
-      if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
-        stream_ref_if_not_destroyed(&s->refcount->refs);
+  void FlushCompressedBytes() {
+    uint32_t send_bytes =
+        (uint32_t)GPR_MIN(max_outgoing(), s_->compressed_data_buffer.length);
+    bool is_last_data_frame =
+        (send_bytes == s_->compressed_data_buffer.length &&
+         s_->flow_controlled_buffer.length == 0 &&
+         s_->fetching_send_message == NULL);
+    if (is_last_data_frame && s_->send_trailing_metadata != NULL &&
+        s_->stream_compression_ctx != NULL) {
+      if (!grpc_stream_compress(s_->stream_compression_ctx,
+                                &s_->flow_controlled_buffer,
+                                &s_->compressed_data_buffer, NULL, MAX_SIZE_T,
+                                GRPC_STREAM_COMPRESSION_FLUSH_FINISH)) {
+        gpr_log(GPR_ERROR, "Stream compression failed.");
       }
+      grpc_stream_compression_context_destroy(s_->stream_compression_ctx);
+      s_->stream_compression_ctx = NULL;
+      /* After finish, bytes in s->compressed_data_buffer may be
+       * more than max_outgoing. Start another round of the current
+       * while loop so that send_bytes and is_last_data_frame are
+       * recalculated. */
+      return;
+    }
+    is_last_frame_ = is_last_data_frame && s_->send_trailing_metadata != NULL &&
+                     grpc_metadata_batch_is_empty(s_->send_trailing_metadata);
+    grpc_chttp2_encode_data(s_->id, &s_->compressed_data_buffer, send_bytes,
+                            is_last_frame_, &s_->stats.outgoing, &t_->outbuf);
+    s_->flow_control->SentData(send_bytes);
+    if (s_->compressed_data_buffer.length == 0) {
+      s_->sending_bytes += s_->uncompressed_data_size;
     }
   }
 
-  grpc_chttp2_begin_write_result result = {false, false, false};
+  void CompressMoreBytes() {
+    if (s_->stream_compression_ctx == NULL) {
+      s_->stream_compression_ctx =
+          grpc_stream_compression_context_create(s_->stream_compression_method);
+    }
+    s_->uncompressed_data_size = s_->flow_controlled_buffer.length;
+    if (!grpc_stream_compress(s_->stream_compression_ctx,
+                              &s_->flow_controlled_buffer,
+                              &s_->compressed_data_buffer, NULL, MAX_SIZE_T,
+                              GRPC_STREAM_COMPRESSION_FLUSH_SYNC)) {
+      gpr_log(GPR_ERROR, "Stream compression failed.");
+    }
+  }
+
+  bool is_last_frame() const { return is_last_frame_; }
+
+  void CallCallbacks(grpc_exec_ctx *exec_ctx) {
+    if (update_list(exec_ctx, t_, s_,
+                    (int64_t)(s_->sending_bytes - sending_bytes_before_),
+                    &s_->on_flow_controlled_cbs,
+                    &s_->flow_controlled_bytes_flowed, GRPC_ERROR_NONE)) {
+      write_context_->NoteScheduledResults();
+    }
+  }
+
+ private:
+  WriteContext *write_context_;
+  grpc_chttp2_transport *t_;
+  grpc_chttp2_stream *s_;
+  const size_t sending_bytes_before_;
+  bool is_last_frame_ = false;
+};
+
+class StreamWriteContext {
+ public:
+  StreamWriteContext(WriteContext *write_context, grpc_chttp2_stream *s)
+      : write_context_(write_context), t_(write_context->transport()), s_(s) {
+    GRPC_CHTTP2_IF_TRACING(
+        gpr_log(GPR_DEBUG, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t_,
+                t_->is_client ? "CLIENT" : "SERVER", s->id,
+                s->sent_initial_metadata, s->send_initial_metadata != NULL,
+                (int)(s->flow_control->local_window_delta() -
+                      s->flow_control->announced_window_delta())));
+  }
+
+  void FlushInitialMetadata(grpc_exec_ctx *exec_ctx) {
+    /* send initial metadata if it's available */
+    if (s_->sent_initial_metadata) return;
+    if (s_->send_initial_metadata == nullptr) return;
+
+    // We skip this on the server side if there is no custom initial
+    // metadata, there are no messages to send, and we are also sending
+    // trailing metadata.  This results in a Trailers-Only response,
+    // which is required for retries, as per:
+    // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid
+    if (!t_->is_client && s_->fetching_send_message == nullptr &&
+        s_->flow_controlled_buffer.length == 0 &&
+        s_->compressed_data_buffer.length == 0 &&
+        s_->send_trailing_metadata != nullptr &&
+        is_default_initial_metadata(s_->send_initial_metadata)) {
+      ConvertInitialMetadataToTrailingMetadata();
+    } else {
+      grpc_encode_header_options hopt = {
+          s_->id,  // stream_id
+          false,   // is_eof
+          t_->settings[GRPC_PEER_SETTINGS]
+                      [GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] !=
+              0,  // use_true_binary_metadata
+          t_->settings[GRPC_PEER_SETTINGS]
+                      [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],  // max_frame_size
+          &s_->stats.outgoing                                 // stats
+      };
+      grpc_chttp2_encode_header(exec_ctx, &t_->hpack_compressor, NULL, 0,
+                                s_->send_initial_metadata, &hopt, &t_->outbuf);
+      write_context_->ResetPingRecvClock();
+      write_context_->IncInitialMetadataWrites();
+    }
+
+    s_->send_initial_metadata = NULL;
+    s_->sent_initial_metadata = true;
+    write_context_->NoteScheduledResults();
+    grpc_chttp2_complete_closure_step(
+        exec_ctx, t_, s_, &s_->send_initial_metadata_finished, GRPC_ERROR_NONE,
+        "send_initial_metadata_finished");
+  }
+
+  void FlushWindowUpdates(grpc_exec_ctx *exec_ctx) {
+    /* send any window updates */
+    const uint32_t stream_announce = s_->flow_control->MaybeSendUpdate();
+    if (stream_announce == 0) return;
+
+    grpc_slice_buffer_add(
+        &t_->outbuf, grpc_chttp2_window_update_create(s_->id, stream_announce,
+                                                      &s_->stats.outgoing));
+    write_context_->ResetPingRecvClock();
+    write_context_->IncWindowUpdateWrites();
+  }
+
+  void FlushData(grpc_exec_ctx *exec_ctx) {
+    if (!s_->sent_initial_metadata) return;
+
+    if (s_->flow_controlled_buffer.length == 0 &&
+        s_->compressed_data_buffer.length == 0) {
+      return;  // early out: nothing to do
+    }
+
+    DataSendContext data_send_context(write_context_, t_, s_);
+
+    if (!data_send_context.AnyOutgoing()) {
+      if (t_->flow_control->remote_window() <= 0) {
+        report_stall(t_, s_, "transport");
+        grpc_chttp2_list_add_stalled_by_transport(t_, s_);
+      } else if (data_send_context.stream_remote_window() <= 0) {
+        report_stall(t_, s_, "stream");
+        grpc_chttp2_list_add_stalled_by_stream(t_, s_);
+      }
+      return;  // early out: nothing to do
+    }
+
+    while ((s_->flow_controlled_buffer.length > 0 ||
+            s_->compressed_data_buffer.length > 0) &&
+           data_send_context.max_outgoing() > 0) {
+      if (s_->compressed_data_buffer.length > 0) {
+        data_send_context.FlushCompressedBytes();
+      } else {
+        data_send_context.CompressMoreBytes();
+      }
+    }
+    write_context_->ResetPingRecvClock();
+    if (data_send_context.is_last_frame()) {
+      SentLastFrame(exec_ctx);
+    }
+    data_send_context.CallCallbacks(exec_ctx);
+    stream_became_writable_ = true;
+    if (s_->flow_controlled_buffer.length > 0 ||
+        s_->compressed_data_buffer.length > 0) {
+      GRPC_CHTTP2_STREAM_REF(s_, "chttp2_writing:fork");
+      grpc_chttp2_list_add_writable_stream(t_, s_);
+    }
+    write_context_->IncMessageWrites();
+  }
+
+  void FlushTrailingMetadata(grpc_exec_ctx *exec_ctx) {
+    if (!s_->sent_initial_metadata) return;
+
+    if (s_->send_trailing_metadata == NULL) return;
+    if (s_->fetching_send_message != NULL) return;
+    if (s_->flow_controlled_buffer.length != 0) return;
+    if (s_->compressed_data_buffer.length != 0) return;
+
+    GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
+    if (grpc_metadata_batch_is_empty(s_->send_trailing_metadata)) {
+      grpc_chttp2_encode_data(s_->id, &s_->flow_controlled_buffer, 0, true,
+                              &s_->stats.outgoing, &t_->outbuf);
+    } else {
+      grpc_encode_header_options hopt = {
+          s_->id, true,
+          t_->settings[GRPC_PEER_SETTINGS]
+                      [GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] !=
+              0,
+
+          t_->settings[GRPC_PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
+          &s_->stats.outgoing};
+      grpc_chttp2_encode_header(exec_ctx, &t_->hpack_compressor,
+                                extra_headers_for_trailing_metadata_,
+                                num_extra_headers_for_trailing_metadata_,
+                                s_->send_trailing_metadata, &hopt, &t_->outbuf);
+    }
+    write_context_->IncTrailingMetadataWrites();
+    write_context_->ResetPingRecvClock();
+    SentLastFrame(exec_ctx);
+
+    write_context_->NoteScheduledResults();
+    grpc_chttp2_complete_closure_step(
+        exec_ctx, t_, s_, &s_->send_trailing_metadata_finished, GRPC_ERROR_NONE,
+        "send_trailing_metadata_finished");
+  }
+
+  bool stream_became_writable() { return stream_became_writable_; }
+
+ private:
+  void ConvertInitialMetadataToTrailingMetadata() {
+    GRPC_CHTTP2_IF_TRACING(
+        gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)"));
+    // When sending Trailers-Only, we need to move the :status and
+    // content-type headers to the trailers.
+    if (s_->send_initial_metadata->idx.named.status != NULL) {
+      extra_headers_for_trailing_metadata_
+          [num_extra_headers_for_trailing_metadata_++] =
+              &s_->send_initial_metadata->idx.named.status->md;
+    }
+    if (s_->send_initial_metadata->idx.named.content_type != NULL) {
+      extra_headers_for_trailing_metadata_
+          [num_extra_headers_for_trailing_metadata_++] =
+              &s_->send_initial_metadata->idx.named.content_type->md;
+    }
+  }
+
+  void SentLastFrame(grpc_exec_ctx *exec_ctx) {
+    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_HTTP2_NO_ERROR, &s_->stats.outgoing));
+    }
+    grpc_chttp2_mark_stream_closed(exec_ctx, t_, s_, !t_->is_client, true,
+                                   GRPC_ERROR_NONE);
+  }
+
+  WriteContext *const write_context_;
+  grpc_chttp2_transport *const t_;
+  grpc_chttp2_stream *const s_;
+  bool stream_became_writable_ = false;
+  grpc_mdelem *extra_headers_for_trailing_metadata_[2];
+  size_t num_extra_headers_for_trailing_metadata_ = 0;
+};
+}  // namespace
+
+grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
+  WriteContext ctx(exec_ctx, t);
+  ctx.FlushSettings(exec_ctx);
+  ctx.FlushPingAcks();
+  ctx.FlushQueuedBuffers(exec_ctx);
+  ctx.EnactHpackSettings(exec_ctx);
+
+  if (t->flow_control->remote_window() > 0) {
+    ctx.UpdateStreamsNoLongerStalled();
+  }
 
   /* for each grpc_chttp2_stream that's become writable, frame it's data
      (according to available window sizes) and add to the output buffer */
-  while (true) {
-    if (t->outbuf.length > target_write_size(t)) {
-      result.partial = true;
-      break;
-    }
+  while (grpc_chttp2_stream *s = ctx.NextStream()) {
+    StreamWriteContext stream_ctx(&ctx, s);
+    stream_ctx.FlushInitialMetadata(exec_ctx);
+    stream_ctx.FlushWindowUpdates(exec_ctx);
+    stream_ctx.FlushData(exec_ctx);
+    stream_ctx.FlushTrailingMetadata(exec_ctx);
 
-    if (!grpc_chttp2_list_pop_writable_stream(t, &s)) {
-      break;
-    }
-
-    bool sent_initial_metadata = s->sent_initial_metadata;
-    bool now_writing = false;
-
-    GRPC_CHTTP2_IF_TRACING(
-        gpr_log(GPR_DEBUG, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t,
-                t->is_client ? "CLIENT" : "SERVER", s->id,
-                sent_initial_metadata, s->send_initial_metadata != NULL,
-                (int)(s->flow_control.local_window_delta -
-                      s->flow_control.announced_window_delta)));
-
-    grpc_mdelem *extra_headers_for_trailing_metadata[2];
-    size_t num_extra_headers_for_trailing_metadata = 0;
-
-    /* send initial metadata if it's available */
-    if (!sent_initial_metadata && s->send_initial_metadata != NULL) {
-      // We skip this on the server side if there is no custom initial
-      // metadata, there are no messages to send, and we are also sending
-      // trailing metadata.  This results in a Trailers-Only response,
-      // which is required for retries, as per:
-      // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid
-      if (t->is_client || s->fetching_send_message != NULL ||
-          s->flow_controlled_buffer.length != 0 ||
-          s->send_trailing_metadata == NULL ||
-          !is_default_initial_metadata(s->send_initial_metadata)) {
-        grpc_encode_header_options hopt = {
-            s->id,  // stream_id
-            false,  // is_eof
-            t->settings[GRPC_PEER_SETTINGS]
-                       [GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] !=
-                0,  // use_true_binary_metadata
-            t->settings[GRPC_PEER_SETTINGS]
-                       [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],  // max_frame_size
-            &s->stats.outgoing                                 // stats
-        };
-        grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, NULL, 0,
-                                  s->send_initial_metadata, &hopt, &t->outbuf);
-        now_writing = true;
-        if (!t->is_client) {
-          t->ping_recv_state.last_ping_recv_time = GRPC_MILLIS_INF_PAST;
-          t->ping_recv_state.ping_strikes = 0;
-        }
-        initial_metadata_writes++;
-      } else {
-        GRPC_CHTTP2_IF_TRACING(
-            gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)"));
-        // When sending Trailers-Only, we need to move the :status and
-        // content-type headers to the trailers.
-        if (s->send_initial_metadata->idx.named.status != NULL) {
-          extra_headers_for_trailing_metadata
-              [num_extra_headers_for_trailing_metadata++] =
-                  &s->send_initial_metadata->idx.named.status->md;
-        }
-        if (s->send_initial_metadata->idx.named.content_type != NULL) {
-          extra_headers_for_trailing_metadata
-              [num_extra_headers_for_trailing_metadata++] =
-                  &s->send_initial_metadata->idx.named.content_type->md;
-        }
-        trailing_metadata_writes++;
-      }
-      s->send_initial_metadata = NULL;
-      s->sent_initial_metadata = true;
-      sent_initial_metadata = true;
-      result.early_results_scheduled = true;
-      grpc_chttp2_complete_closure_step(
-          exec_ctx, t, s, &s->send_initial_metadata_finished, GRPC_ERROR_NONE,
-          "send_initial_metadata_finished");
-    }
-
-    /* send any window updates */
-    uint32_t stream_announce = grpc_chttp2_flowctl_maybe_send_stream_update(
-        &t->flow_control, &s->flow_control);
-    if (stream_announce > 0) {
-      grpc_slice_buffer_add(
-          &t->outbuf, grpc_chttp2_window_update_create(s->id, stream_announce,
-                                                       &s->stats.outgoing));
-      if (!t->is_client) {
-        t->ping_recv_state.last_ping_recv_time = GRPC_MILLIS_INF_PAST;
-        t->ping_recv_state.ping_strikes = 0;
-      }
-      flow_control_writes++;
-    }
-    if (sent_initial_metadata) {
-      /* send any body bytes, if allowed by flow control */
-      if (s->flow_controlled_buffer.length > 0 ||
-          s->compressed_data_buffer.length > 0) {
-        uint32_t stream_remote_window = (uint32_t)GPR_MAX(
-            0,
-            s->flow_control.remote_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_PEER_SETTINGS]
-                       [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
-            GPR_MIN(stream_remote_window, t->flow_control.remote_window));
-        if (max_outgoing > 0) {
-          bool is_last_data_frame = false;
-          bool is_last_frame = false;
-          size_t sending_bytes_before = s->sending_bytes;
-          while ((s->flow_controlled_buffer.length > 0 ||
-                  s->compressed_data_buffer.length > 0) &&
-                 max_outgoing > 0) {
-            if (s->compressed_data_buffer.length > 0) {
-              uint32_t send_bytes = (uint32_t)GPR_MIN(
-                  max_outgoing, s->compressed_data_buffer.length);
-              is_last_data_frame =
-                  (send_bytes == s->compressed_data_buffer.length &&
-                   s->flow_controlled_buffer.length == 0 &&
-                   s->fetching_send_message == NULL);
-              if (is_last_data_frame && s->send_trailing_metadata != NULL &&
-                  s->stream_compression_ctx != NULL) {
-                if (!grpc_stream_compress(
-                        s->stream_compression_ctx, &s->flow_controlled_buffer,
-                        &s->compressed_data_buffer, NULL, MAX_SIZE_T,
-                        GRPC_STREAM_COMPRESSION_FLUSH_FINISH)) {
-                  gpr_log(GPR_ERROR, "Stream compression failed.");
-                }
-                grpc_stream_compression_context_destroy(
-                    s->stream_compression_ctx);
-                s->stream_compression_ctx = NULL;
-                /* After finish, bytes in s->compressed_data_buffer may be
-                 * more than max_outgoing. Start another round of the current
-                 * while loop so that send_bytes and is_last_data_frame are
-                 * recalculated. */
-                continue;
-              }
-              is_last_frame =
-                  is_last_data_frame && s->send_trailing_metadata != NULL &&
-                  grpc_metadata_batch_is_empty(s->send_trailing_metadata);
-              grpc_chttp2_encode_data(s->id, &s->compressed_data_buffer,
-                                      send_bytes, is_last_frame,
-                                      &s->stats.outgoing, &t->outbuf);
-              grpc_chttp2_flowctl_sent_data(&t->flow_control, &s->flow_control,
-                                            send_bytes);
-              max_outgoing -= send_bytes;
-              if (s->compressed_data_buffer.length == 0) {
-                s->sending_bytes += s->uncompressed_data_size;
-              }
-            } else {
-              if (s->stream_compression_ctx == NULL) {
-                s->stream_compression_ctx =
-                    grpc_stream_compression_context_create(
-                        s->stream_compression_method);
-              }
-              s->uncompressed_data_size = s->flow_controlled_buffer.length;
-              if (!grpc_stream_compress(
-                      s->stream_compression_ctx, &s->flow_controlled_buffer,
-                      &s->compressed_data_buffer, NULL, MAX_SIZE_T,
-                      GRPC_STREAM_COMPRESSION_FLUSH_SYNC)) {
-                gpr_log(GPR_ERROR, "Stream compression failed.");
-              }
-            }
-          }
-          if (!t->is_client) {
-            t->ping_recv_state.last_ping_recv_time = 0;
-            t->ping_recv_state.ping_strikes = 0;
-          }
-          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_HTTP2_NO_ERROR,
-                                                    &s->stats.outgoing));
-            }
-            grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1,
-                                           GRPC_ERROR_NONE);
-          }
-          result.early_results_scheduled |=
-              update_list(exec_ctx, t, s,
-                          (int64_t)(s->sending_bytes - sending_bytes_before),
-                          &s->on_flow_controlled_cbs,
-                          &s->flow_controlled_bytes_flowed, GRPC_ERROR_NONE);
-          now_writing = true;
-          if (s->flow_controlled_buffer.length > 0 ||
-              s->compressed_data_buffer.length > 0) {
-            GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:fork");
-            grpc_chttp2_list_add_writable_stream(t, s);
-          }
-          message_writes++;
-        } else if (t->flow_control.remote_window == 0) {
-          report_stall(t, s, "transport");
-          grpc_chttp2_list_add_stalled_by_transport(t, s);
-          now_writing = true;
-        } else if (stream_remote_window == 0) {
-          report_stall(t, s, "stream");
-          grpc_chttp2_list_add_stalled_by_stream(t, s);
-          now_writing = true;
-        }
-      }
-      if (s->send_trailing_metadata != NULL &&
-          s->fetching_send_message == NULL &&
-          s->flow_controlled_buffer.length == 0 &&
-          s->compressed_data_buffer.length == 0) {
-        GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
-        if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) {
-          grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true,
-                                  &s->stats.outgoing, &t->outbuf);
-        } else {
-          grpc_encode_header_options hopt = {
-              s->id, true,
-
-              t->settings
-                      [GRPC_PEER_SETTINGS]
-                      [GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] !=
-                  0,
-
-              t->settings[GRPC_PEER_SETTINGS]
-                         [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
-              &s->stats.outgoing};
-          grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor,
-                                    extra_headers_for_trailing_metadata,
-                                    num_extra_headers_for_trailing_metadata,
-                                    s->send_trailing_metadata, &hopt,
-                                    &t->outbuf);
-          trailing_metadata_writes++;
-        }
-        s->send_trailing_metadata = NULL;
-        s->sent_trailing_metadata = true;
-        if (!t->is_client) {
-          t->ping_recv_state.last_ping_recv_time = GRPC_MILLIS_INF_PAST;
-          t->ping_recv_state.ping_strikes = 0;
-        }
-        if (!t->is_client && !s->read_closed) {
-          grpc_slice_buffer_add(
-              &t->outbuf, grpc_chttp2_rst_stream_create(
-                              s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing));
-        }
-        grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1,
-                                       GRPC_ERROR_NONE);
-        now_writing = true;
-        result.early_results_scheduled = true;
-        grpc_chttp2_complete_closure_step(
-            exec_ctx, t, s, &s->send_trailing_metadata_finished,
-            GRPC_ERROR_NONE, "send_trailing_metadata_finished");
-      }
-    }
-
-    if (now_writing) {
-      GRPC_STATS_INC_HTTP2_SEND_INITIAL_METADATA_PER_WRITE(
-          exec_ctx, initial_metadata_writes);
-      GRPC_STATS_INC_HTTP2_SEND_MESSAGE_PER_WRITE(exec_ctx, message_writes);
-      GRPC_STATS_INC_HTTP2_SEND_TRAILING_METADATA_PER_WRITE(
-          exec_ctx, trailing_metadata_writes);
-      GRPC_STATS_INC_HTTP2_SEND_FLOWCTL_PER_WRITE(exec_ctx,
-                                                  flow_control_writes);
-
+    if (stream_ctx.stream_became_writable()) {
       if (!grpc_chttp2_list_add_writing_stream(t, s)) {
         /* already in writing list: drop ref */
         GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:already_writing");
+      } else {
+        /* ref will be dropped at end of write */
       }
     } else {
       GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:no_write");
     }
   }
 
-  maybe_initiate_ping(exec_ctx, t);
+  ctx.FlushWindowUpdates(exec_ctx);
 
-  uint32_t transport_announce = grpc_chttp2_flowctl_maybe_send_transport_update(
-      &t->flow_control, t->outbuf.count > 0);
-  if (transport_announce) {
-    grpc_transport_one_way_stats throwaway_stats;
-    grpc_slice_buffer_add(
-        &t->outbuf, grpc_chttp2_window_update_create(0, transport_announce,
-                                                     &throwaway_stats));
-    if (!t->is_client) {
-      t->ping_recv_state.last_ping_recv_time = GRPC_MILLIS_INF_PAST;
-      t->ping_recv_state.ping_strikes = 0;
-    }
-  }
+  maybe_initiate_ping(exec_ctx, t);
 
   GPR_TIMER_END("grpc_chttp2_begin_write", 0);
 
-  result.writing = t->outbuf.count > 0;
-  return result;
+  return ctx.Result();
 }
 
 void grpc_chttp2_end_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc
index ff1367f..97e4f7d 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.cc
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc
@@ -692,7 +692,7 @@
   uint8_t *p = (uint8_t *)write_buffer;
   /* Append 5 byte header */
   /* Compressed flag */
-  *p++ = (flags & GRPC_WRITE_INTERNAL_COMPRESS) ? 1 : 0;
+  *p++ = (uint8_t)((flags & GRPC_WRITE_INTERNAL_COMPRESS) ? 1 : 0);
   /* Message length */
   *p++ = (uint8_t)(length >> 24);
   *p++ = (uint8_t)(length >> 16);
diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc
index 1001d74..1551f5e 100644
--- a/src/core/ext/transport/inproc/inproc_transport.cc
+++ b/src/core/ext/transport/inproc/inproc_transport.cc
@@ -62,96 +62,22 @@
   struct inproc_stream *stream_list;
 } inproc_transport;
 
-typedef struct sb_list_entry {
-  grpc_slice_buffer sb;
-  struct sb_list_entry *next;
-} sb_list_entry;
-
-// Specialize grpc_byte_stream for our use case
-typedef struct {
-  grpc_byte_stream base;
-  sb_list_entry *le;
-  grpc_error *shutdown_error;
-} inproc_slice_byte_stream;
-
-typedef struct {
-  // TODO (vjpai): Add some inlined elements to avoid alloc in simple cases
-  sb_list_entry *head;
-  sb_list_entry *tail;
-} slice_buffer_list;
-
-static void slice_buffer_list_init(slice_buffer_list *l) {
-  l->head = NULL;
-  l->tail = NULL;
-}
-
-static void sb_list_entry_destroy(grpc_exec_ctx *exec_ctx, sb_list_entry *le) {
-  grpc_slice_buffer_destroy_internal(exec_ctx, &le->sb);
-  gpr_free(le);
-}
-
-static void slice_buffer_list_destroy(grpc_exec_ctx *exec_ctx,
-                                      slice_buffer_list *l) {
-  sb_list_entry *curr = l->head;
-  while (curr != NULL) {
-    sb_list_entry *le = curr;
-    curr = curr->next;
-    sb_list_entry_destroy(exec_ctx, le);
-  }
-  l->head = NULL;
-  l->tail = NULL;
-}
-
-static bool slice_buffer_list_empty(slice_buffer_list *l) {
-  return l->head == NULL;
-}
-
-static void slice_buffer_list_append_entry(slice_buffer_list *l,
-                                           sb_list_entry *next) {
-  next->next = NULL;
-  if (l->tail) {
-    l->tail->next = next;
-    l->tail = next;
-  } else {
-    l->head = next;
-    l->tail = next;
-  }
-}
-
-static grpc_slice_buffer *slice_buffer_list_append(slice_buffer_list *l) {
-  sb_list_entry *next = (sb_list_entry *)gpr_malloc(sizeof(*next));
-  grpc_slice_buffer_init(&next->sb);
-  slice_buffer_list_append_entry(l, next);
-  return &next->sb;
-}
-
-static sb_list_entry *slice_buffer_list_pophead(slice_buffer_list *l) {
-  sb_list_entry *ret = l->head;
-  l->head = l->head->next;
-  if (l->head == NULL) {
-    l->tail = NULL;
-  }
-  return ret;
-}
-
 typedef struct inproc_stream {
   inproc_transport *t;
   grpc_metadata_batch to_read_initial_md;
   uint32_t to_read_initial_md_flags;
   bool to_read_initial_md_filled;
-  slice_buffer_list to_read_message;
   grpc_metadata_batch to_read_trailing_md;
   bool to_read_trailing_md_filled;
-  bool reads_needed;
-  bool read_closure_scheduled;
-  grpc_closure read_closure;
+  bool ops_needed;
+  bool op_closure_scheduled;
+  grpc_closure op_closure;
   // Write buffer used only during gap at init time when client-side
   // stream is set up but server side stream is not yet set up
   grpc_metadata_batch write_buffer_initial_md;
   bool write_buffer_initial_md_filled;
   uint32_t write_buffer_initial_md_flags;
   grpc_millis write_buffer_deadline;
-  slice_buffer_list write_buffer_message;
   grpc_metadata_batch write_buffer_trailing_md;
   bool write_buffer_trailing_md_filled;
   grpc_error *write_buffer_cancel_error;
@@ -164,11 +90,15 @@
 
   gpr_arena *arena;
 
+  grpc_transport_stream_op_batch *send_message_op;
+  grpc_transport_stream_op_batch *send_trailing_md_op;
   grpc_transport_stream_op_batch *recv_initial_md_op;
   grpc_transport_stream_op_batch *recv_message_op;
   grpc_transport_stream_op_batch *recv_trailing_md_op;
 
-  inproc_slice_byte_stream recv_message_stream;
+  grpc_slice_buffer recv_message;
+  grpc_slice_buffer_stream recv_stream;
+  bool recv_inited;
 
   bool initial_md_sent;
   bool trailing_md_sent;
@@ -187,54 +117,11 @@
   struct inproc_stream *stream_list_next;
 } inproc_stream;
 
-static bool inproc_slice_byte_stream_next(grpc_exec_ctx *exec_ctx,
-                                          grpc_byte_stream *bs, size_t max,
-                                          grpc_closure *on_complete) {
-  // Because inproc transport always provides the entire message atomically,
-  // the byte stream always has data available when this function is called.
-  // Thus, this function always returns true (unlike other transports) and
-  // there is never any need to schedule a closure
-  return true;
-}
-
-static grpc_error *inproc_slice_byte_stream_pull(grpc_exec_ctx *exec_ctx,
-                                                 grpc_byte_stream *bs,
-                                                 grpc_slice *slice) {
-  inproc_slice_byte_stream *stream = (inproc_slice_byte_stream *)bs;
-  if (stream->shutdown_error != GRPC_ERROR_NONE) {
-    return GRPC_ERROR_REF(stream->shutdown_error);
-  }
-  *slice = grpc_slice_buffer_take_first(&stream->le->sb);
-  return GRPC_ERROR_NONE;
-}
-
-static void inproc_slice_byte_stream_shutdown(grpc_exec_ctx *exec_ctx,
-                                              grpc_byte_stream *bs,
-                                              grpc_error *error) {
-  inproc_slice_byte_stream *stream = (inproc_slice_byte_stream *)bs;
-  GRPC_ERROR_UNREF(stream->shutdown_error);
-  stream->shutdown_error = error;
-}
-
-static void inproc_slice_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
-                                             grpc_byte_stream *bs) {
-  inproc_slice_byte_stream *stream = (inproc_slice_byte_stream *)bs;
-  sb_list_entry_destroy(exec_ctx, stream->le);
-  GRPC_ERROR_UNREF(stream->shutdown_error);
-}
-
-static const grpc_byte_stream_vtable inproc_slice_byte_stream_vtable = {
-    inproc_slice_byte_stream_next, inproc_slice_byte_stream_pull,
-    inproc_slice_byte_stream_shutdown, inproc_slice_byte_stream_destroy};
-
-void inproc_slice_byte_stream_init(inproc_slice_byte_stream *s,
-                                   sb_list_entry *le) {
-  s->base.length = (uint32_t)le->sb.length;
-  s->base.flags = 0;
-  s->base.vtable = &inproc_slice_byte_stream_vtable;
-  s->le = le;
-  s->shutdown_error = GRPC_ERROR_NONE;
-}
+static grpc_closure do_nothing_closure;
+static bool cancel_stream_locked(grpc_exec_ctx *exec_ctx, inproc_stream *s,
+                                 grpc_error *error);
+static void op_state_machine(grpc_exec_ctx *exec_ctx, void *arg,
+                             grpc_error *error);
 
 static void ref_transport(inproc_transport *t) {
   INPROC_LOG(GPR_DEBUG, "ref_transport %p", t);
@@ -280,12 +167,14 @@
 static void really_destroy_stream(grpc_exec_ctx *exec_ctx, inproc_stream *s) {
   INPROC_LOG(GPR_DEBUG, "really_destroy_stream %p", s);
 
-  slice_buffer_list_destroy(exec_ctx, &s->to_read_message);
-  slice_buffer_list_destroy(exec_ctx, &s->write_buffer_message);
   GRPC_ERROR_UNREF(s->write_buffer_cancel_error);
   GRPC_ERROR_UNREF(s->cancel_self_error);
   GRPC_ERROR_UNREF(s->cancel_other_error);
 
+  if (s->recv_inited) {
+    grpc_slice_buffer_destroy_internal(exec_ctx, &s->recv_message);
+  }
+
   unref_transport(exec_ctx, s->t);
 
   if (s->closure_at_destroy) {
@@ -293,9 +182,6 @@
   }
 }
 
-static void read_state_machine(grpc_exec_ctx *exec_ctx, void *arg,
-                               grpc_error *error);
-
 static void log_metadata(const grpc_metadata_batch *md_batch, bool is_client,
                          bool is_initial) {
   for (grpc_linked_mdelem *md = md_batch->list.head; md != NULL;
@@ -359,11 +245,9 @@
   s->write_buffer_initial_md_filled = false;
   grpc_metadata_batch_init(&s->write_buffer_trailing_md);
   s->write_buffer_trailing_md_filled = false;
-  slice_buffer_list_init(&s->to_read_message);
-  slice_buffer_list_init(&s->write_buffer_message);
-  s->reads_needed = false;
-  s->read_closure_scheduled = false;
-  GRPC_CLOSURE_INIT(&s->read_closure, read_state_machine, s,
+  s->ops_needed = false;
+  s->op_closure_scheduled = false;
+  GRPC_CLOSURE_INIT(&s->op_closure, op_state_machine, s,
                     grpc_schedule_on_exec_ctx);
   s->t = t;
   s->closure_at_destroy = NULL;
@@ -425,11 +309,6 @@
       grpc_metadata_batch_clear(exec_ctx, &cs->write_buffer_initial_md);
       cs->write_buffer_initial_md_filled = false;
     }
-    while (!slice_buffer_list_empty(&cs->write_buffer_message)) {
-      slice_buffer_list_append_entry(
-          &s->to_read_message,
-          slice_buffer_list_pophead(&cs->write_buffer_message));
-    }
     if (cs->write_buffer_trailing_md_filled) {
       fill_in_metadata(exec_ctx, s, &cs->write_buffer_trailing_md, 0,
                        &s->to_read_trailing_md, NULL,
@@ -488,9 +367,39 @@
   }
 }
 
+// Call the on_complete closure associated with this stream_op_batch if
+// this stream_op_batch is only one of the pending operations for this
+// stream. This is called when one of the pending operations for the stream
+// is done and about to be NULLed out
+static void complete_if_batch_end_locked(grpc_exec_ctx *exec_ctx,
+                                         inproc_stream *s, grpc_error *error,
+                                         grpc_transport_stream_op_batch *op,
+                                         const char *msg) {
+  int is_sm = (int)(op == s->send_message_op);
+  int is_stm = (int)(op == s->send_trailing_md_op);
+  int is_rim = (int)(op == s->recv_initial_md_op);
+  int is_rm = (int)(op == s->recv_message_op);
+  int is_rtm = (int)(op == s->recv_trailing_md_op);
+
+  if ((is_sm + is_stm + is_rim + is_rm + is_rtm) == 1) {
+    INPROC_LOG(GPR_DEBUG, "%s %p %p %p", msg, s, op, error);
+    GRPC_CLOSURE_SCHED(exec_ctx, op->on_complete, GRPC_ERROR_REF(error));
+  }
+}
+
+static void maybe_schedule_op_closure_locked(grpc_exec_ctx *exec_ctx,
+                                             inproc_stream *s,
+                                             grpc_error *error) {
+  if (s && s->ops_needed && !s->op_closure_scheduled) {
+    GRPC_CLOSURE_SCHED(exec_ctx, &s->op_closure, GRPC_ERROR_REF(error));
+    s->op_closure_scheduled = true;
+    s->ops_needed = false;
+  }
+}
+
 static void fail_helper_locked(grpc_exec_ctx *exec_ctx, inproc_stream *s,
                                grpc_error *error) {
-  INPROC_LOG(GPR_DEBUG, "read_state_machine %p fail_helper", s);
+  INPROC_LOG(GPR_DEBUG, "op_state_machine %p fail_helper", s);
   // If we're failing this side, we need to make sure that
   // we also send or have already sent trailing metadata
   if (!s->trailing_md_sent) {
@@ -512,14 +421,7 @@
       if (other->cancel_other_error == GRPC_ERROR_NONE) {
         other->cancel_other_error = GRPC_ERROR_REF(error);
       }
-      if (other->reads_needed) {
-        if (!other->read_closure_scheduled) {
-          GRPC_CLOSURE_SCHED(exec_ctx, &other->read_closure,
-                             GRPC_ERROR_REF(error));
-          other->read_closure_scheduled = true;
-        }
-        other->reads_needed = false;
-      }
+      maybe_schedule_op_closure_locked(exec_ctx, other, error);
     } else if (s->write_buffer_cancel_error == GRPC_ERROR_NONE) {
       s->write_buffer_cancel_error = GRPC_ERROR_REF(error);
     }
@@ -564,14 +466,9 @@
                        err);
     // Last use of err so no need to REF and then UNREF it
 
-    if ((s->recv_initial_md_op != s->recv_message_op) &&
-        (s->recv_initial_md_op != s->recv_trailing_md_op)) {
-      INPROC_LOG(GPR_DEBUG,
-                 "fail_helper %p scheduling initial-metadata-on-complete %p",
-                 error, s);
-      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_initial_md_op->on_complete,
-                         GRPC_ERROR_REF(error));
-    }
+    complete_if_batch_end_locked(
+        exec_ctx, s, error, s->recv_initial_md_op,
+        "fail_helper scheduling recv-initial-metadata-on-complete");
     s->recv_initial_md_op = NULL;
   }
   if (s->recv_message_op) {
@@ -580,20 +477,30 @@
     GRPC_CLOSURE_SCHED(
         exec_ctx, s->recv_message_op->payload->recv_message.recv_message_ready,
         GRPC_ERROR_REF(error));
-    if (s->recv_message_op != s->recv_trailing_md_op) {
-      INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling message-on-complete %p",
-                 s, error);
-      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete,
-                         GRPC_ERROR_REF(error));
-    }
+    complete_if_batch_end_locked(
+        exec_ctx, s, error, s->recv_message_op,
+        "fail_helper scheduling recv-message-on-complete");
     s->recv_message_op = NULL;
   }
+  if (s->send_message_op) {
+    complete_if_batch_end_locked(
+        exec_ctx, s, error, s->send_message_op,
+        "fail_helper scheduling send-message-on-complete");
+    s->send_message_op = NULL;
+  }
+  if (s->send_trailing_md_op) {
+    complete_if_batch_end_locked(
+        exec_ctx, s, error, s->send_trailing_md_op,
+        "fail_helper scheduling send-trailng-md-on-complete");
+    s->send_trailing_md_op = NULL;
+  }
   if (s->recv_trailing_md_op) {
     INPROC_LOG(GPR_DEBUG,
                "fail_helper %p scheduling trailing-md-on-complete %p", s,
                error);
-    GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
-                       GRPC_ERROR_REF(error));
+    complete_if_batch_end_locked(
+        exec_ctx, s, error, s->recv_trailing_md_op,
+        "fail_helper scheduling recv-trailing-metadata-on-complete");
     s->recv_trailing_md_op = NULL;
   }
   close_other_side_locked(exec_ctx, s, "fail_helper:other_side");
@@ -602,12 +509,61 @@
   GRPC_ERROR_UNREF(error);
 }
 
-static void read_state_machine(grpc_exec_ctx *exec_ctx, void *arg,
-                               grpc_error *error) {
+static void message_transfer_locked(grpc_exec_ctx *exec_ctx,
+                                    inproc_stream *sender,
+                                    inproc_stream *receiver) {
+  size_t remaining =
+      sender->send_message_op->payload->send_message.send_message->length;
+  if (receiver->recv_inited) {
+    grpc_slice_buffer_destroy_internal(exec_ctx, &receiver->recv_message);
+  }
+  grpc_slice_buffer_init(&receiver->recv_message);
+  receiver->recv_inited = true;
+  do {
+    grpc_slice message_slice;
+    grpc_closure unused;
+    GPR_ASSERT(grpc_byte_stream_next(
+        exec_ctx, sender->send_message_op->payload->send_message.send_message,
+        SIZE_MAX, &unused));
+    grpc_error *error = grpc_byte_stream_pull(
+        exec_ctx, sender->send_message_op->payload->send_message.send_message,
+        &message_slice);
+    if (error != GRPC_ERROR_NONE) {
+      cancel_stream_locked(exec_ctx, sender, GRPC_ERROR_REF(error));
+      break;
+    }
+    GPR_ASSERT(error == GRPC_ERROR_NONE);
+    remaining -= GRPC_SLICE_LENGTH(message_slice);
+    grpc_slice_buffer_add(&receiver->recv_message, message_slice);
+  } while (remaining > 0);
+
+  grpc_slice_buffer_stream_init(&receiver->recv_stream, &receiver->recv_message,
+                                0);
+  *receiver->recv_message_op->payload->recv_message.recv_message =
+      &receiver->recv_stream.base;
+  INPROC_LOG(GPR_DEBUG, "message_transfer_locked %p scheduling message-ready",
+             receiver);
+  GRPC_CLOSURE_SCHED(
+      exec_ctx,
+      receiver->recv_message_op->payload->recv_message.recv_message_ready,
+      GRPC_ERROR_NONE);
+  complete_if_batch_end_locked(
+      exec_ctx, sender, GRPC_ERROR_NONE, sender->send_message_op,
+      "message_transfer scheduling sender on_complete");
+  complete_if_batch_end_locked(
+      exec_ctx, receiver, GRPC_ERROR_NONE, receiver->recv_message_op,
+      "message_transfer scheduling receiver on_complete");
+
+  receiver->recv_message_op = NULL;
+  sender->send_message_op = NULL;
+}
+
+static void op_state_machine(grpc_exec_ctx *exec_ctx, void *arg,
+                             grpc_error *error) {
   // This function gets called when we have contents in the unprocessed reads
   // Get what we want based on our ops wanted
   // Schedule our appropriate closures
-  // and then return to reads_needed state if still needed
+  // and then return to ops_needed state if still needed
 
   // Since this is a closure directly invoked by the combiner, it should not
   // unref the error parameter explicitly; the combiner will do that implicitly
@@ -615,12 +571,14 @@
 
   bool needs_close = false;
 
-  INPROC_LOG(GPR_DEBUG, "read_state_machine %p", arg);
+  INPROC_LOG(GPR_DEBUG, "op_state_machine %p", arg);
   inproc_stream *s = (inproc_stream *)arg;
   gpr_mu *mu = &s->t->mu->mu;  // keep aside in case s gets closed
   gpr_mu_lock(mu);
-  s->read_closure_scheduled = false;
+  s->op_closure_scheduled = false;
   // cancellation takes precedence
+  inproc_stream *other = s->other_side;
+
   if (s->cancel_self_error != GRPC_ERROR_NONE) {
     fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(s->cancel_self_error));
     goto done;
@@ -632,89 +590,116 @@
     goto done;
   }
 
-  if (s->recv_initial_md_op) {
-    if (!s->to_read_initial_md_filled) {
-      // We entered the state machine on some other kind of read even though
-      // we still haven't satisfied initial md . That's an error.
-      new_err =
-          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unexpected frame sequencing");
-      INPROC_LOG(GPR_DEBUG,
-                 "read_state_machine %p scheduling on_complete errors for no "
-                 "initial md %p",
-                 s, new_err);
+  if (s->send_message_op && other) {
+    if (other->recv_message_op) {
+      message_transfer_locked(exec_ctx, s, other);
+      maybe_schedule_op_closure_locked(exec_ctx, other, GRPC_ERROR_NONE);
+    } else if (!s->t->is_client &&
+               (s->trailing_md_sent || other->recv_trailing_md_op)) {
+      // A server send will never be matched if the client is waiting
+      // for trailing metadata already
+      complete_if_batch_end_locked(
+          exec_ctx, s, GRPC_ERROR_NONE, s->send_message_op,
+          "op_state_machine scheduling send-message-on-complete");
+      s->send_message_op = NULL;
+    }
+  }
+  // Pause a send trailing metadata if there is still an outstanding
+  // send message unless we know that the send message will never get
+  // matched to a receive. This happens on the client if the server has
+  // already sent status.
+  if (s->send_trailing_md_op &&
+      (!s->send_message_op ||
+       (s->t->is_client &&
+        (s->trailing_md_recvd || s->to_read_trailing_md_filled)))) {
+    grpc_metadata_batch *dest = (other == NULL) ? &s->write_buffer_trailing_md
+                                                : &other->to_read_trailing_md;
+    bool *destfilled = (other == NULL) ? &s->write_buffer_trailing_md_filled
+                                       : &other->to_read_trailing_md_filled;
+    if (*destfilled || s->trailing_md_sent) {
+      // The buffer is already in use; that's an error!
+      INPROC_LOG(GPR_DEBUG, "Extra trailing metadata %p", s);
+      new_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra trailing metadata");
       fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
       goto done;
-    } else if (s->initial_md_recvd) {
+    } else {
+      if (!other || !other->closed) {
+        fill_in_metadata(exec_ctx, s,
+                         s->send_trailing_md_op->payload->send_trailing_metadata
+                             .send_trailing_metadata,
+                         0, dest, NULL, destfilled);
+      }
+      s->trailing_md_sent = true;
+      if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
+        INPROC_LOG(GPR_DEBUG,
+                   "op_state_machine %p scheduling trailing-md-on-complete", s);
+        GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
+                           GRPC_ERROR_NONE);
+        s->recv_trailing_md_op = NULL;
+        needs_close = true;
+      }
+    }
+    maybe_schedule_op_closure_locked(exec_ctx, other, GRPC_ERROR_NONE);
+    complete_if_batch_end_locked(
+        exec_ctx, s, GRPC_ERROR_NONE, s->send_trailing_md_op,
+        "op_state_machine scheduling send-trailing-metadata-on-complete");
+    s->send_trailing_md_op = NULL;
+  }
+  if (s->recv_initial_md_op) {
+    if (s->initial_md_recvd) {
       new_err =
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already recvd initial md");
       INPROC_LOG(
           GPR_DEBUG,
-          "read_state_machine %p scheduling on_complete errors for already "
+          "op_state_machine %p scheduling on_complete errors for already "
           "recvd initial md %p",
           s, new_err);
       fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
       goto done;
     }
 
-    s->initial_md_recvd = true;
-    new_err = fill_in_metadata(
-        exec_ctx, s, &s->to_read_initial_md, s->to_read_initial_md_flags,
-        s->recv_initial_md_op->payload->recv_initial_metadata
-            .recv_initial_metadata,
-        s->recv_initial_md_op->payload->recv_initial_metadata.recv_flags, NULL);
-    s->recv_initial_md_op->payload->recv_initial_metadata.recv_initial_metadata
-        ->deadline = s->deadline;
-    grpc_metadata_batch_clear(exec_ctx, &s->to_read_initial_md);
-    s->to_read_initial_md_filled = false;
-    INPROC_LOG(GPR_DEBUG,
-               "read_state_machine %p scheduling initial-metadata-ready %p", s,
-               new_err);
-    GRPC_CLOSURE_SCHED(exec_ctx,
-                       s->recv_initial_md_op->payload->recv_initial_metadata
-                           .recv_initial_metadata_ready,
-                       GRPC_ERROR_REF(new_err));
-    if ((s->recv_initial_md_op != s->recv_message_op) &&
-        (s->recv_initial_md_op != s->recv_trailing_md_op)) {
-      INPROC_LOG(
-          GPR_DEBUG,
-          "read_state_machine %p scheduling initial-metadata-on-complete %p", s,
-          new_err);
-      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_initial_md_op->on_complete,
+    if (s->to_read_initial_md_filled) {
+      s->initial_md_recvd = true;
+      new_err = fill_in_metadata(
+          exec_ctx, s, &s->to_read_initial_md, s->to_read_initial_md_flags,
+          s->recv_initial_md_op->payload->recv_initial_metadata
+              .recv_initial_metadata,
+          s->recv_initial_md_op->payload->recv_initial_metadata.recv_flags,
+          NULL);
+      s->recv_initial_md_op->payload->recv_initial_metadata
+          .recv_initial_metadata->deadline = s->deadline;
+      grpc_metadata_batch_clear(exec_ctx, &s->to_read_initial_md);
+      s->to_read_initial_md_filled = false;
+      INPROC_LOG(GPR_DEBUG,
+                 "op_state_machine %p scheduling initial-metadata-ready %p", s,
+                 new_err);
+      GRPC_CLOSURE_SCHED(exec_ctx,
+                         s->recv_initial_md_op->payload->recv_initial_metadata
+                             .recv_initial_metadata_ready,
                          GRPC_ERROR_REF(new_err));
-    }
-    s->recv_initial_md_op = NULL;
+      complete_if_batch_end_locked(
+          exec_ctx, s, new_err, s->recv_initial_md_op,
+          "op_state_machine scheduling recv-initial-metadata-on-complete");
+      s->recv_initial_md_op = NULL;
 
-    if (new_err != GRPC_ERROR_NONE) {
-      INPROC_LOG(GPR_DEBUG,
-                 "read_state_machine %p scheduling on_complete errors2 %p", s,
-                 new_err);
-      fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
-      goto done;
+      if (new_err != GRPC_ERROR_NONE) {
+        INPROC_LOG(GPR_DEBUG,
+                   "op_state_machine %p scheduling on_complete errors2 %p", s,
+                   new_err);
+        fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
+        goto done;
+      }
     }
   }
-  if (s->to_read_initial_md_filled) {
-    new_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unexpected recv frame");
-    fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
-    goto done;
-  }
-  if (!slice_buffer_list_empty(&s->to_read_message) && s->recv_message_op) {
-    inproc_slice_byte_stream_init(
-        &s->recv_message_stream,
-        slice_buffer_list_pophead(&s->to_read_message));
-    *s->recv_message_op->payload->recv_message.recv_message =
-        &s->recv_message_stream.base;
-    INPROC_LOG(GPR_DEBUG, "read_state_machine %p scheduling message-ready", s);
-    GRPC_CLOSURE_SCHED(
-        exec_ctx, s->recv_message_op->payload->recv_message.recv_message_ready,
-        GRPC_ERROR_NONE);
-    if (s->recv_message_op != s->recv_trailing_md_op) {
-      INPROC_LOG(GPR_DEBUG,
-                 "read_state_machine %p scheduling message-on-complete %p", s,
-                 new_err);
-      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete,
-                         GRPC_ERROR_REF(new_err));
+  if (s->recv_message_op) {
+    if (other && other->send_message_op) {
+      message_transfer_locked(exec_ctx, other, s);
+      maybe_schedule_op_closure_locked(exec_ctx, other, GRPC_ERROR_NONE);
     }
-    s->recv_message_op = NULL;
+  }
+  if (s->recv_trailing_md_op && s->t->is_client && other &&
+      other->send_message_op) {
+    maybe_schedule_op_closure_locked(exec_ctx, other, GRPC_ERROR_NONE);
   }
   if (s->to_read_trailing_md_filled) {
     if (s->trailing_md_recvd) {
@@ -722,7 +707,7 @@
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already recvd trailing md");
       INPROC_LOG(
           GPR_DEBUG,
-          "read_state_machine %p scheduling on_complete errors for already "
+          "op_state_machine %p scheduling on_complete errors for already "
           "recvd trailing md %p",
           s, new_err);
       fail_helper_locked(exec_ctx, s, GRPC_ERROR_REF(new_err));
@@ -731,21 +716,24 @@
     if (s->recv_message_op != NULL) {
       // This message needs to be wrapped up because it will never be
       // satisfied
-      INPROC_LOG(GPR_DEBUG, "read_state_machine %p scheduling message-ready",
-                 s);
+      INPROC_LOG(GPR_DEBUG, "op_state_machine %p scheduling message-ready", s);
       GRPC_CLOSURE_SCHED(
           exec_ctx,
           s->recv_message_op->payload->recv_message.recv_message_ready,
           GRPC_ERROR_NONE);
-      if (s->recv_message_op != s->recv_trailing_md_op) {
-        INPROC_LOG(GPR_DEBUG,
-                   "read_state_machine %p scheduling message-on-complete %p", s,
-                   new_err);
-        GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete,
-                           GRPC_ERROR_REF(new_err));
-      }
+      complete_if_batch_end_locked(
+          exec_ctx, s, new_err, s->recv_message_op,
+          "op_state_machine scheduling recv-message-on-complete");
       s->recv_message_op = NULL;
     }
+    if ((s->trailing_md_sent || s->t->is_client) && s->send_message_op) {
+      // Nothing further will try to receive from this stream, so finish off
+      // any outstanding send_message op
+      complete_if_batch_end_locked(
+          exec_ctx, s, new_err, s->send_message_op,
+          "op_state_machine scheduling send-message-on-complete");
+      s->send_message_op = NULL;
+    }
     if (s->recv_trailing_md_op != NULL) {
       // We wanted trailing metadata and we got it
       s->trailing_md_recvd = true;
@@ -763,61 +751,65 @@
       //    (If the server hasn't already sent its trailing md, it doesn't have
       //     a final status, so don't mark this op complete)
       if (s->t->is_client || s->trailing_md_sent) {
-        INPROC_LOG(
-            GPR_DEBUG,
-            "read_state_machine %p scheduling trailing-md-on-complete %p", s,
-            new_err);
+        INPROC_LOG(GPR_DEBUG,
+                   "op_state_machine %p scheduling trailing-md-on-complete %p",
+                   s, new_err);
         GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
                            GRPC_ERROR_REF(new_err));
         s->recv_trailing_md_op = NULL;
         needs_close = true;
       } else {
         INPROC_LOG(GPR_DEBUG,
-                   "read_state_machine %p server needs to delay handling "
+                   "op_state_machine %p server needs to delay handling "
                    "trailing-md-on-complete %p",
                    s, new_err);
       }
     } else {
       INPROC_LOG(
           GPR_DEBUG,
-          "read_state_machine %p has trailing md but not yet waiting for it",
-          s);
+          "op_state_machine %p has trailing md but not yet waiting for it", s);
     }
   }
   if (s->trailing_md_recvd && s->recv_message_op) {
     // No further message will come on this stream, so finish off the
     // recv_message_op
-    INPROC_LOG(GPR_DEBUG, "read_state_machine %p scheduling message-ready", s);
+    INPROC_LOG(GPR_DEBUG, "op_state_machine %p scheduling message-ready", s);
     GRPC_CLOSURE_SCHED(
         exec_ctx, s->recv_message_op->payload->recv_message.recv_message_ready,
         GRPC_ERROR_NONE);
-    if (s->recv_message_op != s->recv_trailing_md_op) {
-      INPROC_LOG(GPR_DEBUG,
-                 "read_state_machine %p scheduling message-on-complete %p", s,
-                 new_err);
-      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_message_op->on_complete,
-                         GRPC_ERROR_REF(new_err));
-    }
+    complete_if_batch_end_locked(
+        exec_ctx, s, new_err, s->recv_message_op,
+        "op_state_machine scheduling recv-message-on-complete");
     s->recv_message_op = NULL;
   }
-  if (s->recv_message_op || s->recv_trailing_md_op) {
+  if (s->trailing_md_recvd && (s->trailing_md_sent || s->t->is_client) &&
+      s->send_message_op) {
+    // Nothing further will try to receive from this stream, so finish off
+    // any outstanding send_message op
+    complete_if_batch_end_locked(
+        exec_ctx, s, new_err, s->send_message_op,
+        "op_state_machine scheduling send-message-on-complete");
+    s->send_message_op = NULL;
+  }
+  if (s->send_message_op || s->send_trailing_md_op || s->recv_initial_md_op ||
+      s->recv_message_op || s->recv_trailing_md_op) {
     // Didn't get the item we wanted so we still need to get
     // rescheduled
-    INPROC_LOG(GPR_DEBUG, "read_state_machine %p still needs closure %p %p", s,
-               s->recv_message_op, s->recv_trailing_md_op);
-    s->reads_needed = true;
+    INPROC_LOG(
+        GPR_DEBUG, "op_state_machine %p still needs closure %p %p %p %p %p", s,
+        s->send_message_op, s->send_trailing_md_op, s->recv_initial_md_op,
+        s->recv_message_op, s->recv_trailing_md_op);
+    s->ops_needed = true;
   }
 done:
   if (needs_close) {
-    close_other_side_locked(exec_ctx, s, "read_state_machine");
+    close_other_side_locked(exec_ctx, s, "op_state_machine");
     close_stream_locked(exec_ctx, s);
   }
   gpr_mu_unlock(mu);
   GRPC_ERROR_UNREF(new_err);
 }
 
-static grpc_closure do_nothing_closure;
-
 static bool cancel_stream_locked(grpc_exec_ctx *exec_ctx, inproc_stream *s,
                                  grpc_error *error) {
   bool ret = false;  // was the cancel accepted
@@ -826,14 +818,7 @@
   if (s->cancel_self_error == GRPC_ERROR_NONE) {
     ret = true;
     s->cancel_self_error = GRPC_ERROR_REF(error);
-    if (s->reads_needed) {
-      if (!s->read_closure_scheduled) {
-        GRPC_CLOSURE_SCHED(exec_ctx, &s->read_closure,
-                           GRPC_ERROR_REF(s->cancel_self_error));
-        s->read_closure_scheduled = true;
-      }
-      s->reads_needed = false;
-    }
+    maybe_schedule_op_closure_locked(exec_ctx, s, s->cancel_self_error);
     // Send trailing md to the other side indicating cancellation, even if we
     // already have
     s->trailing_md_sent = true;
@@ -853,14 +838,8 @@
       if (other->cancel_other_error == GRPC_ERROR_NONE) {
         other->cancel_other_error = GRPC_ERROR_REF(s->cancel_self_error);
       }
-      if (other->reads_needed) {
-        if (!other->read_closure_scheduled) {
-          GRPC_CLOSURE_SCHED(exec_ctx, &other->read_closure,
-                             GRPC_ERROR_REF(other->cancel_other_error));
-          other->read_closure_scheduled = true;
-        }
-        other->reads_needed = false;
-      }
+      maybe_schedule_op_closure_locked(exec_ctx, other,
+                                       other->cancel_other_error);
     } else if (s->write_buffer_cancel_error == GRPC_ERROR_NONE) {
       s->write_buffer_cancel_error = GRPC_ERROR_REF(s->cancel_self_error);
     }
@@ -869,11 +848,9 @@
     // couldn't complete that because we hadn't yet sent out trailing
     // md, now's the chance
     if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
-      INPROC_LOG(GPR_DEBUG,
-                 "cancel_stream %p scheduling trailing-md-on-complete %p", s,
-                 s->cancel_self_error);
-      GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
-                         GRPC_ERROR_REF(s->cancel_self_error));
+      complete_if_batch_end_locked(
+          exec_ctx, s, s->cancel_self_error, s->recv_trailing_md_op,
+          "cancel_stream scheduling trailing-md-on-complete");
       s->recv_trailing_md_op = NULL;
     }
   }
@@ -918,7 +895,8 @@
     // already self-canceled so still give it an error
     error = GRPC_ERROR_REF(s->cancel_self_error);
   } else {
-    INPROC_LOG(GPR_DEBUG, "perform_stream_op %p%s%s%s%s%s%s", s,
+    INPROC_LOG(GPR_DEBUG, "perform_stream_op %p %s%s%s%s%s%s%s", s,
+               s->t->is_client ? "client" : "server",
                op->send_initial_metadata ? " send_initial_metadata" : "",
                op->send_message ? " send_message" : "",
                op->send_trailing_metadata ? " send_trailing_metadata" : "",
@@ -929,10 +907,9 @@
 
   bool needs_close = false;
 
+  inproc_stream *other = s->other_side;
   if (error == GRPC_ERROR_NONE &&
-      (op->send_initial_metadata || op->send_message ||
-       op->send_trailing_metadata)) {
-    inproc_stream *other = s->other_side;
+      (op->send_initial_metadata || op->send_trailing_metadata)) {
     if (s->t->is_closed) {
       error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Endpoint already shutdown");
     }
@@ -948,7 +925,7 @@
         INPROC_LOG(GPR_DEBUG, "Extra initial metadata %p", s);
         error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra initial metadata");
       } else {
-        if (!other->closed) {
+        if (!other || !other->closed) {
           fill_in_metadata(
               exec_ctx, s,
               op->payload->send_initial_metadata.send_initial_metadata,
@@ -963,72 +940,21 @@
           s->initial_md_sent = true;
         }
       }
-    }
-    if (error == GRPC_ERROR_NONE && op->send_message) {
-      size_t remaining = op->payload->send_message.send_message->length;
-      grpc_slice_buffer *dest = slice_buffer_list_append(
-          (other == NULL) ? &s->write_buffer_message : &other->to_read_message);
-      do {
-        grpc_slice message_slice;
-        grpc_closure unused;
-        GPR_ASSERT(grpc_byte_stream_next(exec_ctx,
-                                         op->payload->send_message.send_message,
-                                         SIZE_MAX, &unused));
-        error = grpc_byte_stream_pull(
-            exec_ctx, op->payload->send_message.send_message, &message_slice);
-        if (error != GRPC_ERROR_NONE) {
-          cancel_stream_locked(exec_ctx, s, GRPC_ERROR_REF(error));
-          break;
-        }
-        GPR_ASSERT(error == GRPC_ERROR_NONE);
-        remaining -= GRPC_SLICE_LENGTH(message_slice);
-        grpc_slice_buffer_add(dest, message_slice);
-      } while (remaining != 0);
-      grpc_byte_stream_destroy(exec_ctx,
-                               op->payload->send_message.send_message);
-    }
-    if (error == GRPC_ERROR_NONE && op->send_trailing_metadata) {
-      grpc_metadata_batch *dest = (other == NULL) ? &s->write_buffer_trailing_md
-                                                  : &other->to_read_trailing_md;
-      bool *destfilled = (other == NULL) ? &s->write_buffer_trailing_md_filled
-                                         : &other->to_read_trailing_md_filled;
-      if (*destfilled || s->trailing_md_sent) {
-        // The buffer is already in use; that's an error!
-        INPROC_LOG(GPR_DEBUG, "Extra trailing metadata %p", s);
-        error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra trailing metadata");
-      } else {
-        if (!other->closed) {
-          fill_in_metadata(
-              exec_ctx, s,
-              op->payload->send_trailing_metadata.send_trailing_metadata, 0,
-              dest, NULL, destfilled);
-        }
-        s->trailing_md_sent = true;
-        if (!s->t->is_client && s->trailing_md_recvd &&
-            s->recv_trailing_md_op) {
-          INPROC_LOG(GPR_DEBUG,
-                     "perform_stream_op %p scheduling trailing-md-on-complete",
-                     s);
-          GRPC_CLOSURE_SCHED(exec_ctx, s->recv_trailing_md_op->on_complete,
-                             GRPC_ERROR_NONE);
-          s->recv_trailing_md_op = NULL;
-          needs_close = true;
-        }
-      }
-    }
-    if (other != NULL && other->reads_needed) {
-      if (!other->read_closure_scheduled) {
-        GRPC_CLOSURE_SCHED(exec_ctx, &other->read_closure, error);
-        other->read_closure_scheduled = true;
-      }
-      other->reads_needed = false;
+      maybe_schedule_op_closure_locked(exec_ctx, other, error);
     }
   }
+
   if (error == GRPC_ERROR_NONE &&
-      (op->recv_initial_metadata || op->recv_message ||
+      (op->send_message || op->send_trailing_metadata ||
+       op->recv_initial_metadata || op->recv_message ||
        op->recv_trailing_metadata)) {
-    // If there are any reads, mark it so that the read closure will react to
-    // them
+    // Mark ops that need to be processed by the closure
+    if (op->send_message) {
+      s->send_message_op = op;
+    }
+    if (op->send_trailing_metadata) {
+      s->send_trailing_md_op = op;
+    }
     if (op->recv_initial_metadata) {
       s->recv_initial_md_op = op;
     }
@@ -1040,25 +966,28 @@
     }
 
     // We want to initiate the closure if:
-    // 1. There is initial metadata and something ready to take that
-    // 2. There is a message and something ready to take it
-    // 3. There is trailing metadata, even if nothing specifically wants
-    //    that because that can shut down the message as well
-    if ((s->to_read_initial_md_filled && op->recv_initial_metadata) ||
-        ((!slice_buffer_list_empty(&s->to_read_message) ||
-          s->trailing_md_recvd) &&
-         op->recv_message) ||
-        (s->to_read_trailing_md_filled)) {
-      if (!s->read_closure_scheduled) {
-        GRPC_CLOSURE_SCHED(exec_ctx, &s->read_closure, GRPC_ERROR_NONE);
-        s->read_closure_scheduled = true;
+    // 1. We want to send a message and the other side wants to receive or end
+    // 2. We want to send trailing metadata and there isn't an unmatched send
+    // 3. We want initial metadata and the other side has sent it
+    // 4. We want to receive a message and there is a message ready
+    // 5. There is trailing metadata, even if nothing specifically wants
+    //    that because that can shut down the receive message as well
+    if ((op->send_message && other && ((other->recv_message_op != NULL) ||
+                                       (other->recv_trailing_md_op != NULL))) ||
+        (op->send_trailing_metadata && !op->send_message) ||
+        (op->recv_initial_metadata && s->to_read_initial_md_filled) ||
+        (op->recv_message && other && (other->send_message_op != NULL)) ||
+        (s->to_read_trailing_md_filled || s->trailing_md_recvd)) {
+      if (!s->op_closure_scheduled) {
+        GRPC_CLOSURE_SCHED(exec_ctx, &s->op_closure, GRPC_ERROR_NONE);
+        s->op_closure_scheduled = true;
       }
     } else {
-      s->reads_needed = true;
+      s->ops_needed = true;
     }
   } else {
     if (error != GRPC_ERROR_NONE) {
-      // Schedule op's read closures that we didn't push to read state machine
+      // Schedule op's closures that we didn't push to op state machine
       if (op->recv_initial_metadata) {
         INPROC_LOG(
             GPR_DEBUG,
diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h
index 2837174..1896d35 100644
--- a/src/core/lib/channel/channel_args.h
+++ b/src/core/lib/channel/channel_args.h
@@ -157,4 +157,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */
diff --git a/src/core/lib/channel/connected_channel.h b/src/core/lib/channel/connected_channel.h
index b55a108..4615727 100644
--- a/src/core/lib/channel/connected_channel.h
+++ b/src/core/lib/channel/connected_channel.h
@@ -38,4 +38,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H */
diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h
index 51ee56a..8ed38c1 100644
--- a/src/core/lib/channel/handshaker.h
+++ b/src/core/lib/channel/handshaker.h
@@ -172,4 +172,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */
diff --git a/src/core/lib/channel/handshaker_factory.h b/src/core/lib/channel/handshaker_factory.h
index 2a130de..59008ad 100644
--- a/src/core/lib/channel/handshaker_factory.h
+++ b/src/core/lib/channel/handshaker_factory.h
@@ -56,4 +56,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H */
diff --git a/src/core/lib/channel/handshaker_registry.h b/src/core/lib/channel/handshaker_registry.h
index e96bf06..ddd280b 100644
--- a/src/core/lib/channel/handshaker_registry.h
+++ b/src/core/lib/channel/handshaker_registry.h
@@ -53,4 +53,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H */
diff --git a/src/core/lib/compression/algorithm_metadata.h b/src/core/lib/compression/algorithm_metadata.h
index 3eb7088..17caf58 100644
--- a/src/core/lib/compression/algorithm_metadata.h
+++ b/src/core/lib/compression/algorithm_metadata.h
@@ -57,4 +57,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */
diff --git a/src/core/lib/compression/message_compress.h b/src/core/lib/compression/message_compress.h
index d2545a0..fffe175 100644
--- a/src/core/lib/compression/message_compress.h
+++ b/src/core/lib/compression/message_compress.h
@@ -44,4 +44,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H */
diff --git a/src/core/lib/debug/stats_data.cc b/src/core/lib/debug/stats_data.cc
index 5bd7884..5d737c5 100644
--- a/src/core/lib/debug/stats_data.cc
+++ b/src/core/lib/debug/stats_data.cc
@@ -104,6 +104,10 @@
     "combiner_locks_scheduled_items",
     "combiner_locks_scheduled_final_items",
     "combiner_locks_offloaded",
+    "call_combiner_locks_initiated",
+    "call_combiner_locks_scheduled_items",
+    "call_combiner_set_notify_on_cancel",
+    "call_combiner_cancelled",
     "executor_scheduled_short_items",
     "executor_scheduled_long_items",
     "executor_scheduled_to_self",
@@ -112,6 +116,9 @@
     "executor_push_retries",
     "server_requested_calls",
     "server_slowpath_requests_queued",
+    "cq_ev_queue_trylock_failures",
+    "cq_ev_queue_trylock_successes",
+    "cq_ev_queue_transient_pop_failures",
 };
 const char *grpc_stats_counter_doc[GRPC_STATS_COUNTER_COUNT] = {
     "Number of client side calls created by this process",
@@ -210,6 +217,11 @@
     "Number of items scheduled against combiner locks",
     "Number of final items scheduled against combiner locks",
     "Number of combiner locks offloaded to different threads",
+    "Number of call combiner lock entries by process (first items queued to a "
+    "call combiner)",
+    "Number of items scheduled against call combiner locks",
+    "Number of times a cancellation callback was set on a call combiner",
+    "Number of times a call combiner was cancelled",
     "Number of finite runtime closures scheduled against the executor (gRPC "
     "thread pool)",
     "Number of potentially infinite runtime closures scheduled against the "
@@ -222,6 +234,12 @@
     "How many calls were requested (not necessarily received) by the server",
     "How many times was the server slow path taken (indicates too few "
     "outstanding requests)",
+    "Number of lock (trylock) acquisition failures on completion queue event "
+    "queue. High value here indicates high contention on completion queues",
+    "Number of lock (trylock) acquisition successes on completion queue event "
+    "queue.",
+    "Number of times NULL was popped out of completion queue's event queue "
+    "even though the event queue was not empty",
 };
 const char *grpc_stats_histogram_name[GRPC_STATS_HISTOGRAM_COUNT] = {
     "call_initial_size",
diff --git a/src/core/lib/debug/stats_data.h b/src/core/lib/debug/stats_data.h
index d8e4e7d..031942d 100644
--- a/src/core/lib/debug/stats_data.h
+++ b/src/core/lib/debug/stats_data.h
@@ -110,6 +110,10 @@
   GRPC_STATS_COUNTER_COMBINER_LOCKS_SCHEDULED_ITEMS,
   GRPC_STATS_COUNTER_COMBINER_LOCKS_SCHEDULED_FINAL_ITEMS,
   GRPC_STATS_COUNTER_COMBINER_LOCKS_OFFLOADED,
+  GRPC_STATS_COUNTER_CALL_COMBINER_LOCKS_INITIATED,
+  GRPC_STATS_COUNTER_CALL_COMBINER_LOCKS_SCHEDULED_ITEMS,
+  GRPC_STATS_COUNTER_CALL_COMBINER_SET_NOTIFY_ON_CANCEL,
+  GRPC_STATS_COUNTER_CALL_COMBINER_CANCELLED,
   GRPC_STATS_COUNTER_EXECUTOR_SCHEDULED_SHORT_ITEMS,
   GRPC_STATS_COUNTER_EXECUTOR_SCHEDULED_LONG_ITEMS,
   GRPC_STATS_COUNTER_EXECUTOR_SCHEDULED_TO_SELF,
@@ -118,6 +122,9 @@
   GRPC_STATS_COUNTER_EXECUTOR_PUSH_RETRIES,
   GRPC_STATS_COUNTER_SERVER_REQUESTED_CALLS,
   GRPC_STATS_COUNTER_SERVER_SLOWPATH_REQUESTS_QUEUED,
+  GRPC_STATS_COUNTER_CQ_EV_QUEUE_TRYLOCK_FAILURES,
+  GRPC_STATS_COUNTER_CQ_EV_QUEUE_TRYLOCK_SUCCESSES,
+  GRPC_STATS_COUNTER_CQ_EV_QUEUE_TRANSIENT_POP_FAILURES,
   GRPC_STATS_COUNTER_COUNT
 } grpc_stats_counters;
 extern const char *grpc_stats_counter_name[GRPC_STATS_COUNTER_COUNT];
@@ -404,6 +411,17 @@
 #define GRPC_STATS_INC_COMBINER_LOCKS_OFFLOADED(exec_ctx) \
   GRPC_STATS_INC_COUNTER((exec_ctx),                      \
                          GRPC_STATS_COUNTER_COMBINER_LOCKS_OFFLOADED)
+#define GRPC_STATS_INC_CALL_COMBINER_LOCKS_INITIATED(exec_ctx) \
+  GRPC_STATS_INC_COUNTER((exec_ctx),                           \
+                         GRPC_STATS_COUNTER_CALL_COMBINER_LOCKS_INITIATED)
+#define GRPC_STATS_INC_CALL_COMBINER_LOCKS_SCHEDULED_ITEMS(exec_ctx) \
+  GRPC_STATS_INC_COUNTER(                                            \
+      (exec_ctx), GRPC_STATS_COUNTER_CALL_COMBINER_LOCKS_SCHEDULED_ITEMS)
+#define GRPC_STATS_INC_CALL_COMBINER_SET_NOTIFY_ON_CANCEL(exec_ctx) \
+  GRPC_STATS_INC_COUNTER(                                           \
+      (exec_ctx), GRPC_STATS_COUNTER_CALL_COMBINER_SET_NOTIFY_ON_CANCEL)
+#define GRPC_STATS_INC_CALL_COMBINER_CANCELLED(exec_ctx) \
+  GRPC_STATS_INC_COUNTER((exec_ctx), GRPC_STATS_COUNTER_CALL_COMBINER_CANCELLED)
 #define GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS(exec_ctx) \
   GRPC_STATS_INC_COUNTER((exec_ctx),                            \
                          GRPC_STATS_COUNTER_EXECUTOR_SCHEDULED_SHORT_ITEMS)
@@ -425,6 +443,15 @@
 #define GRPC_STATS_INC_SERVER_SLOWPATH_REQUESTS_QUEUED(exec_ctx) \
   GRPC_STATS_INC_COUNTER((exec_ctx),                             \
                          GRPC_STATS_COUNTER_SERVER_SLOWPATH_REQUESTS_QUEUED)
+#define GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_FAILURES(exec_ctx) \
+  GRPC_STATS_INC_COUNTER((exec_ctx),                          \
+                         GRPC_STATS_COUNTER_CQ_EV_QUEUE_TRYLOCK_FAILURES)
+#define GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_SUCCESSES(exec_ctx) \
+  GRPC_STATS_INC_COUNTER((exec_ctx),                           \
+                         GRPC_STATS_COUNTER_CQ_EV_QUEUE_TRYLOCK_SUCCESSES)
+#define GRPC_STATS_INC_CQ_EV_QUEUE_TRANSIENT_POP_FAILURES(exec_ctx) \
+  GRPC_STATS_INC_COUNTER(                                           \
+      (exec_ctx), GRPC_STATS_COUNTER_CQ_EV_QUEUE_TRANSIENT_POP_FAILURES)
 #define GRPC_STATS_INC_CALL_INITIAL_SIZE(exec_ctx, value) \
   grpc_stats_inc_call_initial_size((exec_ctx), (int)(value))
 void grpc_stats_inc_call_initial_size(grpc_exec_ctx *exec_ctx, int x);
diff --git a/src/core/lib/debug/stats_data.yaml b/src/core/lib/debug/stats_data.yaml
index 5c0ab22..af45530 100644
--- a/src/core/lib/debug/stats_data.yaml
+++ b/src/core/lib/debug/stats_data.yaml
@@ -245,6 +245,16 @@
   doc: Number of final items scheduled against combiner locks
 - counter: combiner_locks_offloaded
   doc: Number of combiner locks offloaded to different threads
+# call combiner locks
+- counter: call_combiner_locks_initiated
+  doc: Number of call combiner lock entries by process
+       (first items queued to a call combiner)
+- counter: call_combiner_locks_scheduled_items
+  doc: Number of items scheduled against call combiner locks
+- counter: call_combiner_set_notify_on_cancel
+  doc: Number of times a cancellation callback was set on a call combiner
+- counter: call_combiner_cancelled
+  doc: Number of times a call combiner was cancelled
 # executor
 - counter: executor_scheduled_short_items
   doc: Number of finite runtime closures scheduled against the executor
@@ -272,4 +282,13 @@
 - counter: server_slowpath_requests_queued
   doc: How many times was the server slow path taken (indicates too few
        outstanding requests)
-
+# cq
+- counter: cq_ev_queue_trylock_failures
+  doc: Number of lock (trylock) acquisition failures on completion queue event
+       queue. High value here indicates high contention on completion queues
+- counter: cq_ev_queue_trylock_successes
+  doc: Number of lock (trylock) acquisition successes on completion queue event
+       queue.
+- counter: cq_ev_queue_transient_pop_failures
+  doc: Number of times NULL was popped out of completion queue's event queue
+       even though the event queue was not empty
diff --git a/src/core/lib/debug/stats_data_bq_schema.sql b/src/core/lib/debug/stats_data_bq_schema.sql
index 5486997..04b6d47 100644
--- a/src/core/lib/debug/stats_data_bq_schema.sql
+++ b/src/core/lib/debug/stats_data_bq_schema.sql
@@ -79,6 +79,10 @@
 combiner_locks_scheduled_items_per_iteration:FLOAT,
 combiner_locks_scheduled_final_items_per_iteration:FLOAT,
 combiner_locks_offloaded_per_iteration:FLOAT,
+call_combiner_locks_initiated_per_iteration:FLOAT,
+call_combiner_locks_scheduled_items_per_iteration:FLOAT,
+call_combiner_set_notify_on_cancel_per_iteration:FLOAT,
+call_combiner_cancelled_per_iteration:FLOAT,
 executor_scheduled_short_items_per_iteration:FLOAT,
 executor_scheduled_long_items_per_iteration:FLOAT,
 executor_scheduled_to_self_per_iteration:FLOAT,
@@ -86,4 +90,7 @@
 executor_queue_drained_per_iteration:FLOAT,
 executor_push_retries_per_iteration:FLOAT,
 server_requested_calls_per_iteration:FLOAT,
-server_slowpath_requests_queued_per_iteration:FLOAT
+server_slowpath_requests_queued_per_iteration:FLOAT,
+cq_ev_queue_trylock_failures_per_iteration:FLOAT,
+cq_ev_queue_trylock_successes_per_iteration:FLOAT,
+cq_ev_queue_transient_pop_failures_per_iteration:FLOAT
diff --git a/src/core/lib/http/format_request.h b/src/core/lib/http/format_request.h
index a559aac..2e77e86 100644
--- a/src/core/lib/http/format_request.h
+++ b/src/core/lib/http/format_request.h
@@ -37,4 +37,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_HTTP_FORMAT_REQUEST_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_HTTP_FORMAT_REQUEST_H */
diff --git a/src/core/lib/http/httpcli.h b/src/core/lib/http/httpcli.h
index 3e6bdc0..76b790f 100644
--- a/src/core/lib/http/httpcli.h
+++ b/src/core/lib/http/httpcli.h
@@ -131,4 +131,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_HTTP_HTTPCLI_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_HTTP_HTTPCLI_H */
diff --git a/src/core/lib/http/httpcli_security_connector.cc b/src/core/lib/http/httpcli_security_connector.cc
index ef6c4a5..d832dac 100644
--- a/src/core/lib/http/httpcli_security_connector.cc
+++ b/src/core/lib/http/httpcli_security_connector.cc
@@ -91,8 +91,17 @@
   tsi_peer_destruct(&peer);
 }
 
+static int httpcli_ssl_cmp(grpc_security_connector *sc1,
+                           grpc_security_connector *sc2) {
+  grpc_httpcli_ssl_channel_security_connector *c1 =
+      (grpc_httpcli_ssl_channel_security_connector *)sc1;
+  grpc_httpcli_ssl_channel_security_connector *c2 =
+      (grpc_httpcli_ssl_channel_security_connector *)sc2;
+  return strcmp(c1->secure_peer_name, c2->secure_peer_name);
+}
+
 static grpc_security_connector_vtable httpcli_ssl_vtable = {
-    httpcli_ssl_destroy, httpcli_ssl_check_peer};
+    httpcli_ssl_destroy, httpcli_ssl_check_peer, httpcli_ssl_cmp};
 
 static grpc_security_status httpcli_ssl_channel_security_connector_create(
     grpc_exec_ctx *exec_ctx, const char *pem_root_certs,
@@ -123,6 +132,10 @@
     *sc = NULL;
     return GRPC_SECURITY_ERROR;
   }
+  // We don't actually need a channel credentials object in this case,
+  // but we set it to a non-NULL address so that we don't trigger
+  // assertions in grpc_channel_security_connector_cmp().
+  c->base.channel_creds = (grpc_channel_credentials *)1;
   c->base.add_handshakers = httpcli_ssl_add_handshakers;
   *sc = &c->base;
   return GRPC_SECURITY_OK;
diff --git a/src/core/lib/http/parser.h b/src/core/lib/http/parser.h
index 5484948..d2bda6a 100644
--- a/src/core/lib/http/parser.h
+++ b/src/core/lib/http/parser.h
@@ -117,4 +117,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_HTTP_PARSER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_HTTP_PARSER_H */
diff --git a/src/core/lib/iomgr/call_combiner.cc b/src/core/lib/iomgr/call_combiner.cc
index bab3df0..d457196 100644
--- a/src/core/lib/iomgr/call_combiner.cc
+++ b/src/core/lib/iomgr/call_combiner.cc
@@ -21,6 +21,8 @@
 #include <inttypes.h>
 
 #include <grpc/support/log.h>
+#include "src/core/lib/debug/stats.h"
+#include "src/core/lib/profiling/timers.h"
 
 grpc_tracer_flag grpc_call_combiner_trace =
     GRPC_TRACER_INITIALIZER(false, "call_combiner");
@@ -60,6 +62,7 @@
                               grpc_closure* closure,
                               grpc_error* error DEBUG_ARGS,
                               const char* reason) {
+  GPR_TIMER_BEGIN("call_combiner_start", 0);
   if (GRPC_TRACER_ON(grpc_call_combiner_trace)) {
     gpr_log(GPR_DEBUG,
             "==> grpc_call_combiner_start() [%p] closure=%p [" DEBUG_FMT_STR
@@ -73,7 +76,10 @@
     gpr_log(GPR_DEBUG, "  size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
             prev_size + 1);
   }
+  GRPC_STATS_INC_CALL_COMBINER_LOCKS_SCHEDULED_ITEMS(exec_ctx);
   if (prev_size == 0) {
+    GRPC_STATS_INC_CALL_COMBINER_LOCKS_INITIATED(exec_ctx);
+    GPR_TIMER_MARK("call_combiner_initiate", 0);
     if (GRPC_TRACER_ON(grpc_call_combiner_trace)) {
       gpr_log(GPR_DEBUG, "  EXECUTING IMMEDIATELY");
     }
@@ -87,11 +93,13 @@
     closure->error_data.error = error;
     gpr_mpscq_push(&call_combiner->queue, (gpr_mpscq_node*)closure);
   }
+  GPR_TIMER_END("call_combiner_start", 0);
 }
 
 void grpc_call_combiner_stop(grpc_exec_ctx* exec_ctx,
                              grpc_call_combiner* call_combiner DEBUG_ARGS,
                              const char* reason) {
+  GPR_TIMER_BEGIN("call_combiner_stop", 0);
   if (GRPC_TRACER_ON(grpc_call_combiner_trace)) {
     gpr_log(GPR_DEBUG,
             "==> grpc_call_combiner_stop() [%p] [" DEBUG_FMT_STR "%s]",
@@ -130,11 +138,13 @@
   } else if (GRPC_TRACER_ON(grpc_call_combiner_trace)) {
     gpr_log(GPR_DEBUG, "  queue empty");
   }
+  GPR_TIMER_END("call_combiner_stop", 0);
 }
 
 void grpc_call_combiner_set_notify_on_cancel(grpc_exec_ctx* exec_ctx,
                                              grpc_call_combiner* call_combiner,
                                              grpc_closure* closure) {
+  GRPC_STATS_INC_CALL_COMBINER_SET_NOTIFY_ON_CANCEL(exec_ctx);
   while (true) {
     // Decode original state.
     gpr_atm original_state = gpr_atm_acq_load(&call_combiner->cancel_state);
@@ -179,6 +189,7 @@
 void grpc_call_combiner_cancel(grpc_exec_ctx* exec_ctx,
                                grpc_call_combiner* call_combiner,
                                grpc_error* error) {
+  GRPC_STATS_INC_CALL_COMBINER_CANCELLED(exec_ctx);
   while (true) {
     gpr_atm original_state = gpr_atm_acq_load(&call_combiner->cancel_state);
     grpc_error* original_error = decode_cancel_state_error(original_state);
diff --git a/src/core/lib/iomgr/combiner.cc b/src/core/lib/iomgr/combiner.cc
index 0e707ef..53f4b7e 100644
--- a/src/core/lib/iomgr/combiner.cc
+++ b/src/core/lib/iomgr/combiner.cc
@@ -165,6 +165,7 @@
                               lock, cl, last));
   if (last == 1) {
     GRPC_STATS_INC_COMBINER_LOCKS_INITIATED(exec_ctx);
+    GPR_TIMER_MARK("combiner.initiated", 0);
     gpr_atm_no_barrier_store(&lock->initiating_exec_ctx_or_null,
                              (gpr_atm)exec_ctx);
     // first element on this list: add it to the list of combiner locks
diff --git a/src/core/lib/iomgr/endpoint.cc b/src/core/lib/iomgr/endpoint.cc
index 37cce33..5eab1d3 100644
--- a/src/core/lib/iomgr/endpoint.cc
+++ b/src/core/lib/iomgr/endpoint.cc
@@ -39,6 +39,12 @@
   ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set);
 }
 
+void grpc_endpoint_delete_from_pollset_set(grpc_exec_ctx* exec_ctx,
+                                           grpc_endpoint* ep,
+                                           grpc_pollset_set* pollset_set) {
+  ep->vtable->delete_from_pollset_set(exec_ctx, ep, pollset_set);
+}
+
 void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
                             grpc_error* why) {
   ep->vtable->shutdown(exec_ctx, ep, why);
diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h
index 16ff0ab..92964e0 100644
--- a/src/core/lib/iomgr/endpoint.h
+++ b/src/core/lib/iomgr/endpoint.h
@@ -45,6 +45,8 @@
                          grpc_pollset *pollset);
   void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                              grpc_pollset_set *pollset);
+  void (*delete_from_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                  grpc_pollset_set *pollset);
   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);
@@ -85,14 +87,19 @@
                             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
-   this endpoint are considered */
+/* Add an endpoint to a pollset or pollset_set, so that when the pollset is
+   polled, events from this endpoint are considered */
 void grpc_endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                                   grpc_pollset *pollset);
 void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx,
                                       grpc_endpoint *ep,
                                       grpc_pollset_set *pollset_set);
 
+/* Delete an endpoint from a pollset_set */
+void grpc_endpoint_delete_from_pollset_set(grpc_exec_ctx *exec_ctx,
+                                           grpc_endpoint *ep,
+                                           grpc_pollset_set *pollset_set);
+
 grpc_resource_user *grpc_endpoint_get_resource_user(grpc_endpoint *endpoint);
 
 struct grpc_endpoint {
@@ -103,4 +110,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_H */
diff --git a/src/core/lib/iomgr/endpoint_pair.h b/src/core/lib/iomgr/endpoint_pair.h
index f883002..ee91795 100644
--- a/src/core/lib/iomgr/endpoint_pair.h
+++ b/src/core/lib/iomgr/endpoint_pair.h
@@ -37,4 +37,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_PAIR_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_PAIR_H */
diff --git a/src/core/lib/iomgr/error_internal.h b/src/core/lib/iomgr/error_internal.h
index f718e06..8746d5d 100644
--- a/src/core/lib/iomgr/error_internal.h
+++ b/src/core/lib/iomgr/error_internal.h
@@ -65,4 +65,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H */
diff --git a/src/core/lib/iomgr/ev_epoll1_linux.h b/src/core/lib/iomgr/ev_epoll1_linux.h
index 66fd826..b437032 100644
--- a/src/core/lib/iomgr/ev_epoll1_linux.h
+++ b/src/core/lib/iomgr/ev_epoll1_linux.h
@@ -34,4 +34,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL1_LINUX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL1_LINUX_H */
diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc
index 59dd8fd..fa6d79c 100644
--- a/src/core/lib/iomgr/ev_epollex_linux.cc
+++ b/src/core/lib/iomgr/ev_epollex_linux.cc
@@ -30,6 +30,7 @@
 #include <pthread.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
 #include <unistd.h>
 
 #include <grpc/support/alloc.h>
@@ -49,100 +50,97 @@
 #include "src/core/lib/profiling/timers.h"
 #include "src/core/lib/support/spinlock.h"
 
-/*******************************************************************************
- * Polling object
- */
-typedef enum {
-  PO_POLLING_GROUP,
-  PO_POLLSET_SET,
-  PO_POLLSET,
-  PO_FD,
-  /* ordering is important: we always want to lock pollsets before fds:
-     this guarantees that using an fd as a pollable is safe */
-  PO_EMPTY_POLLABLE,
-  PO_COUNT
-} polling_obj_type;
+// debug aid: create workers on the heap (allows asan to spot
+// use-after-destruction)
+//#define GRPC_EPOLLEX_CREATE_WORKERS_ON_HEAP 1
 
-typedef struct polling_obj polling_obj;
-typedef struct polling_group polling_group;
+#define MAX_EPOLL_EVENTS 100
+#define MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL 5
 
-struct polling_obj {
-  gpr_mu mu;
-  polling_obj_type type;
-  polling_group *group;
-  struct polling_obj *next;
-  struct polling_obj *prev;
-};
-
-struct polling_group {
-  polling_obj po;
-  gpr_refcount refs;
-};
-
-static void po_init(polling_obj *po, polling_obj_type type);
-static void po_destroy(polling_obj *po);
-static void po_join(grpc_exec_ctx *exec_ctx, polling_obj *a, polling_obj *b);
-static int po_cmp(polling_obj *a, polling_obj *b);
-
-static void pg_create(grpc_exec_ctx *exec_ctx, polling_obj **initial_po,
-                      size_t initial_po_count);
-static polling_group *pg_ref(polling_group *pg);
-static void pg_unref(polling_group *pg);
-static void pg_merge(grpc_exec_ctx *exec_ctx, polling_group *a,
-                     polling_group *b);
-static void pg_join(grpc_exec_ctx *exec_ctx, polling_group *pg,
-                    polling_obj *po);
+#ifndef NDEBUG
+grpc_tracer_flag grpc_trace_pollable_refcount =
+    GRPC_TRACER_INITIALIZER(false, "pollable_refcount");
+#endif
 
 /*******************************************************************************
  * pollable Declarations
  */
 
-typedef struct pollable {
-  polling_obj po;
+typedef enum { PO_MULTI, PO_FD, PO_EMPTY } pollable_type;
+
+typedef struct pollable pollable;
+
+/// A pollable is something that can be polled: it has an epoll set to poll on,
+/// and a wakeup fd for kicks
+/// There are three broad types:
+///  - PO_EMPTY - the empty pollable, used before file descriptors are added to
+///               a pollset
+///  - PO_FD - a pollable containing only one FD - used to optimize single-fd
+///            pollsets (which are common with synchronous api usage)
+///  - PO_MULTI - a pollable containing many fds
+struct pollable {
+  pollable_type type;  // immutable
+  gpr_refcount refs;
+
   int epfd;
   grpc_wakeup_fd wakeup;
-  grpc_pollset_worker *root_worker;
-} pollable;
 
-static const char *polling_obj_type_string(polling_obj_type t) {
+  // only for type fd... one ref to the owner fd
+  grpc_fd *owner_fd;
+
+  grpc_pollset_set *pollset_set;
+  pollable *next;
+  pollable *prev;
+
+  gpr_mu mu;
+  grpc_pollset_worker *root_worker;
+
+  int event_cursor;
+  int event_count;
+  struct epoll_event events[MAX_EPOLL_EVENTS];
+};
+
+static const char *pollable_type_string(pollable_type t) {
   switch (t) {
-    case PO_POLLING_GROUP:
-      return "polling_group";
-    case PO_POLLSET_SET:
-      return "pollset_set";
-    case PO_POLLSET:
+    case PO_MULTI:
       return "pollset";
     case PO_FD:
       return "fd";
-    case PO_EMPTY_POLLABLE:
-      return "empty_pollable";
-    case PO_COUNT:
-      return "<invalid:count>";
+    case PO_EMPTY:
+      return "empty";
   }
   return "<invalid>";
 }
 
 static char *pollable_desc(pollable *p) {
   char *out;
-  gpr_asprintf(&out, "type=%s group=%p epfd=%d wakeup=%d",
-               polling_obj_type_string(p->po.type), p->po.group, p->epfd,
-               p->wakeup.read_fd);
+  gpr_asprintf(&out, "type=%s epfd=%d wakeup=%d", pollable_type_string(p->type),
+               p->epfd, p->wakeup.read_fd);
   return out;
 }
 
-static pollable g_empty_pollable;
+/// Shared empty pollable - used by pollset to poll on until the first fd is
+/// added
+static pollable *g_empty_pollable;
 
-static void pollable_init(pollable *p, polling_obj_type type);
-static void pollable_destroy(pollable *p);
-/* ensure that p->epfd, p->wakeup are initialized; p->po.mu must be held */
-static grpc_error *pollable_materialize(pollable *p);
+static grpc_error *pollable_create(pollable_type type, pollable **p);
+#ifdef NDEBUG
+static pollable *pollable_ref(pollable *p);
+static void pollable_unref(pollable *p);
+#define POLLABLE_REF(p, r) pollable_ref(p)
+#define POLLABLE_UNREF(p, r) pollable_unref(p)
+#else
+static pollable *pollable_ref(pollable *p, int line, const char *reason);
+static void pollable_unref(pollable *p, int line, const char *reason);
+#define POLLABLE_REF(p, r) pollable_ref((p), __LINE__, (r))
+#define POLLABLE_UNREF(p, r) pollable_unref((p), __LINE__, (r))
+#endif
 
 /*******************************************************************************
  * Fd Declarations
  */
 
 struct grpc_fd {
-  pollable pollable_obj;
   int fd;
   /* refst format:
        bit 0    : 1=Active / 0=Orphaned
@@ -150,11 +148,10 @@
      Ref/Unref by two to avoid altering the orphaned bit */
   gpr_atm refst;
 
-  /* 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 */
-  gpr_mu orphaned_mu;
-  bool orphaned;
+  gpr_mu orphan_mu;
+
+  gpr_mu pollable_mu;
+  pollable *pollable_obj;
 
   gpr_atm read_closure;
   gpr_atm write_closure;
@@ -176,47 +173,52 @@
  * Pollset Declarations
  */
 
-typedef struct pollset_worker_link {
+typedef struct {
   grpc_pollset_worker *next;
   grpc_pollset_worker *prev;
-} pollset_worker_link;
+} pwlink;
 
-typedef enum {
-  PWL_POLLSET,
-  PWL_POLLABLE,
-  POLLSET_WORKER_LINK_COUNT
-} pollset_worker_links;
+typedef enum { PWLINK_POLLABLE = 0, PWLINK_POLLSET, PWLINK_COUNT } pwlinks;
 
 struct grpc_pollset_worker {
   bool kicked;
   bool initialized_cv;
-  pollset_worker_link links[POLLSET_WORKER_LINK_COUNT];
+#ifndef NDEBUG
+  // debug aid: which thread started this worker
+  pid_t originator;
+#endif
   gpr_cv cv;
   grpc_pollset *pollset;
   pollable *pollable_obj;
+
+  pwlink links[PWLINK_COUNT];
 };
 
-#define MAX_EPOLL_EVENTS 100
-#define MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL 5
-
 struct grpc_pollset {
-  pollable pollable_obj;
-  pollable *current_pollable_obj;
-  int kick_alls_pending;
+  gpr_mu mu;
+  pollable *active_pollable;
   bool kicked_without_poller;
   grpc_closure *shutdown_closure;
   grpc_pollset_worker *root_worker;
-
-  int event_cursor;
-  int event_count;
-  struct epoll_event events[MAX_EPOLL_EVENTS];
+  int containing_pollset_set_count;
 };
 
 /*******************************************************************************
  * Pollset-set Declarations
  */
+
 struct grpc_pollset_set {
-  polling_obj po;
+  gpr_refcount refs;
+  gpr_mu mu;
+  grpc_pollset_set *parent;
+
+  size_t pollset_count;
+  size_t pollset_capacity;
+  grpc_pollset **pollsets;
+
+  size_t fd_count;
+  size_t fd_capacity;
+  grpc_fd **fds;
 };
 
 /*******************************************************************************
@@ -250,11 +252,6 @@
  * becomes a spurious read notification on a reused fd.
  */
 
-/* The alarm system needs to be able to wakeup 'some poller' sometimes
- * (specifically when a new alarm needs to be triggered earlier than the next
- * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a
- * case occurs. */
-
 static grpc_fd *fd_freelist = NULL;
 static gpr_mu fd_freelist_mu;
 
@@ -282,8 +279,9 @@
   grpc_fd *fd = (grpc_fd *)arg;
   /* Add the fd to the freelist */
   grpc_iomgr_unregister_object(&fd->iomgr_object);
-  pollable_destroy(&fd->pollable_obj);
-  gpr_mu_destroy(&fd->orphaned_mu);
+  POLLABLE_UNREF(fd->pollable_obj, "fd_pollable");
+  gpr_mu_destroy(&fd->pollable_mu);
+  gpr_mu_destroy(&fd->orphan_mu);
   gpr_mu_lock(&fd_freelist_mu);
   fd->freelist_next = fd_freelist;
   fd_freelist = fd;
@@ -343,12 +341,11 @@
     new_fd = (grpc_fd *)gpr_malloc(sizeof(grpc_fd));
   }
 
-  pollable_init(&new_fd->pollable_obj, PO_FD);
-
+  gpr_mu_init(&new_fd->pollable_mu);
+  gpr_mu_init(&new_fd->orphan_mu);
+  new_fd->pollable_obj = NULL;
   gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
   new_fd->fd = fd;
-  gpr_mu_init(&new_fd->orphaned_mu);
-  new_fd->orphaned = false;
   grpc_lfev_init(&new_fd->read_closure);
   grpc_lfev_init(&new_fd->write_closure);
   gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
@@ -369,24 +366,17 @@
 }
 
 static int fd_wrapped_fd(grpc_fd *fd) {
-  int ret_fd = -1;
-  gpr_mu_lock(&fd->orphaned_mu);
-  if (!fd->orphaned) {
-    ret_fd = fd->fd;
-  }
-  gpr_mu_unlock(&fd->orphaned_mu);
-
-  return ret_fd;
+  int ret_fd = fd->fd;
+  return (gpr_atm_acq_load(&fd->refst) & 1) ? ret_fd : -1;
 }
 
 static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                       grpc_closure *on_done, int *release_fd,
                       bool already_closed, const char *reason) {
   bool is_fd_closed = already_closed;
-  grpc_error *error = GRPC_ERROR_NONE;
 
-  gpr_mu_lock(&fd->pollable_obj.po.mu);
-  gpr_mu_lock(&fd->orphaned_mu);
+  gpr_mu_lock(&fd->orphan_mu);
+
   fd->on_done_closure = on_done;
 
   /* If release_fd is not NULL, we should be relinquishing control of the file
@@ -398,8 +388,6 @@
     is_fd_closed = true;
   }
 
-  fd->orphaned = true;
-
   if (!is_fd_closed) {
     gpr_log(GPR_DEBUG, "TODO: handle fd removal?");
   }
@@ -408,13 +396,11 @@
      to be alive (and not added to freelist) until the end of this function */
   REF_BY(fd, 1, reason);
 
-  GRPC_CLOSURE_SCHED(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error));
+  GRPC_CLOSURE_SCHED(exec_ctx, fd->on_done_closure, GRPC_ERROR_NONE);
 
-  gpr_mu_unlock(&fd->orphaned_mu);
-  gpr_mu_unlock(&fd->pollable_obj.po.mu);
+  gpr_mu_unlock(&fd->orphan_mu);
+
   UNREF_BY(exec_ctx, fd, 2, reason); /* Drop the reference */
-  GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error));
-  GRPC_ERROR_UNREF(error);
 }
 
 static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
@@ -451,63 +437,87 @@
  * Pollable Definitions
  */
 
-static void pollable_init(pollable *p, polling_obj_type type) {
-  po_init(&p->po, type);
-  p->root_worker = NULL;
-  p->epfd = -1;
-}
+static grpc_error *pollable_create(pollable_type type, pollable **p) {
+  *p = NULL;
 
-static void pollable_destroy(pollable *p) {
-  po_destroy(&p->po);
-  if (p->epfd != -1) {
-    close(p->epfd);
-    grpc_wakeup_fd_destroy(&p->wakeup);
+  int epfd = epoll_create1(EPOLL_CLOEXEC);
+  if (epfd == -1) {
+    return GRPC_OS_ERROR(errno, "epoll_create1");
   }
-}
-
-/* ensure that p->epfd, p->wakeup are initialized; p->po.mu must be held */
-static grpc_error *pollable_materialize(pollable *p) {
-  if (p->epfd == -1) {
-    int new_epfd = epoll_create1(EPOLL_CLOEXEC);
-    if (new_epfd < 0) {
-      return GRPC_OS_ERROR(errno, "epoll_create1");
-    }
-    grpc_error *err = grpc_wakeup_fd_init(&p->wakeup);
-    if (err != GRPC_ERROR_NONE) {
-      close(new_epfd);
-      return err;
-    }
-    struct epoll_event ev;
-    ev.events = (uint32_t)(EPOLLIN | EPOLLET);
-    ev.data.ptr = (void *)(1 | (intptr_t)&p->wakeup);
-    if (epoll_ctl(new_epfd, EPOLL_CTL_ADD, p->wakeup.read_fd, &ev) != 0) {
-      err = GRPC_OS_ERROR(errno, "epoll_ctl");
-      close(new_epfd);
-      grpc_wakeup_fd_destroy(&p->wakeup);
-      return err;
-    }
-
-    p->epfd = new_epfd;
+  *p = (pollable *)gpr_malloc(sizeof(**p));
+  grpc_error *err = grpc_wakeup_fd_init(&(*p)->wakeup);
+  if (err != GRPC_ERROR_NONE) {
+    close(epfd);
+    gpr_free(*p);
+    *p = NULL;
+    return err;
   }
+  struct epoll_event ev;
+  ev.events = (uint32_t)(EPOLLIN | EPOLLET);
+  ev.data.ptr = (void *)(1 | (intptr_t) & (*p)->wakeup);
+  if (epoll_ctl(epfd, EPOLL_CTL_ADD, (*p)->wakeup.read_fd, &ev) != 0) {
+    err = GRPC_OS_ERROR(errno, "epoll_ctl");
+    close(epfd);
+    grpc_wakeup_fd_destroy(&(*p)->wakeup);
+    gpr_free(*p);
+    *p = NULL;
+    return err;
+  }
+
+  (*p)->type = type;
+  gpr_ref_init(&(*p)->refs, 1);
+  gpr_mu_init(&(*p)->mu);
+  (*p)->epfd = epfd;
+  (*p)->owner_fd = NULL;
+  (*p)->pollset_set = NULL;
+  (*p)->next = (*p)->prev = *p;
+  (*p)->root_worker = NULL;
+  (*p)->event_cursor = 0;
+  (*p)->event_count = 0;
   return GRPC_ERROR_NONE;
 }
 
-/* pollable must be materialized */
+#ifdef NDEBUG
+static pollable *pollable_ref(pollable *p) {
+#else
+static pollable *pollable_ref(pollable *p, int line, const char *reason) {
+  if (GRPC_TRACER_ON(grpc_trace_pollable_refcount)) {
+    int r = (int)gpr_atm_no_barrier_load(&p->refs.count);
+    gpr_log(__FILE__, line, GPR_LOG_SEVERITY_DEBUG,
+            "POLLABLE:%p   ref %d->%d %s", p, r, r + 1, reason);
+  }
+#endif
+  gpr_ref(&p->refs);
+  return p;
+}
+
+#ifdef NDEBUG
+static void pollable_unref(pollable *p) {
+#else
+static void pollable_unref(pollable *p, int line, const char *reason) {
+  if (p == NULL) return;
+  if (GRPC_TRACER_ON(grpc_trace_pollable_refcount)) {
+    int r = (int)gpr_atm_no_barrier_load(&p->refs.count);
+    gpr_log(__FILE__, line, GPR_LOG_SEVERITY_DEBUG,
+            "POLLABLE:%p unref %d->%d %s", p, r, r - 1, reason);
+  }
+#endif
+  if (p != NULL && gpr_unref(&p->refs)) {
+    close(p->epfd);
+    grpc_wakeup_fd_destroy(&p->wakeup);
+    gpr_free(p);
+  }
+}
+
 static grpc_error *pollable_add_fd(pollable *p, grpc_fd *fd) {
   grpc_error *error = GRPC_ERROR_NONE;
   static const char *err_desc = "pollable_add_fd";
   const int epfd = p->epfd;
-  GPR_ASSERT(epfd != -1);
 
   if (GRPC_TRACER_ON(grpc_polling_trace)) {
     gpr_log(GPR_DEBUG, "add fd %p (%d) to pollable %p", fd, fd->fd, p);
   }
 
-  gpr_mu_lock(&fd->orphaned_mu);
-  if (fd->orphaned) {
-    gpr_mu_unlock(&fd->orphaned_mu);
-    return GRPC_ERROR_NONE;
-  }
   struct epoll_event ev_fd;
   ev_fd.events = (uint32_t)(EPOLLET | EPOLLIN | EPOLLOUT | EPOLLEXCLUSIVE);
   ev_fd.data.ptr = fd;
@@ -519,7 +529,6 @@
         append_error(&error, GRPC_OS_ERROR(errno, "epoll_ctl"), err_desc);
     }
   }
-  gpr_mu_unlock(&fd->orphaned_mu);
 
   return error;
 }
@@ -535,128 +544,67 @@
 static grpc_error *pollset_global_init(void) {
   gpr_tls_init(&g_current_thread_pollset);
   gpr_tls_init(&g_current_thread_worker);
-  pollable_init(&g_empty_pollable, PO_EMPTY_POLLABLE);
-  return GRPC_ERROR_NONE;
+  return pollable_create(PO_EMPTY, &g_empty_pollable);
 }
 
 static void pollset_global_shutdown(void) {
-  pollable_destroy(&g_empty_pollable);
+  POLLABLE_UNREF(g_empty_pollable, "g_empty_pollable");
   gpr_tls_destroy(&g_current_thread_pollset);
   gpr_tls_destroy(&g_current_thread_worker);
 }
 
+/* pollset->mu must be held while calling this function */
 static void pollset_maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
                                           grpc_pollset *pollset) {
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG,
+            "PS:%p (pollable:%p) maybe_finish_shutdown sc=%p (target:!NULL) "
+            "rw=%p (target:NULL) cpsc=%d (target:0)",
+            pollset, pollset->active_pollable, pollset->shutdown_closure,
+            pollset->root_worker, pollset->containing_pollset_set_count);
+  }
   if (pollset->shutdown_closure != NULL && pollset->root_worker == NULL &&
-      pollset->kick_alls_pending == 0) {
+      pollset->containing_pollset_set_count == 0) {
     GRPC_CLOSURE_SCHED(exec_ctx, pollset->shutdown_closure, GRPC_ERROR_NONE);
     pollset->shutdown_closure = NULL;
   }
 }
 
-static void do_kick_all(grpc_exec_ctx *exec_ctx, void *arg,
-                        grpc_error *error_unused) {
-  grpc_error *error = GRPC_ERROR_NONE;
-  grpc_pollset *pollset = (grpc_pollset *)arg;
-  gpr_mu_lock(&pollset->pollable_obj.po.mu);
-  if (pollset->root_worker != NULL) {
-    grpc_pollset_worker *worker = pollset->root_worker;
-    do {
-      GRPC_STATS_INC_POLLSET_KICK(exec_ctx);
-      if (worker->pollable_obj != &pollset->pollable_obj) {
-        gpr_mu_lock(&worker->pollable_obj->po.mu);
-      }
-      if (worker->initialized_cv && worker != pollset->root_worker) {
-        if (GRPC_TRACER_ON(grpc_polling_trace)) {
-          gpr_log(GPR_DEBUG, "PS:%p kickall_via_cv %p (pollable %p vs %p)",
-                  pollset, worker, &pollset->pollable_obj,
-                  worker->pollable_obj);
-        }
-        worker->kicked = true;
-        gpr_cv_signal(&worker->cv);
-      } else {
-        if (GRPC_TRACER_ON(grpc_polling_trace)) {
-          gpr_log(GPR_DEBUG, "PS:%p kickall_via_wakeup %p (pollable %p vs %p)",
-                  pollset, worker, &pollset->pollable_obj,
-                  worker->pollable_obj);
-        }
-        append_error(&error,
-                     grpc_wakeup_fd_wakeup(&worker->pollable_obj->wakeup),
-                     "pollset_shutdown");
-      }
-      if (worker->pollable_obj != &pollset->pollable_obj) {
-        gpr_mu_unlock(&worker->pollable_obj->po.mu);
-      }
-
-      worker = worker->links[PWL_POLLSET].next;
-    } while (worker != pollset->root_worker);
-  }
-  pollset->kick_alls_pending--;
-  pollset_maybe_finish_shutdown(exec_ctx, pollset);
-  gpr_mu_unlock(&pollset->pollable_obj.po.mu);
-  GRPC_LOG_IF_ERROR("kick_all", error);
-}
-
-static void pollset_kick_all(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
-  pollset->kick_alls_pending++;
-  GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_CREATE(do_kick_all, pollset,
-                                                   grpc_schedule_on_exec_ctx),
-                     GRPC_ERROR_NONE);
-}
-
-static grpc_error *pollset_kick_inner(grpc_pollset *pollset, pollable *p,
-                                      grpc_pollset_worker *specific_worker) {
-  if (GRPC_TRACER_ON(grpc_polling_trace)) {
-    gpr_log(GPR_DEBUG,
-            "PS:%p kick %p tls_pollset=%p tls_worker=%p "
-            "root_worker=(pollset:%p pollable:%p)",
-            p, specific_worker, (void *)gpr_tls_get(&g_current_thread_pollset),
-            (void *)gpr_tls_get(&g_current_thread_worker), pollset->root_worker,
-            p->root_worker);
-  }
-  if (specific_worker == NULL) {
-    if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
-      if (pollset->root_worker == NULL) {
-        if (GRPC_TRACER_ON(grpc_polling_trace)) {
-          gpr_log(GPR_DEBUG, "PS:%p kicked_any_without_poller", p);
-        }
-        pollset->kicked_without_poller = true;
-        return GRPC_ERROR_NONE;
-      } else {
-        if (GRPC_TRACER_ON(grpc_polling_trace)) {
-          gpr_log(GPR_DEBUG, "PS:%p kicked_any_via_wakeup_fd", p);
-        }
-        grpc_error *err = pollable_materialize(p);
-        if (err != GRPC_ERROR_NONE) return err;
-        return grpc_wakeup_fd_wakeup(&p->wakeup);
-      }
-    } else {
-      if (GRPC_TRACER_ON(grpc_polling_trace)) {
-        gpr_log(GPR_DEBUG, "PS:%p kicked_any_but_awake", p);
-      }
-      return GRPC_ERROR_NONE;
-    }
-  } else if (specific_worker->kicked) {
+/* pollset->mu must be held before calling this function,
+ * pollset->active_pollable->mu & specific_worker->pollable_obj->mu must not be
+ * held */
+static grpc_error *kick_one_worker(grpc_exec_ctx *exec_ctx,
+                                   grpc_pollset_worker *specific_worker) {
+  pollable *p = specific_worker->pollable_obj;
+  grpc_core::mu_guard lock(&p->mu);
+  GRPC_STATS_INC_POLLSET_KICK(exec_ctx);
+  GPR_ASSERT(specific_worker != NULL);
+  if (specific_worker->kicked) {
     if (GRPC_TRACER_ON(grpc_polling_trace)) {
       gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_already_kicked", p);
     }
+    GRPC_STATS_INC_POLLSET_KICKED_AGAIN(exec_ctx);
     return GRPC_ERROR_NONE;
-  } else if (gpr_tls_get(&g_current_thread_worker) ==
-             (intptr_t)specific_worker) {
+  }
+  if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) {
     if (GRPC_TRACER_ON(grpc_polling_trace)) {
       gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_awake", p);
     }
+    GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD(exec_ctx);
     specific_worker->kicked = true;
     return GRPC_ERROR_NONE;
-  } else if (specific_worker == p->root_worker) {
+  }
+  if (specific_worker == p->root_worker) {
+    GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD(exec_ctx);
     if (GRPC_TRACER_ON(grpc_polling_trace)) {
       gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_wakeup_fd", p);
     }
-    grpc_error *err = pollable_materialize(p);
-    if (err != GRPC_ERROR_NONE) return err;
     specific_worker->kicked = true;
-    return grpc_wakeup_fd_wakeup(&p->wakeup);
-  } else {
+    grpc_error *error = grpc_wakeup_fd_wakeup(&p->wakeup);
+    return error;
+  }
+  if (specific_worker->initialized_cv) {
+    GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV(exec_ctx);
     if (GRPC_TRACER_ON(grpc_polling_trace)) {
       gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_cv", p);
     }
@@ -664,30 +612,79 @@
     gpr_cv_signal(&specific_worker->cv);
     return GRPC_ERROR_NONE;
   }
+  // we can get here during end_worker after removing specific_worker from the
+  // pollable list but before removing it from the pollset list
+  return GRPC_ERROR_NONE;
 }
 
-/* p->po.mu must be held before calling this function */
 static grpc_error *pollset_kick(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                                 grpc_pollset_worker *specific_worker) {
-  pollable *p = pollset->current_pollable_obj;
-  GRPC_STATS_INC_POLLSET_KICK(exec_ctx);
-  if (p != &pollset->pollable_obj) {
-    gpr_mu_lock(&p->po.mu);
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG,
+            "PS:%p kick %p tls_pollset=%p tls_worker=%p pollset.root_worker=%p",
+            pollset, specific_worker,
+            (void *)gpr_tls_get(&g_current_thread_pollset),
+            (void *)gpr_tls_get(&g_current_thread_worker),
+            pollset->root_worker);
   }
-  grpc_error *error = pollset_kick_inner(pollset, p, specific_worker);
-  if (p != &pollset->pollable_obj) {
-    gpr_mu_unlock(&p->po.mu);
+  if (specific_worker == NULL) {
+    if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
+      if (pollset->root_worker == NULL) {
+        if (GRPC_TRACER_ON(grpc_polling_trace)) {
+          gpr_log(GPR_DEBUG, "PS:%p kicked_any_without_poller", pollset);
+        }
+        GRPC_STATS_INC_POLLSET_KICKED_WITHOUT_POLLER(exec_ctx);
+        pollset->kicked_without_poller = true;
+        return GRPC_ERROR_NONE;
+      } else {
+        // We've been asked to kick a poller, but we haven't been told which one
+        // ... any will do
+        // We look at the pollset worker list because:
+        // 1. the pollable list may include workers from other pollers, so we'd
+        //    need to do an O(N) search
+        // 2. we'd additionally need to take the pollable lock, which we've so
+        //    far avoided
+        // Now, we would prefer to wake a poller in cv_wait, and not in
+        // epoll_wait (since the latter would imply the need to do an additional
+        // wakeup)
+        // We know that if a worker is at the root of a pollable, it's (likely)
+        // also the root of a pollset, and we know that if a worker is NOT at
+        // the root of a pollset, it's (likely) not at the root of a pollable,
+        // so we take our chances and choose the SECOND worker enqueued against
+        // the pollset as a worker that's likely to be in cv_wait
+        return kick_one_worker(
+            exec_ctx, pollset->root_worker->links[PWLINK_POLLSET].next);
+      }
+    } else {
+      if (GRPC_TRACER_ON(grpc_polling_trace)) {
+        gpr_log(GPR_DEBUG, "PS:%p kicked_any_but_awake", pollset);
+      }
+      GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD(exec_ctx);
+      return GRPC_ERROR_NONE;
+    }
+  } else {
+    return kick_one_worker(exec_ctx, specific_worker);
+  }
+}
+
+static grpc_error *pollset_kick_all(grpc_exec_ctx *exec_ctx,
+                                    grpc_pollset *pollset) {
+  grpc_error *error = GRPC_ERROR_NONE;
+  const char *err_desc = "pollset_kick_all";
+  grpc_pollset_worker *w = pollset->root_worker;
+  if (w != NULL) {
+    do {
+      append_error(&error, kick_one_worker(exec_ctx, w), err_desc);
+      w = w->links[PWLINK_POLLSET].next;
+    } while (w != pollset->root_worker);
   }
   return error;
 }
 
 static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
-  pollable_init(&pollset->pollable_obj, PO_POLLSET);
-  pollset->current_pollable_obj = &g_empty_pollable;
-  pollset->kicked_without_poller = false;
-  pollset->shutdown_closure = NULL;
-  pollset->root_worker = NULL;
-  *mu = &pollset->pollable_obj.po.mu;
+  gpr_mu_init(&pollset->mu);
+  pollset->active_pollable = POLLABLE_REF(g_empty_pollable, "pollset");
+  *mu = &pollset->mu;
 }
 
 static int poll_deadline_to_millis_timeout(grpc_exec_ctx *exec_ctx,
@@ -719,12 +716,29 @@
   grpc_lfev_set_ready(exec_ctx, &fd->write_closure, "write");
 }
 
-static grpc_error *fd_become_pollable_locked(grpc_fd *fd) {
+static grpc_error *fd_get_or_become_pollable(grpc_fd *fd, pollable **p) {
+  gpr_mu_lock(&fd->pollable_mu);
   grpc_error *error = GRPC_ERROR_NONE;
-  static const char *err_desc = "fd_become_pollable";
-  if (append_error(&error, pollable_materialize(&fd->pollable_obj), err_desc)) {
-    append_error(&error, pollable_add_fd(&fd->pollable_obj, fd), err_desc);
+  static const char *err_desc = "fd_get_or_become_pollable";
+  if (fd->pollable_obj == NULL) {
+    if (append_error(&error, pollable_create(PO_FD, &fd->pollable_obj),
+                     err_desc)) {
+      fd->pollable_obj->owner_fd = fd;
+      if (!append_error(&error, pollable_add_fd(fd->pollable_obj, fd),
+                        err_desc)) {
+        POLLABLE_UNREF(fd->pollable_obj, "fd_pollable");
+        fd->pollable_obj = NULL;
+      }
+    }
   }
+  if (error == GRPC_ERROR_NONE) {
+    GPR_ASSERT(fd->pollable_obj != NULL);
+    *p = POLLABLE_REF(fd->pollable_obj, "pollset");
+  } else {
+    GPR_ASSERT(fd->pollable_obj == NULL);
+    *p = NULL;
+  }
+  gpr_mu_unlock(&fd->pollable_mu);
   return error;
 }
 
@@ -733,23 +747,20 @@
                              grpc_closure *closure) {
   GPR_ASSERT(pollset->shutdown_closure == NULL);
   pollset->shutdown_closure = closure;
-  pollset_kick_all(exec_ctx, pollset);
+  GRPC_LOG_IF_ERROR("pollset_shutdown", pollset_kick_all(exec_ctx, pollset));
   pollset_maybe_finish_shutdown(exec_ctx, pollset);
 }
 
-static bool pollset_is_pollable_fd(grpc_pollset *pollset, pollable *p) {
-  return p != &g_empty_pollable && p != &pollset->pollable_obj;
-}
-
-static grpc_error *pollset_process_events(grpc_exec_ctx *exec_ctx,
-                                          grpc_pollset *pollset, bool drain) {
+static grpc_error *pollable_process_events(grpc_exec_ctx *exec_ctx,
+                                           grpc_pollset *pollset,
+                                           pollable *pollable_obj, bool drain) {
   static const char *err_desc = "pollset_process_events";
   grpc_error *error = GRPC_ERROR_NONE;
   for (int i = 0; (drain || i < MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL) &&
-                  pollset->event_cursor != pollset->event_count;
+                  pollable_obj->event_cursor != pollable_obj->event_count;
        i++) {
-    int n = pollset->event_cursor++;
-    struct epoll_event *ev = &pollset->events[n];
+    int n = pollable_obj->event_cursor++;
+    struct epoll_event *ev = &pollable_obj->events[n];
     void *data_ptr = ev->data.ptr;
     if (1 & (intptr_t)data_ptr) {
       if (GRPC_TRACER_ON(grpc_polling_trace)) {
@@ -784,22 +795,17 @@
 
 /* pollset_shutdown is guaranteed to be called before pollset_destroy. */
 static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
-  pollable_destroy(&pollset->pollable_obj);
-  if (pollset_is_pollable_fd(pollset, pollset->current_pollable_obj)) {
-    UNREF_BY(exec_ctx, (grpc_fd *)pollset->current_pollable_obj, 2,
-             "pollset_pollable");
-  }
-  GRPC_LOG_IF_ERROR("pollset_process_events",
-                    pollset_process_events(exec_ctx, pollset, true));
+  POLLABLE_UNREF(pollset->active_pollable, "pollset");
+  pollset->active_pollable = NULL;
 }
 
-static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                                 pollable *p, grpc_millis deadline) {
+static grpc_error *pollable_epoll(grpc_exec_ctx *exec_ctx, pollable *p,
+                                  grpc_millis deadline) {
   int timeout = poll_deadline_to_millis_timeout(exec_ctx, deadline);
 
   if (GRPC_TRACER_ON(grpc_polling_trace)) {
     char *desc = pollable_desc(p);
-    gpr_log(GPR_DEBUG, "PS:%p poll %p[%s] for %dms", pollset, p, desc, timeout);
+    gpr_log(GPR_DEBUG, "POLLABLE:%p[%s] poll for %dms", p, desc, timeout);
     gpr_free(desc);
   }
 
@@ -809,7 +815,7 @@
   int r;
   do {
     GRPC_STATS_INC_SYSCALL_POLL(exec_ctx);
-    r = epoll_wait(p->epfd, pollset->events, MAX_EPOLL_EVENTS, timeout);
+    r = epoll_wait(p->epfd, p->events, MAX_EPOLL_EVENTS, timeout);
   } while (r < 0 && errno == EINTR);
   if (timeout != 0) {
     GRPC_SCHEDULING_END_BLOCKING_REGION_WITH_EXEC_CTX(exec_ctx);
@@ -818,24 +824,24 @@
   if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
 
   if (GRPC_TRACER_ON(grpc_polling_trace)) {
-    gpr_log(GPR_DEBUG, "PS:%p poll %p got %d events", pollset, p, r);
+    gpr_log(GPR_DEBUG, "POLLABLE:%p got %d events", p, r);
   }
 
-  pollset->event_cursor = 0;
-  pollset->event_count = r;
+  p->event_cursor = 0;
+  p->event_count = r;
 
   return GRPC_ERROR_NONE;
 }
 
 /* Return true if first in list */
-static bool worker_insert(grpc_pollset_worker **root, pollset_worker_links link,
-                          grpc_pollset_worker *worker) {
-  if (*root == NULL) {
-    *root = worker;
+static bool worker_insert(grpc_pollset_worker **root_worker,
+                          grpc_pollset_worker *worker, pwlinks link) {
+  if (*root_worker == NULL) {
+    *root_worker = worker;
     worker->links[link].next = worker->links[link].prev = worker;
     return true;
   } else {
-    worker->links[link].next = *root;
+    worker->links[link].next = *root_worker;
     worker->links[link].prev = worker->links[link].next->links[link].prev;
     worker->links[link].next->links[link].prev = worker;
     worker->links[link].prev->links[link].next = worker;
@@ -843,26 +849,26 @@
   }
 }
 
-/* Return true if last in list */
-typedef enum { EMPTIED, NEW_ROOT, REMOVED } worker_remove_result;
+/* returns the new root IFF the root changed */
+typedef enum { WRR_NEW_ROOT, WRR_EMPTIED, WRR_REMOVED } worker_remove_result;
 
-static worker_remove_result worker_remove(grpc_pollset_worker **root,
-                                          pollset_worker_links link,
-                                          grpc_pollset_worker *worker) {
-  if (worker == *root) {
+static worker_remove_result worker_remove(grpc_pollset_worker **root_worker,
+                                          grpc_pollset_worker *worker,
+                                          pwlinks link) {
+  if (worker == *root_worker) {
     if (worker == worker->links[link].next) {
-      *root = NULL;
-      return EMPTIED;
+      *root_worker = NULL;
+      return WRR_EMPTIED;
     } else {
-      *root = worker->links[link].next;
+      *root_worker = worker->links[link].next;
       worker->links[link].prev->links[link].next = worker->links[link].next;
       worker->links[link].next->links[link].prev = worker->links[link].prev;
-      return NEW_ROOT;
+      return WRR_NEW_ROOT;
     }
   } else {
     worker->links[link].prev->links[link].next = worker->links[link].next;
     worker->links[link].next->links[link].prev = worker->links[link].prev;
-    return REMOVED;
+    return WRR_REMOVED;
   }
 }
 
@@ -871,25 +877,20 @@
                          grpc_pollset_worker *worker,
                          grpc_pollset_worker **worker_hdl,
                          grpc_millis deadline) {
-  bool do_poll = true;
+  bool do_poll = (pollset->shutdown_closure == nullptr);
   if (worker_hdl != NULL) *worker_hdl = worker;
   worker->initialized_cv = false;
   worker->kicked = false;
   worker->pollset = pollset;
-  worker->pollable_obj = pollset->current_pollable_obj;
-
-  if (pollset_is_pollable_fd(pollset, worker->pollable_obj)) {
-    REF_BY((grpc_fd *)worker->pollable_obj, 2, "one_poll");
-  }
-
-  worker_insert(&pollset->root_worker, PWL_POLLSET, worker);
-  if (!worker_insert(&worker->pollable_obj->root_worker, PWL_POLLABLE,
-                     worker)) {
+  worker->pollable_obj =
+      POLLABLE_REF(pollset->active_pollable, "pollset_worker");
+  worker_insert(&pollset->root_worker, worker, PWLINK_POLLSET);
+  gpr_mu_lock(&worker->pollable_obj->mu);
+  if (!worker_insert(&worker->pollable_obj->root_worker, worker,
+                     PWLINK_POLLABLE)) {
     worker->initialized_cv = true;
     gpr_cv_init(&worker->cv);
-    if (worker->pollable_obj != &pollset->pollable_obj) {
-      gpr_mu_unlock(&pollset->pollable_obj.po.mu);
-    }
+    gpr_mu_unlock(&pollset->mu);
     if (GRPC_TRACER_ON(grpc_polling_trace) &&
         worker->pollable_obj->root_worker != worker) {
       gpr_log(GPR_DEBUG, "PS:%p wait %p w=%p for %dms", pollset,
@@ -897,7 +898,7 @@
               poll_deadline_to_millis_timeout(exec_ctx, deadline));
     }
     while (do_poll && worker->pollable_obj->root_worker != worker) {
-      if (gpr_cv_wait(&worker->cv, &worker->pollable_obj->po.mu,
+      if (gpr_cv_wait(&worker->cv, &worker->pollable_obj->mu,
                       grpc_millis_to_timespec(deadline, GPR_CLOCK_REALTIME))) {
         if (GRPC_TRACER_ON(grpc_polling_trace)) {
           gpr_log(GPR_DEBUG, "PS:%p timeout_wait %p w=%p", pollset,
@@ -916,158 +917,232 @@
                 worker->pollable_obj, worker);
       }
     }
-    if (worker->pollable_obj != &pollset->pollable_obj) {
-      gpr_mu_unlock(&worker->pollable_obj->po.mu);
-      gpr_mu_lock(&pollset->pollable_obj.po.mu);
-      gpr_mu_lock(&worker->pollable_obj->po.mu);
-    }
     grpc_exec_ctx_invalidate_now(exec_ctx);
+  } else {
+    gpr_mu_unlock(&pollset->mu);
   }
+  gpr_mu_unlock(&worker->pollable_obj->mu);
 
-  return do_poll && pollset->shutdown_closure == NULL &&
-         pollset->current_pollable_obj == worker->pollable_obj;
+  return do_poll;
 }
 
 static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                        grpc_pollset_worker *worker,
                        grpc_pollset_worker **worker_hdl) {
-  if (NEW_ROOT ==
-      worker_remove(&worker->pollable_obj->root_worker, PWL_POLLABLE, worker)) {
-    gpr_cv_signal(&worker->pollable_obj->root_worker->cv);
+  gpr_mu_lock(&pollset->mu);
+  gpr_mu_lock(&worker->pollable_obj->mu);
+  switch (worker_remove(&worker->pollable_obj->root_worker, worker,
+                        PWLINK_POLLABLE)) {
+    case WRR_NEW_ROOT: {
+      // wakeup new poller
+      grpc_pollset_worker *new_root = worker->pollable_obj->root_worker;
+      GPR_ASSERT(new_root->initialized_cv);
+      gpr_cv_signal(&new_root->cv);
+      break;
+    }
+    case WRR_EMPTIED:
+      if (pollset->active_pollable != worker->pollable_obj) {
+        // pollable no longer being polled: flush events
+        pollable_process_events(exec_ctx, pollset, worker->pollable_obj, true);
+      }
+      break;
+    case WRR_REMOVED:
+      break;
+  }
+  gpr_mu_unlock(&worker->pollable_obj->mu);
+  POLLABLE_UNREF(worker->pollable_obj, "pollset_worker");
+  if (worker_remove(&pollset->root_worker, worker, PWLINK_POLLSET) ==
+      WRR_EMPTIED) {
+    pollset_maybe_finish_shutdown(exec_ctx, pollset);
   }
   if (worker->initialized_cv) {
     gpr_cv_destroy(&worker->cv);
   }
-  if (pollset_is_pollable_fd(pollset, worker->pollable_obj)) {
-    UNREF_BY(exec_ctx, (grpc_fd *)worker->pollable_obj, 2, "one_poll");
-  }
-  if (EMPTIED == worker_remove(&pollset->root_worker, PWL_POLLSET, worker)) {
-    pollset_maybe_finish_shutdown(exec_ctx, pollset);
-  }
 }
 
-/* pollset->po.mu lock must be held by the caller before calling this.
+#ifndef NDEBUG
+static long gettid(void) { return syscall(__NR_gettid); }
+#endif
+
+/* pollset->mu lock must be held by the caller before calling this.
    The function pollset_work() may temporarily release the lock (pollset->po.mu)
    during the course of its execution but it will always re-acquire the lock and
    ensure that it is held by the time the function returns */
 static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                                 grpc_pollset_worker **worker_hdl,
                                 grpc_millis deadline) {
+#ifdef GRPC_EPOLLEX_CREATE_WORKERS_ON_HEAP
+  grpc_pollset_worker *worker =
+      (grpc_pollset_worker *)gpr_malloc(sizeof(*worker));
+#define WORKER_PTR (worker)
+#else
   grpc_pollset_worker worker;
-  if (0 && GRPC_TRACER_ON(grpc_polling_trace)) {
+#define WORKER_PTR (&worker)
+#endif
+#ifndef NDEBUG
+  WORKER_PTR->originator = gettid();
+#endif
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
     gpr_log(GPR_DEBUG, "PS:%p work hdl=%p worker=%p now=%" PRIdPTR
-                       " deadline=%" PRIdPTR " kwp=%d root_worker=%p",
-            pollset, worker_hdl, &worker, grpc_exec_ctx_now(exec_ctx), deadline,
-            pollset->kicked_without_poller, pollset->root_worker);
+                       " deadline=%" PRIdPTR " kwp=%d pollable=%p",
+            pollset, worker_hdl, WORKER_PTR, grpc_exec_ctx_now(exec_ctx),
+            deadline, pollset->kicked_without_poller, pollset->active_pollable);
   }
-  grpc_error *error = GRPC_ERROR_NONE;
   static const char *err_desc = "pollset_work";
+  grpc_error *error = GRPC_ERROR_NONE;
   if (pollset->kicked_without_poller) {
     pollset->kicked_without_poller = false;
-    return GRPC_ERROR_NONE;
-  }
-  if (pollset->current_pollable_obj != &pollset->pollable_obj) {
-    gpr_mu_lock(&pollset->current_pollable_obj->po.mu);
-  }
-  if (begin_worker(exec_ctx, pollset, &worker, worker_hdl, deadline)) {
-    gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
-    gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
-    GPR_ASSERT(!pollset->shutdown_closure);
-    append_error(&error, pollable_materialize(worker.pollable_obj), err_desc);
-    if (worker.pollable_obj != &pollset->pollable_obj) {
-      gpr_mu_unlock(&worker.pollable_obj->po.mu);
+  } else {
+    if (begin_worker(exec_ctx, pollset, WORKER_PTR, worker_hdl, deadline)) {
+      gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
+      gpr_tls_set(&g_current_thread_worker, (intptr_t)WORKER_PTR);
+      if (WORKER_PTR->pollable_obj->event_cursor ==
+          WORKER_PTR->pollable_obj->event_count) {
+        append_error(&error, pollable_epoll(exec_ctx, WORKER_PTR->pollable_obj,
+                                            deadline),
+                     err_desc);
+      }
+      append_error(&error,
+                   pollable_process_events(exec_ctx, pollset,
+                                           WORKER_PTR->pollable_obj, false),
+                   err_desc);
+      grpc_exec_ctx_flush(exec_ctx);
+      gpr_tls_set(&g_current_thread_pollset, 0);
+      gpr_tls_set(&g_current_thread_worker, 0);
     }
-    gpr_mu_unlock(&pollset->pollable_obj.po.mu);
-    if (pollset->event_cursor == pollset->event_count) {
-      append_error(&error, pollset_epoll(exec_ctx, pollset, worker.pollable_obj,
-                                         deadline),
+    end_worker(exec_ctx, pollset, WORKER_PTR, worker_hdl);
+  }
+#ifdef GRPC_EPOLLEX_CREATE_WORKERS_ON_HEAP
+  gpr_free(worker);
+#endif
+#undef WORKER_PTR
+  return error;
+}
+
+static grpc_error *pollset_transition_pollable_from_empty_to_fd_locked(
+    grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *fd) {
+  static const char *err_desc = "pollset_transition_pollable_from_empty_to_fd";
+  grpc_error *error = GRPC_ERROR_NONE;
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG,
+            "PS:%p add fd %p (%d); transition pollable from empty to fd",
+            pollset, fd, fd->fd);
+  }
+  append_error(&error, pollset_kick_all(exec_ctx, pollset), err_desc);
+  POLLABLE_UNREF(pollset->active_pollable, "pollset");
+  append_error(&error, fd_get_or_become_pollable(fd, &pollset->active_pollable),
+               err_desc);
+  return error;
+}
+
+static grpc_error *pollset_transition_pollable_from_fd_to_multi_locked(
+    grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *and_add_fd) {
+  static const char *err_desc = "pollset_transition_pollable_from_fd_to_multi";
+  grpc_error *error = GRPC_ERROR_NONE;
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(
+        GPR_DEBUG,
+        "PS:%p add fd %p (%d); transition pollable from fd %p to multipoller",
+        pollset, and_add_fd, and_add_fd ? and_add_fd->fd : -1,
+        pollset->active_pollable->owner_fd);
+  }
+  append_error(&error, pollset_kick_all(exec_ctx, pollset), err_desc);
+  grpc_fd *initial_fd = pollset->active_pollable->owner_fd;
+  POLLABLE_UNREF(pollset->active_pollable, "pollset");
+  pollset->active_pollable = NULL;
+  if (append_error(&error, pollable_create(PO_MULTI, &pollset->active_pollable),
+                   err_desc)) {
+    append_error(&error, pollable_add_fd(pollset->active_pollable, initial_fd),
+                 err_desc);
+    if (and_add_fd != NULL) {
+      append_error(&error,
+                   pollable_add_fd(pollset->active_pollable, and_add_fd),
                    err_desc);
     }
-    append_error(&error, pollset_process_events(exec_ctx, pollset, false),
-                 err_desc);
-    gpr_mu_lock(&pollset->pollable_obj.po.mu);
-    if (worker.pollable_obj != &pollset->pollable_obj) {
-      gpr_mu_lock(&worker.pollable_obj->po.mu);
-    }
-    gpr_tls_set(&g_current_thread_pollset, 0);
-    gpr_tls_set(&g_current_thread_worker, 0);
-    pollset_maybe_finish_shutdown(exec_ctx, pollset);
-  }
-  end_worker(exec_ctx, pollset, &worker, worker_hdl);
-  if (worker.pollable_obj != &pollset->pollable_obj) {
-    gpr_mu_unlock(&worker.pollable_obj->po.mu);
-  }
-  if (grpc_exec_ctx_has_work(exec_ctx)) {
-    gpr_mu_unlock(&pollset->pollable_obj.po.mu);
-    grpc_exec_ctx_flush(exec_ctx);
-    gpr_mu_lock(&pollset->pollable_obj.po.mu);
   }
   return error;
 }
 
-static void unref_fd_no_longer_poller(grpc_exec_ctx *exec_ctx, void *arg,
-                                      grpc_error *error) {
-  grpc_fd *fd = (grpc_fd *)arg;
-  UNREF_BY(exec_ctx, fd, 2, "pollset_pollable");
-}
-
 /* expects pollsets locked, flag whether fd is locked or not */
 static grpc_error *pollset_add_fd_locked(grpc_exec_ctx *exec_ctx,
-                                         grpc_pollset *pollset, grpc_fd *fd,
-                                         bool fd_locked) {
-  static const char *err_desc = "pollset_add_fd";
+                                         grpc_pollset *pollset, grpc_fd *fd) {
   grpc_error *error = GRPC_ERROR_NONE;
-  if (pollset->current_pollable_obj == &g_empty_pollable) {
-    if (GRPC_TRACER_ON(grpc_polling_trace)) {
-      gpr_log(GPR_DEBUG,
-              "PS:%p add fd %p; transition pollable from empty to fd", pollset,
-              fd);
-    }
-    /* empty pollable --> single fd pollable */
-    pollset_kick_all(exec_ctx, pollset);
-    pollset->current_pollable_obj = &fd->pollable_obj;
-    if (!fd_locked) gpr_mu_lock(&fd->pollable_obj.po.mu);
-    append_error(&error, fd_become_pollable_locked(fd), err_desc);
-    if (!fd_locked) gpr_mu_unlock(&fd->pollable_obj.po.mu);
-    REF_BY(fd, 2, "pollset_pollable");
-  } else if (pollset->current_pollable_obj == &pollset->pollable_obj) {
-    if (GRPC_TRACER_ON(grpc_polling_trace)) {
-      gpr_log(GPR_DEBUG, "PS:%p add fd %p; already multipolling", pollset, fd);
-    }
-    append_error(&error, pollable_add_fd(pollset->current_pollable_obj, fd),
-                 err_desc);
-  } else if (pollset->current_pollable_obj != &fd->pollable_obj) {
-    grpc_fd *had_fd = (grpc_fd *)pollset->current_pollable_obj;
-    if (GRPC_TRACER_ON(grpc_polling_trace)) {
-      gpr_log(GPR_DEBUG,
-              "PS:%p add fd %p; transition pollable from fd %p to multipoller",
-              pollset, fd, had_fd);
-    }
-    /* Introduce a spurious completion.
-       If we do not, then it may be that the fd-specific epoll set consumed
-       a completion without being polled, leading to a missed edge going up. */
-    grpc_lfev_set_ready(exec_ctx, &had_fd->read_closure, "read");
-    grpc_lfev_set_ready(exec_ctx, &had_fd->write_closure, "write");
-    pollset_kick_all(exec_ctx, pollset);
-    pollset->current_pollable_obj = &pollset->pollable_obj;
-    if (append_error(&error, pollable_materialize(&pollset->pollable_obj),
-                     err_desc)) {
-      pollable_add_fd(&pollset->pollable_obj, had_fd);
-      pollable_add_fd(&pollset->pollable_obj, fd);
-    }
-    GRPC_CLOSURE_SCHED(exec_ctx,
-                       GRPC_CLOSURE_CREATE(unref_fd_no_longer_poller, had_fd,
-                                           grpc_schedule_on_exec_ctx),
-                       GRPC_ERROR_NONE);
+  pollable *po_at_start =
+      POLLABLE_REF(pollset->active_pollable, "pollset_add_fd");
+  switch (pollset->active_pollable->type) {
+    case PO_EMPTY:
+      /* empty pollable --> single fd pollable */
+      error = pollset_transition_pollable_from_empty_to_fd_locked(exec_ctx,
+                                                                  pollset, fd);
+      break;
+    case PO_FD:
+      gpr_mu_lock(&po_at_start->owner_fd->orphan_mu);
+      if ((gpr_atm_no_barrier_load(&pollset->active_pollable->owner_fd->refst) &
+           1) == 0) {
+        error = pollset_transition_pollable_from_empty_to_fd_locked(
+            exec_ctx, pollset, fd);
+      } else {
+        /* fd --> multipoller */
+        error = pollset_transition_pollable_from_fd_to_multi_locked(
+            exec_ctx, pollset, fd);
+      }
+      gpr_mu_unlock(&po_at_start->owner_fd->orphan_mu);
+      break;
+    case PO_MULTI:
+      error = pollable_add_fd(pollset->active_pollable, fd);
+      break;
+  }
+  if (error != GRPC_ERROR_NONE) {
+    POLLABLE_UNREF(pollset->active_pollable, "pollset");
+    pollset->active_pollable = po_at_start;
+  } else {
+    POLLABLE_UNREF(po_at_start, "pollset_add_fd");
+  }
+  return error;
+}
+
+static grpc_error *pollset_as_multipollable_locked(grpc_exec_ctx *exec_ctx,
+                                                   grpc_pollset *pollset,
+                                                   pollable **pollable_obj) {
+  grpc_error *error = GRPC_ERROR_NONE;
+  pollable *po_at_start =
+      POLLABLE_REF(pollset->active_pollable, "pollset_as_multipollable");
+  switch (pollset->active_pollable->type) {
+    case PO_EMPTY:
+      POLLABLE_UNREF(pollset->active_pollable, "pollset");
+      error = pollable_create(PO_MULTI, &pollset->active_pollable);
+      break;
+    case PO_FD:
+      gpr_mu_lock(&po_at_start->owner_fd->orphan_mu);
+      if ((gpr_atm_no_barrier_load(&pollset->active_pollable->owner_fd->refst) &
+           1) == 0) {
+        POLLABLE_UNREF(pollset->active_pollable, "pollset");
+        error = pollable_create(PO_MULTI, &pollset->active_pollable);
+      } else {
+        error = pollset_transition_pollable_from_fd_to_multi_locked(
+            exec_ctx, pollset, NULL);
+      }
+      gpr_mu_unlock(&po_at_start->owner_fd->orphan_mu);
+      break;
+    case PO_MULTI:
+      break;
+  }
+  if (error != GRPC_ERROR_NONE) {
+    POLLABLE_UNREF(pollset->active_pollable, "pollset");
+    pollset->active_pollable = po_at_start;
+    *pollable_obj = NULL;
+  } else {
+    *pollable_obj = POLLABLE_REF(pollset->active_pollable, "pollset_set");
+    POLLABLE_UNREF(po_at_start, "pollset_as_multipollable");
   }
   return error;
 }
 
 static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                            grpc_fd *fd) {
-  gpr_mu_lock(&pollset->pollable_obj.po.mu);
-  grpc_error *error = pollset_add_fd_locked(exec_ctx, pollset, fd, false);
-  gpr_mu_unlock(&pollset->pollable_obj.po.mu);
+  gpr_mu_lock(&pollset->mu);
+  grpc_error *error = pollset_add_fd_locked(exec_ctx, pollset, fd);
+  gpr_mu_unlock(&pollset->mu);
   GRPC_LOG_IF_ERROR("pollset_add_fd", error);
 }
 
@@ -1075,301 +1150,255 @@
  * Pollset-set Definitions
  */
 
-static grpc_pollset_set *pollset_set_create(void) {
-  grpc_pollset_set *pss = (grpc_pollset_set *)gpr_zalloc(sizeof(*pss));
-  po_init(&pss->po, PO_POLLSET_SET);
+static grpc_pollset_set *pss_lock_adam(grpc_pollset_set *pss) {
+  gpr_mu_lock(&pss->mu);
+  while (pss->parent != NULL) {
+    gpr_mu_unlock(&pss->mu);
+    pss = pss->parent;
+    gpr_mu_lock(&pss->mu);
+  }
   return pss;
 }
 
-static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
-                                grpc_pollset_set *pss) {
-  po_destroy(&pss->po);
+static grpc_pollset_set *pollset_set_create(void) {
+  grpc_pollset_set *pss = (grpc_pollset_set *)gpr_zalloc(sizeof(*pss));
+  gpr_mu_init(&pss->mu);
+  gpr_ref_init(&pss->refs, 1);
+  return pss;
+}
+
+static void pollset_set_unref(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss) {
+  if (pss == NULL) return;
+  if (!gpr_unref(&pss->refs)) return;
+  pollset_set_unref(exec_ctx, pss->parent);
+  gpr_mu_destroy(&pss->mu);
+  for (size_t i = 0; i < pss->pollset_count; i++) {
+    gpr_mu_lock(&pss->pollsets[i]->mu);
+    if (0 == --pss->pollsets[i]->containing_pollset_set_count) {
+      pollset_maybe_finish_shutdown(exec_ctx, pss->pollsets[i]);
+    }
+    gpr_mu_unlock(&pss->pollsets[i]->mu);
+  }
+  for (size_t i = 0; i < pss->fd_count; i++) {
+    UNREF_BY(exec_ctx, pss->fds[i], 2, "pollset_set");
+  }
+  gpr_free(pss->pollsets);
+  gpr_free(pss->fds);
   gpr_free(pss);
 }
 
 static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
                                grpc_fd *fd) {
-  po_join(exec_ctx, &pss->po, &fd->pollable_obj.po);
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG, "PSS:%p: add fd %p (%d)", pss, fd, fd->fd);
+  }
+  grpc_error *error = GRPC_ERROR_NONE;
+  static const char *err_desc = "pollset_set_add_fd";
+  pss = pss_lock_adam(pss);
+  for (size_t i = 0; i < pss->pollset_count; i++) {
+    append_error(&error, pollable_add_fd(pss->pollsets[i]->active_pollable, fd),
+                 err_desc);
+  }
+  if (pss->fd_count == pss->fd_capacity) {
+    pss->fd_capacity = GPR_MAX(pss->fd_capacity * 2, 8);
+    pss->fds =
+        (grpc_fd **)gpr_realloc(pss->fds, pss->fd_capacity * sizeof(*pss->fds));
+  }
+  REF_BY(fd, 2, "pollset_set");
+  pss->fds[pss->fd_count++] = fd;
+  gpr_mu_unlock(&pss->mu);
+
+  GRPC_LOG_IF_ERROR(err_desc, error);
 }
 
 static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
-                               grpc_fd *fd) {}
-
-static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
-                                    grpc_pollset_set *pss, grpc_pollset *ps) {
-  po_join(exec_ctx, &pss->po, &ps->pollable_obj.po);
+                               grpc_fd *fd) {
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG, "PSS:%p: del fd %p", pss, fd);
+  }
+  pss = pss_lock_adam(pss);
+  size_t i;
+  for (i = 0; i < pss->fd_count; i++) {
+    if (pss->fds[i] == fd) {
+      UNREF_BY(exec_ctx, fd, 2, "pollset_set");
+      break;
+    }
+  }
+  GPR_ASSERT(i != pss->fd_count);
+  for (; i < pss->fd_count - 1; i++) {
+    pss->fds[i] = pss->fds[i + 1];
+  }
+  pss->fd_count--;
+  gpr_mu_unlock(&pss->mu);
 }
 
 static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
-                                    grpc_pollset_set *pss, grpc_pollset *ps) {}
+                                    grpc_pollset_set *pss, grpc_pollset *ps) {
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG, "PSS:%p: del pollset %p", pss, ps);
+  }
+  pss = pss_lock_adam(pss);
+  size_t i;
+  for (i = 0; i < pss->pollset_count; i++) {
+    if (pss->pollsets[i] == ps) {
+      break;
+    }
+  }
+  GPR_ASSERT(i != pss->pollset_count);
+  for (; i < pss->pollset_count - 1; i++) {
+    pss->pollsets[i] = pss->pollsets[i + 1];
+  }
+  pss->pollset_count--;
+  gpr_mu_unlock(&pss->mu);
+  gpr_mu_lock(&ps->mu);
+  if (0 == --ps->containing_pollset_set_count) {
+    pollset_maybe_finish_shutdown(exec_ctx, ps);
+  }
+  gpr_mu_unlock(&ps->mu);
+}
+
+// add all fds to pollables, and output a new array of unorphaned out_fds
+// assumes pollsets are multipollable
+static grpc_error *add_fds_to_pollsets(grpc_exec_ctx *exec_ctx, grpc_fd **fds,
+                                       size_t fd_count, grpc_pollset **pollsets,
+                                       size_t pollset_count,
+                                       const char *err_desc, grpc_fd **out_fds,
+                                       size_t *out_fd_count) {
+  grpc_error *error = GRPC_ERROR_NONE;
+  for (size_t i = 0; i < fd_count; i++) {
+    gpr_mu_lock(&fds[i]->orphan_mu);
+    if ((gpr_atm_no_barrier_load(&fds[i]->refst) & 1) == 0) {
+      gpr_mu_unlock(&fds[i]->orphan_mu);
+      UNREF_BY(exec_ctx, fds[i], 2, "pollset_set");
+    } else {
+      for (size_t j = 0; j < pollset_count; j++) {
+        append_error(&error,
+                     pollable_add_fd(pollsets[j]->active_pollable, fds[i]),
+                     err_desc);
+      }
+      gpr_mu_unlock(&fds[i]->orphan_mu);
+      out_fds[(*out_fd_count)++] = fds[i];
+    }
+  }
+  return error;
+}
+
+static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
+                                    grpc_pollset_set *pss, grpc_pollset *ps) {
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG, "PSS:%p: add pollset %p", pss, ps);
+  }
+  grpc_error *error = GRPC_ERROR_NONE;
+  static const char *err_desc = "pollset_set_add_pollset";
+  pollable *pollable_obj = NULL;
+  gpr_mu_lock(&ps->mu);
+  if (!GRPC_LOG_IF_ERROR(err_desc, pollset_as_multipollable_locked(
+                                       exec_ctx, ps, &pollable_obj))) {
+    GPR_ASSERT(pollable_obj == NULL);
+    gpr_mu_unlock(&ps->mu);
+    return;
+  }
+  ps->containing_pollset_set_count++;
+  gpr_mu_unlock(&ps->mu);
+  pss = pss_lock_adam(pss);
+  size_t initial_fd_count = pss->fd_count;
+  pss->fd_count = 0;
+  append_error(&error,
+               add_fds_to_pollsets(exec_ctx, pss->fds, initial_fd_count, &ps, 1,
+                                   err_desc, pss->fds, &pss->fd_count),
+               err_desc);
+  if (pss->pollset_count == pss->pollset_capacity) {
+    pss->pollset_capacity = GPR_MAX(pss->pollset_capacity * 2, 8);
+    pss->pollsets = (grpc_pollset **)gpr_realloc(
+        pss->pollsets, pss->pollset_capacity * sizeof(*pss->pollsets));
+  }
+  pss->pollsets[pss->pollset_count++] = ps;
+  gpr_mu_unlock(&pss->mu);
+  POLLABLE_UNREF(pollable_obj, "pollset_set");
+
+  GRPC_LOG_IF_ERROR(err_desc, error);
+}
 
 static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
-                                        grpc_pollset_set *bag,
-                                        grpc_pollset_set *item) {
-  po_join(exec_ctx, &bag->po, &item->po);
+                                        grpc_pollset_set *a,
+                                        grpc_pollset_set *b) {
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG, "PSS: merge (%p, %p)", a, b);
+  }
+  grpc_error *error = GRPC_ERROR_NONE;
+  static const char *err_desc = "pollset_set_add_fd";
+  for (;;) {
+    if (a == b) {
+      // pollset ancestors are the same: nothing to do
+      return;
+    }
+    if (a > b) {
+      GPR_SWAP(grpc_pollset_set *, a, b);
+    }
+    gpr_mu *a_mu = &a->mu;
+    gpr_mu *b_mu = &b->mu;
+    gpr_mu_lock(a_mu);
+    gpr_mu_lock(b_mu);
+    if (a->parent != NULL) {
+      a = a->parent;
+    } else if (b->parent != NULL) {
+      b = b->parent;
+    } else {
+      break;  // exit loop, both pollsets locked
+    }
+    gpr_mu_unlock(a_mu);
+    gpr_mu_unlock(b_mu);
+  }
+  // try to do the least copying possible
+  // TODO(ctiller): there's probably a better heuristic here
+  const size_t a_size = a->fd_count + a->pollset_count;
+  const size_t b_size = b->fd_count + b->pollset_count;
+  if (b_size > a_size) {
+    GPR_SWAP(grpc_pollset_set *, a, b);
+  }
+  if (GRPC_TRACER_ON(grpc_polling_trace)) {
+    gpr_log(GPR_DEBUG, "PSS: parent %p to %p", b, a);
+  }
+  gpr_ref(&a->refs);
+  b->parent = a;
+  if (a->fd_capacity < a->fd_count + b->fd_count) {
+    a->fd_capacity = GPR_MAX(2 * a->fd_capacity, a->fd_count + b->fd_count);
+    a->fds = (grpc_fd **)gpr_realloc(a->fds, a->fd_capacity * sizeof(*a->fds));
+  }
+  size_t initial_a_fd_count = a->fd_count;
+  a->fd_count = 0;
+  append_error(&error, add_fds_to_pollsets(exec_ctx, a->fds, initial_a_fd_count,
+                                           b->pollsets, b->pollset_count,
+                                           "merge_a2b", a->fds, &a->fd_count),
+               err_desc);
+  append_error(&error, add_fds_to_pollsets(exec_ctx, b->fds, b->fd_count,
+                                           a->pollsets, a->pollset_count,
+                                           "merge_b2a", a->fds, &a->fd_count),
+               err_desc);
+  if (a->pollset_capacity < a->pollset_count + b->pollset_count) {
+    a->pollset_capacity =
+        GPR_MAX(2 * a->pollset_capacity, a->pollset_count + b->pollset_count);
+    a->pollsets = (grpc_pollset **)gpr_realloc(
+        a->pollsets, a->pollset_capacity * sizeof(*a->pollsets));
+  }
+  if (b->pollset_count > 0) {
+    memcpy(a->pollsets + a->pollset_count, b->pollsets,
+           b->pollset_count * sizeof(*b->pollsets));
+  }
+  a->pollset_count += b->pollset_count;
+  gpr_free(b->fds);
+  gpr_free(b->pollsets);
+  b->fds = NULL;
+  b->pollsets = NULL;
+  b->fd_count = b->fd_capacity = b->pollset_count = b->pollset_capacity = 0;
+  gpr_mu_unlock(&a->mu);
+  gpr_mu_unlock(&b->mu);
 }
 
 static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
                                         grpc_pollset_set *bag,
                                         grpc_pollset_set *item) {}
 
-static void po_init(polling_obj *po, polling_obj_type type) {
-  gpr_mu_init(&po->mu);
-  po->type = type;
-  po->group = NULL;
-  po->next = po;
-  po->prev = po;
-}
-
-static polling_group *pg_lock_latest(polling_group *pg) {
-  /* assumes pg unlocked; consumes ref, returns ref */
-  gpr_mu_lock(&pg->po.mu);
-  while (pg->po.group != NULL) {
-    polling_group *new_pg = pg_ref(pg->po.group);
-    gpr_mu_unlock(&pg->po.mu);
-    pg_unref(pg);
-    pg = new_pg;
-    gpr_mu_lock(&pg->po.mu);
-  }
-  return pg;
-}
-
-static void po_destroy(polling_obj *po) {
-  if (po->group != NULL) {
-    polling_group *pg = pg_lock_latest(po->group);
-    po->prev->next = po->next;
-    po->next->prev = po->prev;
-    gpr_mu_unlock(&pg->po.mu);
-    pg_unref(pg);
-  }
-  gpr_mu_destroy(&po->mu);
-}
-
-static polling_group *pg_ref(polling_group *pg) {
-  gpr_ref(&pg->refs);
-  return pg;
-}
-
-static void pg_unref(polling_group *pg) {
-  if (gpr_unref(&pg->refs)) {
-    po_destroy(&pg->po);
-    gpr_free(pg);
-  }
-}
-
-static int po_cmp(polling_obj *a, polling_obj *b) {
-  if (a == b) return 0;
-  if (a->type < b->type) return -1;
-  if (a->type > b->type) return 1;
-  if (a < b) return -1;
-  assert(a > b);
-  return 1;
-}
-
-static void po_join(grpc_exec_ctx *exec_ctx, polling_obj *a, polling_obj *b) {
-  switch (po_cmp(a, b)) {
-    case 0:
-      return;
-    case 1:
-      GPR_SWAP(polling_obj *, a, b);
-    /* fall through */
-    case -1:
-      gpr_mu_lock(&a->mu);
-      gpr_mu_lock(&b->mu);
-
-      if (a->group == NULL) {
-        if (b->group == NULL) {
-          polling_obj *initial_po[] = {a, b};
-          pg_create(exec_ctx, initial_po, GPR_ARRAY_SIZE(initial_po));
-          gpr_mu_unlock(&a->mu);
-          gpr_mu_unlock(&b->mu);
-        } else {
-          polling_group *b_group = pg_ref(b->group);
-          gpr_mu_unlock(&b->mu);
-          gpr_mu_unlock(&a->mu);
-          pg_join(exec_ctx, b_group, a);
-        }
-      } else if (b->group == NULL) {
-        polling_group *a_group = pg_ref(a->group);
-        gpr_mu_unlock(&a->mu);
-        gpr_mu_unlock(&b->mu);
-        pg_join(exec_ctx, a_group, b);
-      } else if (a->group == b->group) {
-        /* nothing to do */
-        gpr_mu_unlock(&a->mu);
-        gpr_mu_unlock(&b->mu);
-      } else {
-        polling_group *a_group = pg_ref(a->group);
-        polling_group *b_group = pg_ref(b->group);
-        gpr_mu_unlock(&a->mu);
-        gpr_mu_unlock(&b->mu);
-        pg_merge(exec_ctx, a_group, b_group);
-      }
-  }
-}
-
-static void pg_notify(grpc_exec_ctx *exec_ctx, polling_obj *a, polling_obj *b) {
-  if (a->type == PO_FD && b->type == PO_POLLSET) {
-    pollset_add_fd_locked(exec_ctx, (grpc_pollset *)b, (grpc_fd *)a, true);
-  } else if (a->type == PO_POLLSET && b->type == PO_FD) {
-    pollset_add_fd_locked(exec_ctx, (grpc_pollset *)a, (grpc_fd *)b, true);
-  }
-}
-
-static void pg_broadcast(grpc_exec_ctx *exec_ctx, polling_group *from,
-                         polling_group *to) {
-  for (polling_obj *a = from->po.next; a != &from->po; a = a->next) {
-    for (polling_obj *b = to->po.next; b != &to->po; b = b->next) {
-      if (po_cmp(a, b) < 0) {
-        gpr_mu_lock(&a->mu);
-        gpr_mu_lock(&b->mu);
-      } else {
-        GPR_ASSERT(po_cmp(a, b) != 0);
-        gpr_mu_lock(&b->mu);
-        gpr_mu_lock(&a->mu);
-      }
-      pg_notify(exec_ctx, a, b);
-      gpr_mu_unlock(&a->mu);
-      gpr_mu_unlock(&b->mu);
-    }
-  }
-}
-
-static void pg_create(grpc_exec_ctx *exec_ctx, polling_obj **initial_po,
-                      size_t initial_po_count) {
-  /* assumes all polling objects in initial_po are locked */
-  polling_group *pg = (polling_group *)gpr_malloc(sizeof(*pg));
-  po_init(&pg->po, PO_POLLING_GROUP);
-  gpr_ref_init(&pg->refs, (int)initial_po_count);
-  for (size_t i = 0; i < initial_po_count; i++) {
-    GPR_ASSERT(initial_po[i]->group == NULL);
-    initial_po[i]->group = pg;
-  }
-  for (size_t i = 1; i < initial_po_count; i++) {
-    initial_po[i]->prev = initial_po[i - 1];
-  }
-  for (size_t i = 0; i < initial_po_count - 1; i++) {
-    initial_po[i]->next = initial_po[i + 1];
-  }
-  initial_po[0]->prev = &pg->po;
-  initial_po[initial_po_count - 1]->next = &pg->po;
-  pg->po.next = initial_po[0];
-  pg->po.prev = initial_po[initial_po_count - 1];
-  for (size_t i = 1; i < initial_po_count; i++) {
-    for (size_t j = 0; j < i; j++) {
-      pg_notify(exec_ctx, initial_po[i], initial_po[j]);
-    }
-  }
-}
-
-static void pg_join(grpc_exec_ctx *exec_ctx, polling_group *pg,
-                    polling_obj *po) {
-  /* assumes neither pg nor po are locked; consumes one ref to pg */
-  pg = pg_lock_latest(pg);
-  /* pg locked */
-  for (polling_obj *existing = pg->po.next /* skip pg - it's just a stub */;
-       existing != &pg->po; existing = existing->next) {
-    if (po_cmp(po, existing) < 0) {
-      gpr_mu_lock(&po->mu);
-      gpr_mu_lock(&existing->mu);
-    } else {
-      GPR_ASSERT(po_cmp(po, existing) != 0);
-      gpr_mu_lock(&existing->mu);
-      gpr_mu_lock(&po->mu);
-    }
-    /* pg, po, existing locked */
-    if (po->group != NULL) {
-      gpr_mu_unlock(&pg->po.mu);
-      polling_group *po_group = pg_ref(po->group);
-      gpr_mu_unlock(&po->mu);
-      gpr_mu_unlock(&existing->mu);
-      pg_merge(exec_ctx, pg, po_group);
-      /* early exit: polling obj picked up a group during joining: we needed
-         to do a full merge */
-      return;
-    }
-    pg_notify(exec_ctx, po, existing);
-    gpr_mu_unlock(&po->mu);
-    gpr_mu_unlock(&existing->mu);
-  }
-  gpr_mu_lock(&po->mu);
-  if (po->group != NULL) {
-    gpr_mu_unlock(&pg->po.mu);
-    polling_group *po_group = pg_ref(po->group);
-    gpr_mu_unlock(&po->mu);
-    pg_merge(exec_ctx, pg, po_group);
-    /* early exit: polling obj picked up a group during joining: we needed
-       to do a full merge */
-    return;
-  }
-  po->group = pg;
-  po->next = &pg->po;
-  po->prev = pg->po.prev;
-  po->prev->next = po->next->prev = po;
-  gpr_mu_unlock(&pg->po.mu);
-  gpr_mu_unlock(&po->mu);
-}
-
-static void pg_merge(grpc_exec_ctx *exec_ctx, polling_group *a,
-                     polling_group *b) {
-  for (;;) {
-    if (a == b) {
-      pg_unref(a);
-      pg_unref(b);
-      return;
-    }
-    if (a > b) GPR_SWAP(polling_group *, a, b);
-    gpr_mu_lock(&a->po.mu);
-    gpr_mu_lock(&b->po.mu);
-    if (a->po.group != NULL) {
-      polling_group *m2 = pg_ref(a->po.group);
-      gpr_mu_unlock(&a->po.mu);
-      gpr_mu_unlock(&b->po.mu);
-      pg_unref(a);
-      a = m2;
-    } else if (b->po.group != NULL) {
-      polling_group *m2 = pg_ref(b->po.group);
-      gpr_mu_unlock(&a->po.mu);
-      gpr_mu_unlock(&b->po.mu);
-      pg_unref(b);
-      b = m2;
-    } else {
-      break;
-    }
-  }
-  polling_group **unref = NULL;
-  size_t unref_count = 0;
-  size_t unref_cap = 0;
-  b->po.group = a;
-  pg_broadcast(exec_ctx, a, b);
-  pg_broadcast(exec_ctx, b, a);
-  while (b->po.next != &b->po) {
-    polling_obj *po = b->po.next;
-    gpr_mu_lock(&po->mu);
-    if (unref_count == unref_cap) {
-      unref_cap = GPR_MAX(8, 3 * unref_cap / 2);
-      unref = (polling_group **)gpr_realloc(unref, unref_cap * sizeof(*unref));
-    }
-    unref[unref_count++] = po->group;
-    po->group = pg_ref(a);
-    // unlink from b
-    po->prev->next = po->next;
-    po->next->prev = po->prev;
-    // link to a
-    po->next = &a->po;
-    po->prev = a->po.prev;
-    po->next->prev = po->prev->next = po;
-    gpr_mu_unlock(&po->mu);
-  }
-  gpr_mu_unlock(&a->po.mu);
-  gpr_mu_unlock(&b->po.mu);
-  for (size_t i = 0; i < unref_count; i++) {
-    pg_unref(unref[i]);
-  }
-  gpr_free(unref);
-  pg_unref(b);
-}
-
 /*******************************************************************************
  * Event engine binding
  */
@@ -1399,7 +1428,7 @@
     pollset_add_fd,
 
     pollset_set_create,
-    pollset_set_destroy,
+    pollset_set_unref,  // destroy ==> unref 1 public ref
     pollset_set_add_pollset,
     pollset_set_del_pollset,
     pollset_set_add_pollset_set,
@@ -1412,6 +1441,10 @@
 
 const grpc_event_engine_vtable *grpc_init_epollex_linux(
     bool explicitly_requested) {
+  if (!explicitly_requested) {
+    return NULL;
+  }
+
   if (!grpc_has_wakeup_fd()) {
     return NULL;
   }
@@ -1420,6 +1453,10 @@
     return NULL;
   }
 
+#ifndef NDEBUG
+  grpc_register_tracer(&grpc_trace_pollable_refcount);
+#endif
+
   fd_global_init();
 
   if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
diff --git a/src/core/lib/iomgr/ev_epollex_linux.h b/src/core/lib/iomgr/ev_epollex_linux.h
index 58cc5a2..2849a23 100644
--- a/src/core/lib/iomgr/ev_epollex_linux.h
+++ b/src/core/lib/iomgr/ev_epollex_linux.h
@@ -33,4 +33,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLLEX_LINUX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLLEX_LINUX_H */
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc
index 370ea1d..035bdc4 100644
--- a/src/core/lib/iomgr/ev_epollsig_linux.cc
+++ b/src/core/lib/iomgr/ev_epollsig_linux.cc
@@ -18,6 +18,8 @@
 
 #include "src/core/lib/iomgr/port.h"
 
+#include <grpc/grpc_posix.h>
+
 /* This polling engine is only relevant on linux kernels supporting epoll() */
 #ifdef GRPC_LINUX_EPOLL
 
diff --git a/src/core/lib/iomgr/ev_poll_posix.h b/src/core/lib/iomgr/ev_poll_posix.h
index 84b6815..8612572 100644
--- a/src/core/lib/iomgr/ev_poll_posix.h
+++ b/src/core/lib/iomgr/ev_poll_posix.h
@@ -32,4 +32,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H */
diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc
index e4033fa..677ee67 100644
--- a/src/core/lib/iomgr/ev_posix.cc
+++ b/src/core/lib/iomgr/ev_posix.cc
@@ -61,12 +61,40 @@
   event_engine_factory_fn factory;
 } event_engine_factory;
 
+namespace {
+
+extern "C" {
+
+grpc_poll_function_type real_poll_function;
+
+int dummy_poll(struct pollfd fds[], nfds_t nfds, int timeout) {
+  if (timeout == 0) {
+    return real_poll_function(fds, nfds, 0);
+  } else {
+    gpr_log(GPR_ERROR, "Attempted a blocking poll when declared non-polling.");
+    GPR_ASSERT(false);
+    return -1;
+  }
+}
+}  // extern "C"
+
+const grpc_event_engine_vtable *init_non_polling(bool explicit_request) {
+  if (!explicit_request) {
+    return nullptr;
+  }
+  // return the simplest engine as a dummy but also override the poller
+  auto ret = grpc_init_poll_posix(explicit_request);
+  real_poll_function = grpc_poll_function;
+  grpc_poll_function = dummy_poll;
+
+  return ret;
+}
+}  // namespace
+
 static const event_engine_factory g_factories[] = {
-    {"epoll1", grpc_init_epoll1_linux},
-    {"epollsig", grpc_init_epollsig_linux},
-    {"poll", grpc_init_poll_posix},
-    {"poll-cv", grpc_init_poll_cv_posix},
-    {"epollex", grpc_init_epollex_linux},
+    {"epollex", grpc_init_epollex_linux},   {"epoll1", grpc_init_epoll1_linux},
+    {"epollsig", grpc_init_epollsig_linux}, {"poll", grpc_init_poll_posix},
+    {"poll-cv", grpc_init_poll_cv_posix},   {"none", init_non_polling},
 };
 
 static void add(const char *beg, const char *end, char ***ss, size_t *ns) {
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
index 955326c..bc4456c 100644
--- a/src/core/lib/iomgr/ev_posix.h
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -166,4 +166,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */
diff --git a/src/core/lib/iomgr/exec_ctx.cc b/src/core/lib/iomgr/exec_ctx.cc
index 3d17afc..0394a00 100644
--- a/src/core/lib/iomgr/exec_ctx.cc
+++ b/src/core/lib/iomgr/exec_ctx.cc
@@ -152,6 +152,15 @@
 
 gpr_timespec grpc_millis_to_timespec(grpc_millis millis,
                                      gpr_clock_type clock_type) {
+  // special-case infinities as grpc_millis can be 32bit on some platforms
+  // while gpr_time_from_millis always takes an int64_t.
+  if (millis == GRPC_MILLIS_INF_FUTURE) {
+    return gpr_inf_future(clock_type);
+  }
+  if (millis == GRPC_MILLIS_INF_PAST) {
+    return gpr_inf_past(clock_type);
+  }
+
   if (clock_type == GPR_TIMESPAN) {
     return gpr_time_from_millis(millis, GPR_TIMESPAN);
   }
diff --git a/src/core/lib/iomgr/executor.h b/src/core/lib/iomgr/executor.h
index ab3fc90..ef5ac56 100644
--- a/src/core/lib/iomgr/executor.h
+++ b/src/core/lib/iomgr/executor.h
@@ -53,4 +53,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_EXECUTOR_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_EXECUTOR_H */
diff --git a/src/core/lib/iomgr/iocp_windows.cc b/src/core/lib/iomgr/iocp_windows.cc
index 336cc86..78185cc 100644
--- a/src/core/lib/iomgr/iocp_windows.cc
+++ b/src/core/lib/iomgr/iocp_windows.cc
@@ -21,6 +21,7 @@
 #ifdef GRPC_WINSOCK_SOCKET
 
 #include <winsock2.h>
+#include <limits>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -43,11 +44,14 @@
 
 static DWORD deadline_to_millis_timeout(grpc_exec_ctx *exec_ctx,
                                         grpc_millis deadline) {
-  gpr_timespec timeout;
   if (deadline == GRPC_MILLIS_INF_FUTURE) {
     return INFINITE;
   }
-  return (DWORD)GPR_MAX(0, deadline - grpc_exec_ctx_now(exec_ctx));
+  grpc_millis now = grpc_exec_ctx_now(exec_ctx);
+  if (deadline < now) return 0;
+  grpc_millis timeout = deadline - now;
+  if (timeout > std::numeric_limits<DWORD>::max()) return INFINITE;
+  return static_cast<DWORD>(deadline - now);
 }
 
 grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
@@ -63,6 +67,7 @@
   success =
       GetQueuedCompletionStatus(g_iocp, &bytes, &completion_key, &overlapped,
                                 deadline_to_millis_timeout(exec_ctx, deadline));
+  grpc_exec_ctx_invalidate_now(exec_ctx);
   if (success == 0 && overlapped == NULL) {
     return GRPC_IOCP_WORK_TIMEOUT;
   }
diff --git a/src/core/lib/iomgr/iocp_windows.h b/src/core/lib/iomgr/iocp_windows.h
index aefe7a2..4efbc946 100644
--- a/src/core/lib/iomgr/iocp_windows.h
+++ b/src/core/lib/iomgr/iocp_windows.h
@@ -45,4 +45,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H */
diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h
index fea0849..6c0a08b 100644
--- a/src/core/lib/iomgr/iomgr.h
+++ b/src/core/lib/iomgr/iomgr.h
@@ -40,4 +40,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_H */
diff --git a/src/core/lib/iomgr/iomgr_internal.h b/src/core/lib/iomgr/iomgr_internal.h
index 005abbe..52db37c 100644
--- a/src/core/lib/iomgr/iomgr_internal.h
+++ b/src/core/lib/iomgr/iomgr_internal.h
@@ -48,4 +48,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */
diff --git a/src/core/lib/iomgr/is_epollexclusive_available.h b/src/core/lib/iomgr/is_epollexclusive_available.h
index 5c3e483..9ae9c5c 100644
--- a/src/core/lib/iomgr/is_epollexclusive_available.h
+++ b/src/core/lib/iomgr/is_epollexclusive_available.h
@@ -31,4 +31,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_IS_EPOLLEXCLUSIVE_AVAILABLE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_IS_EPOLLEXCLUSIVE_AVAILABLE_H */
diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h
index 925f004..02229e5 100644
--- a/src/core/lib/iomgr/lockfree_event.h
+++ b/src/core/lib/iomgr/lockfree_event.h
@@ -45,4 +45,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_LOCKFREE_EVENT_H */
diff --git a/src/core/lib/iomgr/network_status_tracker.h b/src/core/lib/iomgr/network_status_tracker.h
index af50d51..cba38d4 100644
--- a/src/core/lib/iomgr/network_status_tracker.h
+++ b/src/core/lib/iomgr/network_status_tracker.h
@@ -35,4 +35,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H */
diff --git a/src/core/lib/iomgr/polling_entity.h b/src/core/lib/iomgr/polling_entity.h
index 4a37acf..009f968 100644
--- a/src/core/lib/iomgr/polling_entity.h
+++ b/src/core/lib/iomgr/polling_entity.h
@@ -72,4 +72,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_POLLING_ENTITY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_POLLING_ENTITY_H */
diff --git a/src/core/lib/iomgr/pollset_set.h b/src/core/lib/iomgr/pollset_set.h
index 17df865..5455eda 100644
--- a/src/core/lib/iomgr/pollset_set.h
+++ b/src/core/lib/iomgr/pollset_set.h
@@ -52,4 +52,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_SET_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_SET_H */
diff --git a/src/core/lib/iomgr/pollset_uv.h b/src/core/lib/iomgr/pollset_uv.h
index d8f72ff..5cc9faf 100644
--- a/src/core/lib/iomgr/pollset_uv.h
+++ b/src/core/lib/iomgr/pollset_uv.h
@@ -32,4 +32,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_UV_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_UV_H */
diff --git a/src/core/lib/iomgr/pollset_windows.h b/src/core/lib/iomgr/pollset_windows.h
index 7733d26..2479b25 100644
--- a/src/core/lib/iomgr/pollset_windows.h
+++ b/src/core/lib/iomgr/pollset_windows.h
@@ -68,4 +68,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_WINDOWS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_WINDOWS_H */
diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h
index 42033d0..1cc6d98 100644
--- a/src/core/lib/iomgr/port.h
+++ b/src/core/lib/iomgr/port.h
@@ -109,6 +109,16 @@
 #define GRPC_POSIX_SOCKETUTILS 1
 #define GRPC_POSIX_WAKEUP_FD 1
 #define GRPC_TIMER_USE_GENERIC 1
+#elif defined(GPR_OPENBSD)
+#define GRPC_HAVE_IFADDRS 1
+#define GRPC_HAVE_IPV6_RECVPKTINFO 1
+#define GRPC_HAVE_UNIX_SOCKET 1
+#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1
+#define GRPC_POSIX_SOCKET 1
+#define GRPC_POSIX_SOCKETADDR 1
+#define GRPC_POSIX_SOCKETUTILS 1
+#define GRPC_POSIX_WAKEUP_FD 1
+#define GRPC_TIMER_USE_GENERIC 1
 #elif defined(GPR_NACL)
 #define GRPC_HAVE_ARPA_NAMESER 1
 #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1
diff --git a/src/core/lib/iomgr/resolve_address.h b/src/core/lib/iomgr/resolve_address.h
index 4a6df2c..5f06342 100644
--- a/src/core/lib/iomgr/resolve_address.h
+++ b/src/core/lib/iomgr/resolve_address.h
@@ -60,4 +60,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */
diff --git a/src/core/lib/iomgr/resource_quota.h b/src/core/lib/iomgr/resource_quota.h
index 3afb525..1d4249b 100644
--- a/src/core/lib/iomgr/resource_quota.h
+++ b/src/core/lib/iomgr/resource_quota.h
@@ -158,4 +158,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_RESOURCE_QUOTA_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_RESOURCE_QUOTA_H */
diff --git a/src/core/lib/iomgr/sockaddr_utils.h b/src/core/lib/iomgr/sockaddr_utils.h
index 129bb54..1fd552f 100644
--- a/src/core/lib/iomgr/sockaddr_utils.h
+++ b/src/core/lib/iomgr/sockaddr_utils.h
@@ -85,4 +85,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */
diff --git a/src/core/lib/iomgr/socket_utils.h b/src/core/lib/iomgr/socket_utils.h
index f319e93..d6c538e 100644
--- a/src/core/lib/iomgr/socket_utils.h
+++ b/src/core/lib/iomgr/socket_utils.h
@@ -32,4 +32,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_H */
diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h
index 623b83f..73809b6 100644
--- a/src/core/lib/iomgr/socket_utils_posix.h
+++ b/src/core/lib/iomgr/socket_utils_posix.h
@@ -137,4 +137,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H */
diff --git a/src/core/lib/iomgr/socket_windows.h b/src/core/lib/iomgr/socket_windows.h
index a00a761..84fa071 100644
--- a/src/core/lib/iomgr/socket_windows.h
+++ b/src/core/lib/iomgr/socket_windows.h
@@ -115,4 +115,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */
diff --git a/src/core/lib/iomgr/tcp_client.h b/src/core/lib/iomgr/tcp_client.h
index 1b102b5..b2f365f 100644
--- a/src/core/lib/iomgr/tcp_client.h
+++ b/src/core/lib/iomgr/tcp_client.h
@@ -45,4 +45,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TCP_CLIENT_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_CLIENT_H */
diff --git a/src/core/lib/iomgr/tcp_client_posix.h b/src/core/lib/iomgr/tcp_client_posix.h
index 0b97755..8740511 100644
--- a/src/core/lib/iomgr/tcp_client_posix.h
+++ b/src/core/lib/iomgr/tcp_client_posix.h
@@ -35,4 +35,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TCP_CLIENT_POSIX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_CLIENT_POSIX_H */
diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc
index 7fcaef7..b7c1803 100644
--- a/src/core/lib/iomgr/tcp_posix.cc
+++ b/src/core/lib/iomgr/tcp_posix.cc
@@ -186,7 +186,7 @@
   }
   if (old_count == 0) {
     GRPC_STATS_INC_TCP_BACKUP_POLLERS_CREATED(exec_ctx);
-    p = (backup_poller *)gpr_malloc(sizeof(*p) + grpc_pollset_size());
+    p = (backup_poller *)gpr_zalloc(sizeof(*p) + grpc_pollset_size());
     if (GRPC_TRACER_ON(grpc_tcp_trace)) {
       gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p create", p);
     }
@@ -704,6 +704,13 @@
   grpc_pollset_set_add_fd(exec_ctx, pollset_set, tcp->em_fd);
 }
 
+static void tcp_delete_from_pollset_set(grpc_exec_ctx *exec_ctx,
+                                        grpc_endpoint *ep,
+                                        grpc_pollset_set *pollset_set) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  grpc_pollset_set_del_fd(exec_ctx, pollset_set, tcp->em_fd);
+}
+
 static char *tcp_get_peer(grpc_endpoint *ep) {
   grpc_tcp *tcp = (grpc_tcp *)ep;
   return gpr_strdup(tcp->peer_string);
@@ -719,10 +726,16 @@
   return tcp->resource_user;
 }
 
-static const grpc_endpoint_vtable vtable = {
-    tcp_read,     tcp_write,   tcp_add_to_pollset,    tcp_add_to_pollset_set,
-    tcp_shutdown, tcp_destroy, tcp_get_resource_user, tcp_get_peer,
-    tcp_get_fd};
+static const grpc_endpoint_vtable vtable = {tcp_read,
+                                            tcp_write,
+                                            tcp_add_to_pollset,
+                                            tcp_add_to_pollset_set,
+                                            tcp_delete_from_pollset_set,
+                                            tcp_shutdown,
+                                            tcp_destroy,
+                                            tcp_get_resource_user,
+                                            tcp_get_peer,
+                                            tcp_get_fd};
 
 #define MAX_CHUNK_SIZE 32 * 1024 * 1024
 
diff --git a/src/core/lib/iomgr/tcp_posix.h b/src/core/lib/iomgr/tcp_posix.h
index dda78b2..47e78fa 100644
--- a/src/core/lib/iomgr/tcp_posix.h
+++ b/src/core/lib/iomgr/tcp_posix.h
@@ -61,4 +61,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TCP_POSIX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_POSIX_H */
diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h
index 3f190ac..8f9ce38 100644
--- a/src/core/lib/iomgr/tcp_server.h
+++ b/src/core/lib/iomgr/tcp_server.h
@@ -106,4 +106,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_H */
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h
index 4bb0660..6746333 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix.h
+++ b/src/core/lib/iomgr/tcp_server_utils_posix.h
@@ -125,4 +125,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H */
diff --git a/src/core/lib/iomgr/tcp_uv.cc b/src/core/lib/iomgr/tcp_uv.cc
index e311964..99b9f1e 100644
--- a/src/core/lib/iomgr/tcp_uv.cc
+++ b/src/core/lib/iomgr/tcp_uv.cc
@@ -304,6 +304,15 @@
   (void)pollset;
 }
 
+static void uv_delete_from_pollset_set(grpc_exec_ctx *exec_ctx,
+                                       grpc_endpoint *ep,
+                                       grpc_pollset_set *pollset) {
+  // No-op. We're ignoring pollsets currently
+  (void)exec_ctx;
+  (void)ep;
+  (void)pollset;
+}
+
 static void shutdown_callback(uv_shutdown_t *req, int status) {}
 
 static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
@@ -340,10 +349,16 @@
 
 static int uv_get_fd(grpc_endpoint *ep) { return -1; }
 
-static grpc_endpoint_vtable vtable = {
-    uv_endpoint_read,      uv_endpoint_write,    uv_add_to_pollset,
-    uv_add_to_pollset_set, uv_endpoint_shutdown, uv_destroy,
-    uv_get_resource_user,  uv_get_peer,          uv_get_fd};
+static grpc_endpoint_vtable vtable = {uv_endpoint_read,
+                                      uv_endpoint_write,
+                                      uv_add_to_pollset,
+                                      uv_add_to_pollset_set,
+                                      uv_delete_from_pollset_set,
+                                      uv_endpoint_shutdown,
+                                      uv_destroy,
+                                      uv_get_resource_user,
+                                      uv_get_peer,
+                                      uv_get_fd};
 
 grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle,
                                grpc_resource_quota *resource_quota,
diff --git a/src/core/lib/iomgr/tcp_uv.h b/src/core/lib/iomgr/tcp_uv.h
index ba7db8a..3399535 100644
--- a/src/core/lib/iomgr/tcp_uv.h
+++ b/src/core/lib/iomgr/tcp_uv.h
@@ -50,4 +50,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TCP_UV_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TCP_UV_H */
diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc
index dc84e56..5aba507 100644
--- a/src/core/lib/iomgr/tcp_windows.cc
+++ b/src/core/lib/iomgr/tcp_windows.cc
@@ -371,6 +371,10 @@
   grpc_iocp_add_socket(tcp->socket);
 }
 
+static void win_delete_from_pollset_set(grpc_exec_ctx *exec_ctx,
+                                        grpc_endpoint *ep,
+                                        grpc_pollset_set *pss) {}
+
 /* Initiates a shutdown of the TCP endpoint. This will queue abort callbacks
    for the potential read and write operations. It is up to the caller to
    guarantee this isn't called in parallel to a read or write request, so
@@ -412,10 +416,16 @@
 
 static int win_get_fd(grpc_endpoint *ep) { return -1; }
 
-static grpc_endpoint_vtable vtable = {
-    win_read,     win_write,   win_add_to_pollset,    win_add_to_pollset_set,
-    win_shutdown, win_destroy, win_get_resource_user, win_get_peer,
-    win_get_fd};
+static grpc_endpoint_vtable vtable = {win_read,
+                                      win_write,
+                                      win_add_to_pollset,
+                                      win_add_to_pollset_set,
+                                      win_delete_from_pollset_set,
+                                      win_shutdown,
+                                      win_destroy,
+                                      win_get_resource_user,
+                                      win_get_peer,
+                                      win_get_fd};
 
 grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
                                grpc_channel_args *channel_args,
diff --git a/src/core/lib/iomgr/time_averaged_stats.h b/src/core/lib/iomgr/time_averaged_stats.h
index e255b58..d38ed27 100644
--- a/src/core/lib/iomgr/time_averaged_stats.h
+++ b/src/core/lib/iomgr/time_averaged_stats.h
@@ -78,4 +78,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TIME_AVERAGED_STATS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TIME_AVERAGED_STATS_H */
diff --git a/src/core/lib/iomgr/timer_heap.h b/src/core/lib/iomgr/timer_heap.h
index f15e8a3..228d038 100644
--- a/src/core/lib/iomgr/timer_heap.h
+++ b/src/core/lib/iomgr/timer_heap.h
@@ -47,4 +47,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H */
diff --git a/src/core/lib/iomgr/timer_manager.h b/src/core/lib/iomgr/timer_manager.h
index d8a59a9..72960d6 100644
--- a/src/core/lib/iomgr/timer_manager.h
+++ b/src/core/lib/iomgr/timer_manager.h
@@ -42,4 +42,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_TIMER_MANAGER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_TIMER_MANAGER_H */
diff --git a/src/core/lib/iomgr/udp_server.h b/src/core/lib/iomgr/udp_server.h
index bcd8572..e887cb1 100644
--- a/src/core/lib/iomgr/udp_server.h
+++ b/src/core/lib/iomgr/udp_server.h
@@ -81,4 +81,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_UDP_SERVER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_UDP_SERVER_H */
diff --git a/src/core/lib/iomgr/unix_sockets_posix.h b/src/core/lib/iomgr/unix_sockets_posix.h
index b96131a..3e7f9c7 100644
--- a/src/core/lib/iomgr/unix_sockets_posix.h
+++ b/src/core/lib/iomgr/unix_sockets_posix.h
@@ -46,4 +46,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H */
diff --git a/src/core/lib/json/json.h b/src/core/lib/json/json.h
index 81b7e0c..c9fdec4 100644
--- a/src/core/lib/json/json.h
+++ b/src/core/lib/json/json.h
@@ -78,4 +78,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_JSON_JSON_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_JSON_JSON_H */
diff --git a/src/core/lib/json/json_reader.h b/src/core/lib/json/json_reader.h
index ab2384f..7f14a9a 100644
--- a/src/core/lib/json/json_reader.h
+++ b/src/core/lib/json/json_reader.h
@@ -150,4 +150,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_JSON_JSON_READER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_JSON_JSON_READER_H */
diff --git a/src/core/lib/json/json_writer.h b/src/core/lib/json/json_writer.h
index 18bd2a8..132d1f2 100644
--- a/src/core/lib/json/json_writer.h
+++ b/src/core/lib/json/json_writer.h
@@ -87,4 +87,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_JSON_JSON_WRITER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_JSON_JSON_WRITER_H */
diff --git a/src/core/lib/profiling/basic_timers.cc b/src/core/lib/profiling/basic_timers.cc
index ab9d604..0ae7d7f 100644
--- a/src/core/lib/profiling/basic_timers.cc
+++ b/src/core/lib/profiling/basic_timers.cc
@@ -209,9 +209,9 @@
 
 static void rotate_log() {
   /* Using malloc here, as this code could end up being called by gpr_malloc */
-  gpr_timer_log *new = malloc(sizeof(*new));
+  gpr_timer_log *log = static_cast<gpr_timer_log *>(malloc(sizeof(*log)));
   gpr_once_init(&g_once_init, init_output);
-  new->num_entries = 0;
+  log->num_entries = 0;
   pthread_mutex_lock(&g_mu);
   if (g_thread_log != NULL) {
     timer_log_remove(&g_in_progress_logs, g_thread_log);
@@ -221,9 +221,9 @@
   } else {
     g_thread_id = g_next_thread_id++;
   }
-  timer_log_push_back(&g_in_progress_logs, new);
+  timer_log_push_back(&g_in_progress_logs, log);
   pthread_mutex_unlock(&g_mu);
-  g_thread_log = new;
+  g_thread_log = log;
 }
 
 static void gpr_timers_log_add(const char *tagstr, marker_type type,
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.cc b/src/core/lib/security/credentials/fake/fake_credentials.cc
index 795ca06..cf10bf2 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.cc
+++ b/src/core/lib/security/credentials/fake/fake_credentials.cc
@@ -38,7 +38,8 @@
     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, target, args);
+  *sc =
+      grpc_fake_channel_security_connector_create(c, call_creds, target, args);
   return GRPC_SECURITY_OK;
 }
 
@@ -46,7 +47,7 @@
 fake_transport_security_server_create_security_connector(
     grpc_exec_ctx *exec_ctx, grpc_server_credentials *c,
     grpc_server_security_connector **sc) {
-  *sc = grpc_fake_server_security_connector_create();
+  *sc = grpc_fake_server_security_connector_create(c);
   return GRPC_SECURITY_OK;
 }
 
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h
index 64f6f43..ed3f893 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.h
+++ b/src/core/lib/security/credentials/fake/fake_credentials.h
@@ -64,4 +64,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_FAKE_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.h b/src/core/lib/security/credentials/jwt/jwt_credentials.h
index c09485f..5cee6ed 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.h
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.h
@@ -53,4 +53,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc b/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
index f52a424..7867105 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
@@ -262,7 +262,7 @@
   grpc_mdelem cached_access_token_md = GRPC_MDNULL;
   gpr_mu_lock(&c->mu);
   if (!GRPC_MDISNULL(c->access_token_md) &&
-      (c->token_expiration + grpc_exec_ctx_now(exec_ctx) > refresh_threshold)) {
+      (c->token_expiration - grpc_exec_ctx_now(exec_ctx) > refresh_threshold)) {
     cached_access_token_md = GRPC_MDELEM_REF(c->access_token_md);
   }
   if (!GRPC_MDISNULL(cached_access_token_md)) {
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 4beaec9..c12db89 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -110,4 +110,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/src/core/lib/security/credentials/ssl/ssl_credentials.cc
index 9df69a2..8e47aeb 100644
--- a/src/core/lib/security/credentials/ssl/ssl_credentials.cc
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.cc
@@ -31,18 +31,21 @@
 // SSL Channel Credentials.
 //
 
-static void ssl_config_pem_key_cert_pair_destroy(
-    tsi_ssl_pem_key_cert_pair *kp) {
+void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair *kp,
+                                             size_t num_key_cert_pairs) {
   if (kp == NULL) return;
-  gpr_free((void *)kp->private_key);
-  gpr_free((void *)kp->cert_chain);
+  for (size_t i = 0; i < num_key_cert_pairs; i++) {
+    gpr_free((void *)kp[i].private_key);
+    gpr_free((void *)kp[i].cert_chain);
+  }
+  gpr_free(kp);
 }
 
 static void ssl_destruct(grpc_exec_ctx *exec_ctx,
                          grpc_channel_credentials *creds) {
   grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
   gpr_free(c->config.pem_root_certs);
-  ssl_config_pem_key_cert_pair_destroy(&c->config.pem_key_cert_pair);
+  grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pair, 1);
 }
 
 static grpc_security_status ssl_create_security_connector(
@@ -62,7 +65,8 @@
     }
   }
   status = grpc_ssl_channel_security_connector_create(
-      exec_ctx, call_creds, &c->config, target, overridden_target_name, sc);
+      exec_ctx, creds, call_creds, &c->config, target, overridden_target_name,
+      sc);
   if (status != GRPC_SECURITY_OK) {
     return status;
   }
@@ -84,9 +88,11 @@
   if (pem_key_cert_pair != NULL) {
     GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
     GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
-    config->pem_key_cert_pair.cert_chain =
+    config->pem_key_cert_pair = (tsi_ssl_pem_key_cert_pair *)gpr_zalloc(
+        sizeof(tsi_ssl_pem_key_cert_pair));
+    config->pem_key_cert_pair->cert_chain =
         gpr_strdup(pem_key_cert_pair->cert_chain);
-    config->pem_key_cert_pair.private_key =
+    config->pem_key_cert_pair->private_key =
         gpr_strdup(pem_key_cert_pair->private_key);
   }
 }
@@ -116,11 +122,8 @@
 static void ssl_server_destruct(grpc_exec_ctx *exec_ctx,
                                 grpc_server_credentials *creds) {
   grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
-  size_t i;
-  for (i = 0; i < c->config.num_key_cert_pairs; i++) {
-    ssl_config_pem_key_cert_pair_destroy(&c->config.pem_key_cert_pairs[i]);
-  }
-  gpr_free(c->config.pem_key_cert_pairs);
+  grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pairs,
+                                          c->config.num_key_cert_pairs);
   gpr_free(c->config.pem_root_certs);
 }
 
@@ -128,36 +131,43 @@
     grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds,
     grpc_server_security_connector **sc) {
   grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
-  return grpc_ssl_server_security_connector_create(exec_ctx, &c->config, sc);
+  return grpc_ssl_server_security_connector_create(exec_ctx, creds, &c->config,
+                                                   sc);
 }
 
 static grpc_server_credentials_vtable ssl_server_vtable = {
     ssl_server_destruct, ssl_server_create_security_connector};
 
+tsi_ssl_pem_key_cert_pair *grpc_convert_grpc_to_tsi_cert_pairs(
+    const grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+    size_t num_key_cert_pairs) {
+  tsi_ssl_pem_key_cert_pair *tsi_pairs = NULL;
+  if (num_key_cert_pairs > 0) {
+    GPR_ASSERT(pem_key_cert_pairs != NULL);
+    tsi_pairs = (tsi_ssl_pem_key_cert_pair *)gpr_zalloc(
+        num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair));
+  }
+  for (size_t i = 0; i < num_key_cert_pairs; i++) {
+    GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
+    GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
+    tsi_pairs[i].cert_chain = gpr_strdup(pem_key_cert_pairs[i].cert_chain);
+    tsi_pairs[i].private_key = gpr_strdup(pem_key_cert_pairs[i].private_key);
+  }
+  return tsi_pairs;
+}
+
 static void ssl_build_server_config(
     const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
     size_t num_key_cert_pairs,
     grpc_ssl_client_certificate_request_type client_certificate_request,
     grpc_ssl_server_config *config) {
-  size_t i;
   config->client_certificate_request = client_certificate_request;
   if (pem_root_certs != NULL) {
     config->pem_root_certs = gpr_strdup(pem_root_certs);
   }
-  if (num_key_cert_pairs > 0) {
-    GPR_ASSERT(pem_key_cert_pairs != NULL);
-    config->pem_key_cert_pairs = (tsi_ssl_pem_key_cert_pair *)gpr_zalloc(
-        num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair));
-  }
+  config->pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs(
+      pem_key_cert_pairs, num_key_cert_pairs);
   config->num_key_cert_pairs = num_key_cert_pairs;
-  for (i = 0; i < num_key_cert_pairs; i++) {
-    GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL);
-    GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL);
-    config->pem_key_cert_pairs[i].cert_chain =
-        gpr_strdup(pem_key_cert_pairs[i].cert_chain);
-    config->pem_key_cert_pairs[i].private_key =
-        gpr_strdup(pem_key_cert_pairs[i].private_key);
-  }
 }
 
 grpc_server_credentials *grpc_ssl_server_credentials_create(
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.h b/src/core/lib/security/credentials/ssl/ssl_credentials.h
index b43c656..42e425d 100644
--- a/src/core/lib/security/credentials/ssl/ssl_credentials.h
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.h
@@ -20,6 +20,10 @@
 
 #include "src/core/lib/security/credentials/credentials.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct {
   grpc_channel_credentials base;
   grpc_ssl_config config;
@@ -30,4 +34,15 @@
   grpc_ssl_server_config config;
 } grpc_ssl_server_credentials;
 
+tsi_ssl_pem_key_cert_pair *grpc_convert_grpc_to_tsi_cert_pairs(
+    const grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+    size_t num_key_cert_pairs);
+
+void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair *kp,
+                                             size_t num_key_cert_pairs);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H */
diff --git a/src/core/lib/security/transport/lb_targets_info.h b/src/core/lib/security/transport/lb_targets_info.h
index 705d33b..43f0e64 100644
--- a/src/core/lib/security/transport/lb_targets_info.h
+++ b/src/core/lib/security/transport/lb_targets_info.h
@@ -37,4 +37,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H */
diff --git a/src/core/lib/security/transport/secure_endpoint.cc b/src/core/lib/security/transport/secure_endpoint.cc
index ae5633b..859d04a 100644
--- a/src/core/lib/security/transport/secure_endpoint.cc
+++ b/src/core/lib/security/transport/secure_endpoint.cc
@@ -379,6 +379,13 @@
   grpc_endpoint_add_to_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set);
 }
 
+static void endpoint_delete_from_pollset_set(grpc_exec_ctx *exec_ctx,
+                                             grpc_endpoint *secure_ep,
+                                             grpc_pollset_set *pollset_set) {
+  secure_endpoint *ep = (secure_endpoint *)secure_ep;
+  grpc_endpoint_delete_from_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set);
+}
+
 static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
   secure_endpoint *ep = (secure_endpoint *)secure_ep;
   return grpc_endpoint_get_peer(ep->wrapped_ep);
@@ -399,6 +406,7 @@
                                             endpoint_write,
                                             endpoint_add_to_pollset,
                                             endpoint_add_to_pollset_set,
+                                            endpoint_delete_from_pollset_set,
                                             endpoint_shutdown,
                                             endpoint_destroy,
                                             endpoint_get_resource_user,
diff --git a/src/core/lib/security/transport/secure_endpoint.h b/src/core/lib/security/transport/secure_endpoint.h
index 832cc1c..980449c 100644
--- a/src/core/lib/security/transport/secure_endpoint.h
+++ b/src/core/lib/security/transport/secure_endpoint.h
@@ -44,4 +44,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H */
diff --git a/src/core/lib/security/transport/security_connector.cc b/src/core/lib/security/transport/security_connector.cc
index 51844fb..b050be2 100644
--- a/src/core/lib/security/transport/security_connector.cc
+++ b/src/core/lib/security/transport/security_connector.cc
@@ -136,6 +136,39 @@
   }
 }
 
+int grpc_security_connector_cmp(grpc_security_connector *sc,
+                                grpc_security_connector *other) {
+  if (sc == NULL || other == NULL) return GPR_ICMP(sc, other);
+  int c = GPR_ICMP(sc->vtable, other->vtable);
+  if (c != 0) return c;
+  return sc->vtable->cmp(sc, other);
+}
+
+int grpc_channel_security_connector_cmp(grpc_channel_security_connector *sc1,
+                                        grpc_channel_security_connector *sc2) {
+  GPR_ASSERT(sc1->channel_creds != NULL);
+  GPR_ASSERT(sc2->channel_creds != NULL);
+  int c = GPR_ICMP(sc1->channel_creds, sc2->channel_creds);
+  if (c != 0) return c;
+  c = GPR_ICMP(sc1->request_metadata_creds, sc2->request_metadata_creds);
+  if (c != 0) return c;
+  c = GPR_ICMP((void *)sc1->check_call_host, (void *)sc2->check_call_host);
+  if (c != 0) return c;
+  c = GPR_ICMP((void *)sc1->cancel_check_call_host,
+               (void *)sc2->cancel_check_call_host);
+  if (c != 0) return c;
+  return GPR_ICMP((void *)sc1->add_handshakers, (void *)sc2->add_handshakers);
+}
+
+int grpc_server_security_connector_cmp(grpc_server_security_connector *sc1,
+                                       grpc_server_security_connector *sc2) {
+  GPR_ASSERT(sc1->server_creds != NULL);
+  GPR_ASSERT(sc2->server_creds != NULL);
+  int c = GPR_ICMP(sc1->server_creds, sc2->server_creds);
+  if (c != 0) return c;
+  return GPR_ICMP((void *)sc1->add_handshakers, (void *)sc2->add_handshakers);
+}
+
 bool grpc_channel_security_connector_check_call_host(
     grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
     const char *host, grpc_auth_context *auth_context,
@@ -199,25 +232,27 @@
   if (gpr_unref(&sc->refcount)) sc->vtable->destroy(exec_ctx, sc);
 }
 
-static void connector_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) {
+static void connector_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) {
   GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, (grpc_security_connector *)p,
-                                "connector_pointer_arg_destroy");
+                                "connector_arg_destroy");
 }
 
-static void *connector_pointer_arg_copy(void *p) {
+static void *connector_arg_copy(void *p) {
   return GRPC_SECURITY_CONNECTOR_REF((grpc_security_connector *)p,
-                                     "connector_pointer_arg_copy");
+                                     "connector_arg_copy");
 }
 
-static int connector_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
+static int connector_cmp(void *a, void *b) {
+  return grpc_security_connector_cmp((grpc_security_connector *)a,
+                                     (grpc_security_connector *)b);
+}
 
-static const grpc_arg_pointer_vtable connector_pointer_vtable = {
-    connector_pointer_arg_copy, connector_pointer_arg_destroy,
-    connector_pointer_cmp};
+static const grpc_arg_pointer_vtable connector_arg_vtable = {
+    connector_arg_copy, connector_arg_destroy, connector_cmp};
 
 grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) {
   return grpc_channel_arg_pointer_create((char *)GRPC_ARG_SECURITY_CONNECTOR,
-                                         sc, &connector_pointer_vtable);
+                                         sc, &connector_arg_vtable);
 }
 
 grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) {
@@ -382,6 +417,32 @@
   fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked);
 }
 
+static int fake_channel_cmp(grpc_security_connector *sc1,
+                            grpc_security_connector *sc2) {
+  grpc_fake_channel_security_connector *c1 =
+      (grpc_fake_channel_security_connector *)sc1;
+  grpc_fake_channel_security_connector *c2 =
+      (grpc_fake_channel_security_connector *)sc2;
+  int c = grpc_channel_security_connector_cmp(&c1->base, &c2->base);
+  if (c != 0) return c;
+  c = strcmp(c1->target, c2->target);
+  if (c != 0) return c;
+  if (c1->expected_targets == NULL || c2->expected_targets == NULL) {
+    c = GPR_ICMP(c1->expected_targets, c2->expected_targets);
+  } else {
+    c = strcmp(c1->expected_targets, c2->expected_targets);
+  }
+  if (c != 0) return c;
+  return GPR_ICMP(c1->is_lb_channel, c2->is_lb_channel);
+}
+
+static int fake_server_cmp(grpc_security_connector *sc1,
+                           grpc_security_connector *sc2) {
+  return grpc_server_security_connector_cmp(
+      (grpc_server_security_connector *)sc1,
+      (grpc_server_security_connector *)sc2);
+}
+
 static bool fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
                                          grpc_channel_security_connector *sc,
                                          const char *host,
@@ -418,12 +479,13 @@
 }
 
 static grpc_security_connector_vtable fake_channel_vtable = {
-    fake_channel_destroy, fake_channel_check_peer};
+    fake_channel_destroy, fake_channel_check_peer, fake_channel_cmp};
 
 static grpc_security_connector_vtable fake_server_vtable = {
-    fake_server_destroy, fake_server_check_peer};
+    fake_server_destroy, fake_server_check_peer, fake_server_cmp};
 
 grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
+    grpc_channel_credentials *channel_creds,
     grpc_call_credentials *request_metadata_creds, const char *target,
     const grpc_channel_args *args) {
   grpc_fake_channel_security_connector *c =
@@ -431,6 +493,7 @@
   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.channel_creds = channel_creds;
   c->base.request_metadata_creds =
       grpc_call_credentials_ref(request_metadata_creds);
   c->base.check_call_host = fake_channel_check_call_host;
@@ -444,13 +507,14 @@
 }
 
 grpc_server_security_connector *grpc_fake_server_security_connector_create(
-    void) {
+    grpc_server_credentials *server_creds) {
   grpc_server_security_connector *c =
       (grpc_server_security_connector *)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;
+  c->server_creds = server_creds;
   c->add_handshakers = fake_server_add_handshakers;
   return c;
 }
@@ -473,6 +537,7 @@
                                 grpc_security_connector *sc) {
   grpc_ssl_channel_security_connector *c =
       (grpc_ssl_channel_security_connector *)sc;
+  grpc_channel_credentials_unref(exec_ctx, c->base.channel_creds);
   grpc_call_credentials_unref(exec_ctx, c->base.request_metadata_creds);
   tsi_ssl_client_handshaker_factory_unref(c->client_handshaker_factory);
   c->client_handshaker_factory = NULL;
@@ -485,6 +550,7 @@
                                grpc_security_connector *sc) {
   grpc_ssl_server_security_connector *c =
       (grpc_ssl_server_security_connector *)sc;
+  grpc_server_credentials_unref(exec_ctx, c->base.server_creds);
   tsi_ssl_server_handshaker_factory_unref(c->server_handshaker_factory);
   c->server_handshaker_factory = NULL;
   gpr_free(sc);
@@ -641,6 +707,29 @@
   GRPC_CLOSURE_SCHED(exec_ctx, on_peer_checked, error);
 }
 
+static int ssl_channel_cmp(grpc_security_connector *sc1,
+                           grpc_security_connector *sc2) {
+  grpc_ssl_channel_security_connector *c1 =
+      (grpc_ssl_channel_security_connector *)sc1;
+  grpc_ssl_channel_security_connector *c2 =
+      (grpc_ssl_channel_security_connector *)sc2;
+  int c = grpc_channel_security_connector_cmp(&c1->base, &c2->base);
+  if (c != 0) return c;
+  c = strcmp(c1->target_name, c2->target_name);
+  if (c != 0) return c;
+  return (c1->overridden_target_name == NULL ||
+          c2->overridden_target_name == NULL)
+             ? GPR_ICMP(c1->overridden_target_name, c2->overridden_target_name)
+             : strcmp(c1->overridden_target_name, c2->overridden_target_name);
+}
+
+static int ssl_server_cmp(grpc_security_connector *sc1,
+                          grpc_security_connector *sc2) {
+  return grpc_server_security_connector_cmp(
+      (grpc_server_security_connector *)sc1,
+      (grpc_server_security_connector *)sc2);
+}
+
 static void add_shallow_auth_property_to_peer(tsi_peer *peer,
                                               const grpc_auth_property *prop,
                                               const char *tsi_prop_name) {
@@ -717,10 +806,10 @@
 }
 
 static grpc_security_connector_vtable ssl_channel_vtable = {
-    ssl_channel_destroy, ssl_channel_check_peer};
+    ssl_channel_destroy, ssl_channel_check_peer, ssl_channel_cmp};
 
 static grpc_security_connector_vtable ssl_server_vtable = {
-    ssl_server_destroy, ssl_server_check_peer};
+    ssl_server_destroy, ssl_server_check_peer, ssl_server_cmp};
 
 /* returns a NULL terminated slice. */
 static grpc_slice compute_default_pem_root_certs_once(void) {
@@ -804,7 +893,8 @@
 }
 
 grpc_security_status grpc_ssl_channel_security_connector_create(
-    grpc_exec_ctx *exec_ctx, grpc_call_credentials *request_metadata_creds,
+    grpc_exec_ctx *exec_ctx, grpc_channel_credentials *channel_creds,
+    grpc_call_credentials *request_metadata_creds,
     const grpc_ssl_config *config, const char *target_name,
     const char *overridden_target_name, grpc_channel_security_connector **sc) {
   size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
@@ -840,6 +930,7 @@
   gpr_ref_init(&c->base.base.refcount, 1);
   c->base.base.vtable = &ssl_channel_vtable;
   c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
+  c->base.channel_creds = grpc_channel_credentials_ref(channel_creds);
   c->base.request_metadata_creds =
       grpc_call_credentials_ref(request_metadata_creds);
   c->base.check_call_host = ssl_channel_check_call_host;
@@ -851,10 +942,11 @@
     c->overridden_target_name = gpr_strdup(overridden_target_name);
   }
 
-  has_key_cert_pair = config->pem_key_cert_pair.private_key != NULL &&
-                      config->pem_key_cert_pair.cert_chain != NULL;
+  has_key_cert_pair = config->pem_key_cert_pair != NULL &&
+                      config->pem_key_cert_pair->private_key != NULL &&
+                      config->pem_key_cert_pair->cert_chain != NULL;
   result = tsi_create_ssl_client_handshaker_factory(
-      has_key_cert_pair ? &config->pem_key_cert_pair : NULL, pem_root_certs,
+      has_key_cert_pair ? config->pem_key_cert_pair : NULL, pem_root_certs,
       ssl_cipher_suites(), alpn_protocol_strings, (uint16_t)num_alpn_protocols,
       &c->client_handshaker_factory);
   if (result != TSI_OK) {
@@ -874,8 +966,8 @@
 }
 
 grpc_security_status grpc_ssl_server_security_connector_create(
-    grpc_exec_ctx *exec_ctx, const grpc_ssl_server_config *config,
-    grpc_server_security_connector **sc) {
+    grpc_exec_ctx *exec_ctx, grpc_server_credentials *server_creds,
+    const grpc_ssl_server_config *config, grpc_server_security_connector **sc) {
   size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
   const char **alpn_protocol_strings =
       (const char **)gpr_malloc(sizeof(const char *) * num_alpn_protocols);
@@ -897,6 +989,7 @@
   gpr_ref_init(&c->base.base.refcount, 1);
   c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
   c->base.base.vtable = &ssl_server_vtable;
+  c->base.server_creds = grpc_server_credentials_ref(server_creds);
   result = tsi_create_ssl_server_handshaker_factory_ex(
       config->pem_key_cert_pairs, config->num_key_cert_pairs,
       config->pem_root_certs, get_tsi_client_certificate_request_type(
diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h
index 4d87cd0..8287151 100644
--- a/src/core/lib/security/transport/security_connector.h
+++ b/src/core/lib/security/transport/security_connector.h
@@ -60,13 +60,9 @@
   void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
                      tsi_peer peer, grpc_auth_context **auth_context,
                      grpc_closure *on_peer_checked);
+  int (*cmp)(grpc_security_connector *sc, grpc_security_connector *other);
 } grpc_security_connector_vtable;
 
-typedef struct grpc_security_connector_handshake_list {
-  void *handshake;
-  struct grpc_security_connector_handshake_list *next;
-} grpc_security_connector_handshake_list;
-
 struct grpc_security_connector {
   const grpc_security_connector_vtable *vtable;
   gpr_refcount refcount;
@@ -104,6 +100,10 @@
                                         grpc_auth_context **auth_context,
                                         grpc_closure *on_peer_checked);
 
+/* Compares two security connectors. */
+int grpc_security_connector_cmp(grpc_security_connector *sc,
+                                grpc_security_connector *other);
+
 /* Util to encapsulate the connector in a channel arg. */
 grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc);
 
@@ -116,13 +116,14 @@
 
 /* --- channel_security_connector object. ---
 
-    A channel security connector object represents away to configure the
+    A channel security connector object represents a way to configure the
     underlying transport security mechanism on the client side.  */
 
 typedef struct grpc_channel_security_connector grpc_channel_security_connector;
 
 struct grpc_channel_security_connector {
   grpc_security_connector base;
+  grpc_channel_credentials *channel_creds;
   grpc_call_credentials *request_metadata_creds;
   bool (*check_call_host)(grpc_exec_ctx *exec_ctx,
                           grpc_channel_security_connector *sc, const char *host,
@@ -138,6 +139,10 @@
                           grpc_handshake_manager *handshake_mgr);
 };
 
+/// A helper function for use in grpc_security_connector_cmp() implementations.
+int grpc_channel_security_connector_cmp(grpc_channel_security_connector *sc1,
+                                        grpc_channel_security_connector *sc2);
+
 /// Checks that the host that will be set for a call is acceptable.
 /// Returns true if completed synchronously, in which case \a error will
 /// be set to indicate the result.  Otherwise, \a on_call_host_checked
@@ -161,18 +166,23 @@
 
 /* --- server_security_connector object. ---
 
-    A server security connector object represents away to configure the
+    A server security connector object represents a way to configure the
     underlying transport security mechanism on the server side.  */
 
 typedef struct grpc_server_security_connector grpc_server_security_connector;
 
 struct grpc_server_security_connector {
   grpc_security_connector base;
+  grpc_server_credentials *server_creds;
   void (*add_handshakers)(grpc_exec_ctx *exec_ctx,
                           grpc_server_security_connector *sc,
                           grpc_handshake_manager *handshake_mgr);
 };
 
+/// A helper function for use in grpc_security_connector_cmp() implementations.
+int grpc_server_security_connector_cmp(grpc_server_security_connector *sc1,
+                                       grpc_server_security_connector *sc2);
+
 void grpc_server_security_connector_add_handshakers(
     grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
     grpc_handshake_manager *handshake_mgr);
@@ -182,18 +192,19 @@
 /* For TESTING ONLY!
    Creates a fake connector that emulates real channel security.  */
 grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
+    grpc_channel_credentials *channel_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.  */
 grpc_server_security_connector *grpc_fake_server_security_connector_create(
-    void);
+    grpc_server_credentials *server_creds);
 
 /* Config for ssl clients. */
 
 typedef struct {
-  tsi_ssl_pem_key_cert_pair pem_key_cert_pair;
+  tsi_ssl_pem_key_cert_pair *pem_key_cert_pair;
   char *pem_root_certs;
 } grpc_ssl_config;
 
@@ -211,7 +222,8 @@
   specific error code otherwise.
 */
 grpc_security_status grpc_ssl_channel_security_connector_create(
-    grpc_exec_ctx *exec_ctx, grpc_call_credentials *request_metadata_creds,
+    grpc_exec_ctx *exec_ctx, grpc_channel_credentials *channel_creds,
+    grpc_call_credentials *request_metadata_creds,
     const grpc_ssl_config *config, const char *target_name,
     const char *overridden_target_name, grpc_channel_security_connector **sc);
 
@@ -236,8 +248,8 @@
   specific error code otherwise.
 */
 grpc_security_status grpc_ssl_server_security_connector_create(
-    grpc_exec_ctx *exec_ctx, const grpc_ssl_server_config *config,
-    grpc_server_security_connector **sc);
+    grpc_exec_ctx *exec_ctx, grpc_server_credentials *server_creds,
+    const grpc_ssl_server_config *config, grpc_server_security_connector **sc);
 
 /* Util. */
 const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
diff --git a/src/core/lib/security/transport/security_handshaker.h b/src/core/lib/security/transport/security_handshaker.h
index 345065f..178099b 100644
--- a/src/core/lib/security/transport/security_handshaker.h
+++ b/src/core/lib/security/transport/security_handshaker.h
@@ -39,4 +39,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H */
diff --git a/src/core/lib/security/transport/tsi_error.h b/src/core/lib/security/transport/tsi_error.h
index 4c78b06..4e19daf 100644
--- a/src/core/lib/security/transport/tsi_error.h
+++ b/src/core/lib/security/transport/tsi_error.h
@@ -32,4 +32,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H */
diff --git a/src/core/lib/security/util/json_util.h b/src/core/lib/security/util/json_util.h
index 43a2f6b..cdd8a71 100644
--- a/src/core/lib/security/util/json_util.h
+++ b/src/core/lib/security/util/json_util.h
@@ -45,4 +45,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H */
diff --git a/src/core/lib/slice/b64.h b/src/core/lib/slice/b64.h
index c01da56..9b4dc65 100644
--- a/src/core/lib/slice/b64.h
+++ b/src/core/lib/slice/b64.h
@@ -55,4 +55,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SLICE_B64_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SLICE_B64_H */
diff --git a/src/core/lib/slice/percent_encoding.h b/src/core/lib/slice/percent_encoding.h
index e6f8512..14a4deb 100644
--- a/src/core/lib/slice/percent_encoding.h
+++ b/src/core/lib/slice/percent_encoding.h
@@ -68,4 +68,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SLICE_PERCENT_ENCODING_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SLICE_PERCENT_ENCODING_H */
diff --git a/src/core/lib/slice/slice_hash_table.h b/src/core/lib/slice/slice_hash_table.h
index 3c3f0e6..41250df 100644
--- a/src/core/lib/slice/slice_hash_table.h
+++ b/src/core/lib/slice/slice_hash_table.h
@@ -75,4 +75,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SLICE_SLICE_HASH_TABLE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SLICE_SLICE_HASH_TABLE_H */
diff --git a/src/core/lib/slice/slice_internal.h b/src/core/lib/slice/slice_internal.h
index 8591185..fcf70a0 100644
--- a/src/core/lib/slice/slice_internal.h
+++ b/src/core/lib/slice/slice_internal.h
@@ -54,4 +54,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H */
diff --git a/src/core/lib/slice/slice_traits.h b/src/core/lib/slice/slice_traits.h
index 1eda17c..7fdb675 100644
--- a/src/core/lib/slice/slice_traits.h
+++ b/src/core/lib/slice/slice_traits.h
@@ -34,4 +34,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SLICE_SLICE_TRAITS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SLICE_SLICE_TRAITS_H */
diff --git a/src/core/lib/support/env_windows.cc b/src/core/lib/support/env_windows.cc
index 73c643c..c5a25dc 100644
--- a/src/core/lib/support/env_windows.cc
+++ b/src/core/lib/support/env_windows.cc
@@ -43,7 +43,10 @@
   DWORD ret;
 
   ret = GetEnvironmentVariable(tname, NULL, 0);
-  if (ret == 0) return NULL;
+  if (ret == 0) {
+    gpr_free(tname);
+    return NULL;
+  }
   size = ret * (DWORD)sizeof(TCHAR);
   tresult = (LPTSTR)gpr_malloc(size);
   ret = GetEnvironmentVariable(tname, tresult, size);
diff --git a/src/core/lib/support/manual_constructor.h b/src/core/lib/support/manual_constructor.h
new file mode 100644
index 0000000..d753cf9
--- /dev/null
+++ b/src/core/lib/support/manual_constructor.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SUPPORT_MANUAL_CONSTRUCTOR_H
+#define GRPC_CORE_LIB_SUPPORT_MANUAL_CONSTRUCTOR_H
+
+// manually construct a region of memory with some type
+
+#include <stddef.h>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+namespace grpc_core {
+
+template <typename Type>
+class ManualConstructor {
+ public:
+  // No constructor or destructor because one of the most useful uses of
+  // this class is as part of a union, and members of a union could not have
+  // constructors or destructors till C++11.  And, anyway, the whole point of
+  // this class is to bypass constructor and destructor.
+
+  Type* get() { return reinterpret_cast<Type*>(&space_); }
+  const Type* get() const { return reinterpret_cast<const Type*>(&space_); }
+
+  Type* operator->() { return get(); }
+  const Type* operator->() const { return get(); }
+
+  Type& operator*() { return *get(); }
+  const Type& operator*() const { return *get(); }
+
+  void Init() { new (&space_) Type; }
+
+  // Init() constructs the Type instance using the given arguments
+  // (which are forwarded to Type's constructor).
+  //
+  // Note that Init() with no arguments performs default-initialization,
+  // not zero-initialization (i.e it behaves the same as "new Type;", not
+  // "new Type();"), so it will leave non-class types uninitialized.
+  template <typename... Ts>
+  void Init(Ts&&... args) {
+    new (&space_) Type(std::forward<Ts>(args)...);
+  }
+
+  // Init() that is equivalent to copy and move construction.
+  // Enables usage like this:
+  //   ManualConstructor<std::vector<int>> v;
+  //   v.Init({1, 2, 3});
+  void Init(const Type& x) { new (&space_) Type(x); }
+  void Init(Type&& x) { new (&space_) Type(std::move(x)); }
+
+  void Destroy() { get()->~Type(); }
+
+ private:
+  typename std::aligned_storage<sizeof(Type), alignof(Type)>::type space_;
+};
+
+}  // namespace grpc_core
+
+#endif
diff --git a/src/core/lib/support/memory.h b/src/core/lib/support/memory.h
index dc3d32e..6b33668 100644
--- a/src/core/lib/support/memory.h
+++ b/src/core/lib/support/memory.h
@@ -21,6 +21,7 @@
 
 #include <grpc/support/alloc.h>
 
+#include <limits>
 #include <memory>
 #include <utility>
 
@@ -54,6 +55,46 @@
   return UniquePtr<T>(New<T>(std::forward<Args>(args)...));
 }
 
+// an allocator that uses gpr_malloc/gpr_free
+template <class T>
+class Allocator {
+ public:
+  typedef T value_type;
+  typedef T* pointer;
+  typedef const T* const_pointer;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef std::size_t size_type;
+  typedef std::ptrdiff_t difference_type;
+  typedef std::false_type propagate_on_container_move_assignment;
+  template <class U>
+  struct rebind {
+    typedef Allocator<U> other;
+  };
+  typedef std::true_type is_always_equal;
+
+  pointer address(reference x) const { return &x; }
+  const_pointer address(const_reference x) const { return &x; }
+  pointer allocate(std::size_t n,
+                   std::allocator<void>::const_pointer hint = 0) {
+    return static_cast<pointer>(gpr_malloc(n * sizeof(T)));
+  }
+  void deallocate(T* p, std::size_t n) { gpr_free(p); }
+  size_t max_size() const {
+    return std::numeric_limits<size_type>::max() / sizeof(value_type);
+  }
+  void construct(pointer p, const_reference val) { new ((void*)p) T(val); }
+  template <class U, class... Args>
+  void construct(U* p, Args&&... args) {
+    ::new ((void*)p) U(std::forward<Args>(args)...);
+  }
+  void destroy(pointer p) { p->~T(); }
+  template <class U>
+  void destroy(U* p) {
+    p->~U();
+  }
+};
+
 }  // namespace grpc_core
 
 #endif /* GRPC_CORE_LIB_SUPPORT_MEMORY_H */
diff --git a/src/core/lib/support/time_posix.cc b/src/core/lib/support/time_posix.cc
index 3267ea6..3f8a909 100644
--- a/src/core/lib/support/time_posix.cc
+++ b/src/core/lib/support/time_posix.cc
@@ -42,7 +42,7 @@
   return rv;
 }
 
-#if _POSIX_TIMERS > 0
+#if _POSIX_TIMERS > 0 || defined(__OpenBSD__)
 static gpr_timespec gpr_from_timespec(struct timespec ts,
                                       gpr_clock_type clock_type) {
   /*
diff --git a/src/core/lib/support/vector.h b/src/core/lib/support/vector.h
new file mode 100644
index 0000000..4a7db80
--- /dev/null
+++ b/src/core/lib/support/vector.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SUPPORT_VECTOR_H
+#define GRPC_CORE_LIB_SUPPORT_VECTOR_H
+
+#include "absl/container/inlined_vector.h"
+#include "src/core/lib/support/memory.h"
+
+namespace grpc_core {
+
+template <typename T, size_t N>
+using InlinedVector = absl::InlinedVector<T, N, Allocator<T>>;
+
+}  // namespace grpc_core
+
+#endif
diff --git a/src/core/lib/surface/channel_stack_type.h b/src/core/lib/surface/channel_stack_type.h
index 903b90a..c778487 100644
--- a/src/core/lib/surface/channel_stack_type.h
+++ b/src/core/lib/surface/channel_stack_type.h
@@ -50,4 +50,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_STACK_TYPE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_STACK_TYPE_H */
diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc
index 36b4b83..21664f0 100644
--- a/src/core/lib/surface/completion_queue.cc
+++ b/src/core/lib/surface/completion_queue.cc
@@ -362,11 +362,24 @@
 
 static grpc_cq_completion *cq_event_queue_pop(grpc_cq_event_queue *q) {
   grpc_cq_completion *c = NULL;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
   if (gpr_spinlock_trylock(&q->queue_lock)) {
-    c = (grpc_cq_completion *)gpr_mpscq_pop(&q->queue);
+    GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_SUCCESSES(&exec_ctx);
+
+    bool is_empty = false;
+    c = (grpc_cq_completion *)gpr_mpscq_pop_and_check_end(&q->queue, &is_empty);
     gpr_spinlock_unlock(&q->queue_lock);
+
+    if (c == NULL && !is_empty) {
+      GRPC_STATS_INC_CQ_EV_QUEUE_TRANSIENT_POP_FAILURES(&exec_ctx);
+    }
+  } else {
+    GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_FAILURES(&exec_ctx);
   }
 
+  grpc_exec_ctx_finish(&exec_ctx);
+
   if (c) {
     gpr_atm_no_barrier_fetch_add(&q->num_queue_items, -1);
   }
diff --git a/src/core/lib/surface/completion_queue_factory.h b/src/core/lib/surface/completion_queue_factory.h
index cb0af6f..af8f3d6 100644
--- a/src/core/lib/surface/completion_queue_factory.h
+++ b/src/core/lib/surface/completion_queue_factory.h
@@ -41,4 +41,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H */
diff --git a/src/core/lib/surface/event_string.h b/src/core/lib/surface/event_string.h
index 127609c..2d53cf0 100644
--- a/src/core/lib/surface/event_string.h
+++ b/src/core/lib/surface/event_string.h
@@ -32,4 +32,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SURFACE_EVENT_STRING_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SURFACE_EVENT_STRING_H */
diff --git a/src/core/lib/surface/init.h b/src/core/lib/surface/init.h
index b2f4857..d429026 100644
--- a/src/core/lib/surface/init.h
+++ b/src/core/lib/surface/init.h
@@ -32,4 +32,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SURFACE_INIT_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SURFACE_INIT_H */
diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h
index 1114715..375eab4 100644
--- a/src/core/lib/surface/server.h
+++ b/src/core/lib/surface/server.h
@@ -62,4 +62,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SURFACE_SERVER_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SURFACE_SERVER_H */
diff --git a/src/core/lib/surface/validate_metadata.h b/src/core/lib/surface/validate_metadata.h
index aa02419..afc8be6 100644
--- a/src/core/lib/surface/validate_metadata.h
+++ b/src/core/lib/surface/validate_metadata.h
@@ -33,4 +33,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_SURFACE_VALIDATE_METADATA_H */
diff --git a/src/core/lib/transport/bdp_estimator.cc b/src/core/lib/transport/bdp_estimator.cc
index 6ed427c..f159701 100644
--- a/src/core/lib/transport/bdp_estimator.cc
+++ b/src/core/lib/transport/bdp_estimator.cc
@@ -21,117 +21,64 @@
 #include <inttypes.h>
 #include <stdlib.h>
 
-#include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
 grpc_tracer_flag grpc_bdp_estimator_trace =
     GRPC_TRACER_INITIALIZER(false, "bdp_estimator");
 
-void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name) {
-  estimator->estimate = 65536;
-  estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED;
-  estimator->ping_start_time = gpr_time_0(GPR_CLOCK_MONOTONIC);
-  estimator->next_ping_scheduled = 0;
-  estimator->name = name;
-  estimator->bw_est = 0;
-  estimator->inter_ping_delay = 100.0;  // start at 100ms
-  estimator->stable_estimate_count = 0;
-}
+namespace grpc_core {
 
-bool grpc_bdp_estimator_get_estimate(const grpc_bdp_estimator *estimator,
-                                     int64_t *estimate) {
-  *estimate = estimator->estimate;
-  return true;
-}
+BdpEstimator::BdpEstimator(const char *name)
+    : ping_state_(PingState::UNSCHEDULED),
+      accumulator_(0),
+      estimate_(65536),
+      ping_start_time_(gpr_time_0(GPR_CLOCK_MONOTONIC)),
+      inter_ping_delay_(100.0),  // start at 100ms
+      stable_estimate_count_(0),
+      bw_est_(0),
+      name_(name) {}
 
-bool grpc_bdp_estimator_get_bw(const grpc_bdp_estimator *estimator,
-                               double *bw) {
-  *bw = estimator->bw_est;
-  return true;
-}
-
-void grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
-                                           int64_t num_bytes) {
-  estimator->accumulator += num_bytes;
-}
-
-bool grpc_bdp_estimator_need_ping(grpc_exec_ctx *exec_ctx,
-                                  const grpc_bdp_estimator *estimator) {
-  switch (estimator->ping_state) {
-    case GRPC_BDP_PING_UNSCHEDULED:
-      return grpc_exec_ctx_now(exec_ctx) >= estimator->next_ping_scheduled;
-    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_TRACER_ON(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_TRACER_ON(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;
-  estimator->ping_start_time = gpr_now(GPR_CLOCK_MONOTONIC);
-}
-
-void grpc_bdp_estimator_complete_ping(grpc_exec_ctx *exec_ctx,
-                                      grpc_bdp_estimator *estimator) {
+grpc_millis BdpEstimator::CompletePing(grpc_exec_ctx *exec_ctx) {
   gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
-  gpr_timespec dt_ts = gpr_time_sub(now, estimator->ping_start_time);
+  gpr_timespec dt_ts = gpr_time_sub(now, ping_start_time_);
   double dt = (double)dt_ts.tv_sec + 1e-9 * (double)dt_ts.tv_nsec;
-  double bw = dt > 0 ? ((double)estimator->accumulator / dt) : 0;
-  int start_inter_ping_delay = estimator->inter_ping_delay;
+  double bw = dt > 0 ? ((double)accumulator_ / dt) : 0;
+  int start_inter_ping_delay = inter_ping_delay_;
   if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
     gpr_log(GPR_DEBUG, "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64
                        " dt=%lf bw=%lfMbs bw_est=%lfMbs",
-            estimator->name, estimator->accumulator, estimator->estimate, dt,
-            bw / 125000.0, estimator->bw_est / 125000.0);
+            name_, accumulator_, estimate_, dt, bw / 125000.0,
+            bw_est_ / 125000.0);
   }
-  GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_STARTED);
-  if (estimator->accumulator > 2 * estimator->estimate / 3 &&
-      bw > estimator->bw_est) {
-    estimator->estimate =
-        GPR_MAX(estimator->accumulator, estimator->estimate * 2);
-    estimator->bw_est = bw;
+  GPR_ASSERT(ping_state_ == PingState::STARTED);
+  if (accumulator_ > 2 * estimate_ / 3 && bw > bw_est_) {
+    estimate_ = GPR_MAX(accumulator_, estimate_ * 2);
+    bw_est_ = bw;
     if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
-      gpr_log(GPR_DEBUG, "bdp[%s]: estimate increased to %" PRId64,
-              estimator->name, estimator->estimate);
+      gpr_log(GPR_DEBUG, "bdp[%s]: estimate increased to %" PRId64, name_,
+              estimate_);
     }
-    estimator->inter_ping_delay /= 2;  // if the ping estimate changes,
-                                       // exponentially get faster at probing
-  } else if (estimator->inter_ping_delay < 10000) {
-    estimator->stable_estimate_count++;
-    if (estimator->stable_estimate_count >= 2) {
-      estimator->inter_ping_delay +=
+    inter_ping_delay_ /= 2;  // if the ping estimate changes,
+                             // exponentially get faster at probing
+  } else if (inter_ping_delay_ < 10000) {
+    stable_estimate_count_++;
+    if (stable_estimate_count_ >= 2) {
+      inter_ping_delay_ +=
           100 +
           (int)(rand() * 100.0 / RAND_MAX);  // if the ping estimate is steady,
                                              // slowly ramp down the probe time
     }
   }
-  if (start_inter_ping_delay != estimator->inter_ping_delay) {
-    estimator->stable_estimate_count = 0;
+  if (start_inter_ping_delay != inter_ping_delay_) {
+    stable_estimate_count_ = 0;
     if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
-      gpr_log(GPR_DEBUG, "bdp[%s]:update_inter_time to %dms", estimator->name,
-              estimator->inter_ping_delay);
+      gpr_log(GPR_DEBUG, "bdp[%s]:update_inter_time to %dms", name_,
+              inter_ping_delay_);
     }
   }
-  estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED;
-  estimator->accumulator = 0;
-  estimator->next_ping_scheduled =
-      grpc_exec_ctx_now(exec_ctx) + estimator->inter_ping_delay;
+  ping_state_ = PingState::UNSCHEDULED;
+  accumulator_ = 0;
+  return grpc_exec_ctx_now(exec_ctx) + inter_ping_delay_;
 }
+
+}  // namespace grpc_core
diff --git a/src/core/lib/transport/bdp_estimator.h b/src/core/lib/transport/bdp_estimator.h
index 480d523..750da39 100644
--- a/src/core/lib/transport/bdp_estimator.h
+++ b/src/core/lib/transport/bdp_estimator.h
@@ -19,67 +19,76 @@
 #ifndef GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H
 #define GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H
 
-#include <grpc/support/time.h>
+#include <grpc/support/port_platform.h>
+
+#include <inttypes.h>
 #include <stdbool.h>
 #include <stdint.h>
+
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 
-#define GRPC_BDP_SAMPLES 16
-#define GRPC_BDP_MIN_SAMPLES_FOR_ESTIMATE 3
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern grpc_tracer_flag grpc_bdp_estimator_trace;
 
-typedef enum {
-  GRPC_BDP_PING_UNSCHEDULED,
-  GRPC_BDP_PING_SCHEDULED,
-  GRPC_BDP_PING_STARTED
-} grpc_bdp_estimator_ping_state;
+namespace grpc_core {
 
-typedef struct grpc_bdp_estimator {
-  grpc_bdp_estimator_ping_state ping_state;
-  int64_t accumulator;
-  int64_t estimate;
+class BdpEstimator {
+ public:
+  explicit BdpEstimator(const char *name);
+  ~BdpEstimator() {}
+
+  int64_t EstimateBdp() const { return estimate_; }
+  double EstimateBandwidth() const { return bw_est_; }
+
+  void AddIncomingBytes(int64_t num_bytes) { accumulator_ += 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 SchedulePing() {
+    if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
+      gpr_log(GPR_DEBUG, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, name_,
+              accumulator_, estimate_);
+    }
+    GPR_ASSERT(ping_state_ == PingState::UNSCHEDULED);
+    ping_state_ = PingState::SCHEDULED;
+    accumulator_ = 0;
+  }
+
+  // Start a ping: call after calling grpc_bdp_estimator_schedule_ping and
+  // once
+  // the ping is on the wire
+  void StartPing() {
+    if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
+      gpr_log(GPR_DEBUG, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, name_,
+              accumulator_, estimate_);
+    }
+    GPR_ASSERT(ping_state_ == PingState::SCHEDULED);
+    ping_state_ = PingState::STARTED;
+    accumulator_ = 0;
+    ping_start_time_ = gpr_now(GPR_CLOCK_MONOTONIC);
+  }
+
+  // Completes a previously started ping, returns when to schedule the next one
+  grpc_millis CompletePing(grpc_exec_ctx *exec_ctx);
+
+ private:
+  enum class PingState { UNSCHEDULED, SCHEDULED, STARTED };
+
+  PingState ping_state_;
+  int64_t accumulator_;
+  int64_t estimate_;
   // when was the current ping started?
-  gpr_timespec ping_start_time;
-  // when should the next ping start?
-  grpc_millis next_ping_scheduled;
-  int inter_ping_delay;
-  int stable_estimate_count;
-  double bw_est;
-  const char *name;
-} grpc_bdp_estimator;
+  gpr_timespec ping_start_time_;
+  int inter_ping_delay_;
+  int stable_estimate_count_;
+  double bw_est_;
+  const char *name_;
+};
 
-void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name);
+}  // namespace grpc_core
 
-// Returns true if a reasonable estimate could be obtained
-bool grpc_bdp_estimator_get_estimate(const grpc_bdp_estimator *estimator,
-                                     int64_t *estimate);
-// Tracks new bytes read.
-bool grpc_bdp_estimator_get_bw(const grpc_bdp_estimator *estimator, double *bw);
-// Returns true if the user should schedule a ping
-void grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
-                                           int64_t num_bytes);
-// Returns true if the user should schedule a ping
-bool grpc_bdp_estimator_need_ping(grpc_exec_ctx *exec_ctx,
-                                  const grpc_bdp_estimator *estimator);
-// 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_exec_ctx *exec_ctx,
-                                      grpc_bdp_estimator *estimator);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H */
diff --git a/src/core/lib/transport/byte_stream.h b/src/core/lib/transport/byte_stream.h
index d3e04df..c1d8ee5 100644
--- a/src/core/lib/transport/byte_stream.h
+++ b/src/core/lib/transport/byte_stream.h
@@ -143,4 +143,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_TRANSPORT_BYTE_STREAM_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_BYTE_STREAM_H */
diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h
index 1796a54..c0ba188 100644
--- a/src/core/lib/transport/connectivity_state.h
+++ b/src/core/lib/transport/connectivity_state.h
@@ -92,4 +92,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H */
diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h
index 2c97f9f..b4f9df4 100644
--- a/src/core/lib/transport/error_utils.h
+++ b/src/core/lib/transport/error_utils.h
@@ -48,4 +48,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H */
diff --git a/src/core/lib/transport/metadata.cc b/src/core/lib/transport/metadata.cc
index 5455b24..2392f26 100644
--- a/src/core/lib/transport/metadata.cc
+++ b/src/core/lib/transport/metadata.cc
@@ -352,11 +352,14 @@
   return raw_length / 3 * 4 + tail_xtra[raw_length % 3];
 }
 
-size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem) {
+size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem,
+                                           bool use_true_binary_metadata) {
   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);
+    return overhead_and_key + (use_true_binary_metadata
+                                   ? value_len + 1
+                                   : get_base64_encoded_size(value_len));
   } else {
     return overhead_and_key + value_len;
   }
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index 9f82225..3f1032a 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -132,7 +132,8 @@
 
 bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b);
 
-size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem);
+size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem,
+                                           bool use_true_binary_metadata);
 
 /* Mutator and accessor for grpc_mdelem user data. The destructor function
    is used as a type tag and is checked during user_data fetch. */
diff --git a/src/core/lib/transport/pid_controller.cc b/src/core/lib/transport/pid_controller.cc
index 4b304f1..9f7750d 100644
--- a/src/core/lib/transport/pid_controller.cc
+++ b/src/core/lib/transport/pid_controller.cc
@@ -19,45 +19,30 @@
 #include "src/core/lib/transport/pid_controller.h"
 #include <grpc/support/useful.h>
 
-void grpc_pid_controller_init(grpc_pid_controller *pid_controller,
-                              grpc_pid_controller_args args) {
-  pid_controller->args = args;
-  pid_controller->last_control_value = args.initial_control_value;
-  grpc_pid_controller_reset(pid_controller);
-}
+namespace grpc_core {
 
-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;
-}
+PidController::PidController(const Args &args)
+    : last_control_value_(args.initial_control_value()), args_(args) {}
 
-double grpc_pid_controller_update(grpc_pid_controller *pid_controller,
-                                  double error, double dt) {
-  if (dt == 0) return pid_controller->last_control_value;
+double PidController::Update(double error, double dt) {
+  if (dt <= 0) return last_control_value_;
   /* 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;
+  error_integral_ += dt * (last_error_ + error) * 0.5;
+  error_integral_ = GPR_CLAMP(error_integral_, -args_.integral_range(),
+                              args_.integral_range());
+  double diff_error = (error - 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;
+  double dc_dt = args_.gain_p() * error + args_.gain_i() * error_integral_ +
+                 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;
-  pid_controller->last_dc_dt = dc_dt;
-  pid_controller->last_control_value = new_control_value;
+  double new_control_value =
+      last_control_value_ + dt * (last_dc_dt_ + dc_dt) * 0.5;
+  new_control_value = GPR_CLAMP(new_control_value, args_.min_control_value(),
+                                args_.max_control_value());
+  last_error_ = error;
+  last_dc_dt_ = dc_dt;
+  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;
-}
+}  // namespace grpc_core
diff --git a/src/core/lib/transport/pid_controller.h b/src/core/lib/transport/pid_controller.h
index 17feabf..87e59a1 100644
--- a/src/core/lib/transport/pid_controller.h
+++ b/src/core/lib/transport/pid_controller.h
@@ -19,9 +19,7 @@
 #ifndef GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H
 #define GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <limits>
 
 /* \file Simple PID controller.
    Implements a proportional-integral-derivative controller.
@@ -30,41 +28,87 @@
    Gains can be set to adjust sensitivity to current error (p), the integral
    of error (i), and the derivative of error (d). */
 
-typedef struct {
-  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;
+namespace grpc_core {
 
-typedef struct {
-  double last_error;
-  double error_integral;
-  double last_control_value;
-  double last_dc_dt;
-  grpc_pid_controller_args args;
-} grpc_pid_controller;
+class PidController {
+ public:
+  class Args {
+   public:
+    double gain_p() const { return gain_p_; }
+    double gain_i() const { return gain_i_; }
+    double gain_d() const { return gain_d_; }
+    double initial_control_value() const { return initial_control_value_; }
+    double min_control_value() const { return min_control_value_; }
+    double max_control_value() const { return max_control_value_; }
+    double integral_range() const { return integral_range_; }
 
-/** Initialize the controller */
-void grpc_pid_controller_init(grpc_pid_controller *pid_controller,
-                              grpc_pid_controller_args args);
+    Args& set_gain_p(double gain_p) {
+      gain_p_ = gain_p;
+      return *this;
+    }
+    Args& set_gain_i(double gain_i) {
+      gain_i_ = gain_i;
+      return *this;
+    }
+    Args& set_gain_d(double gain_d) {
+      gain_d_ = gain_d;
+      return *this;
+    }
+    Args& set_initial_control_value(double initial_control_value) {
+      initial_control_value_ = initial_control_value;
+      return *this;
+    }
+    Args& set_min_control_value(double min_control_value) {
+      min_control_value_ = min_control_value;
+      return *this;
+    }
+    Args& set_max_control_value(double max_control_value) {
+      max_control_value_ = max_control_value;
+      return *this;
+    }
+    Args& set_integral_range(double integral_range) {
+      integral_range_ = integral_range;
+      return *this;
+    }
 
-/** Reset the controller: useful when things have changed significantly */
-void grpc_pid_controller_reset(grpc_pid_controller *pid_controller);
+   private:
+    double gain_p_ = 0.0;
+    double gain_i_ = 0.0;
+    double gain_d_ = 0.0;
+    double initial_control_value_ = 0.0;
+    double min_control_value_ = std::numeric_limits<double>::min();
+    double max_control_value_ = std::numeric_limits<double>::max();
+    double integral_range_ = std::numeric_limits<double>::max();
+  };
 
-/** Update the controller: given a current error estimate, and the time since
-    the last update, returns a new control value */
-double grpc_pid_controller_update(grpc_pid_controller *pid_controller,
-                                  double error, double dt);
+  explicit PidController(const Args& args);
 
-/** Returns the last control value calculated */
-double grpc_pid_controller_last(grpc_pid_controller *pid_controller);
+  /// Reset the controller internal state: useful when the environment has
+  /// changed significantly
+  void Reset() {
+    last_error_ = 0.0;
+    last_dc_dt_ = 0.0;
+    error_integral_ = 0.0;
+  }
 
-#ifdef __cplusplus
-}
-#endif
+  /// Update the controller: given a current error estimate, and the time since
+  /// the last update, returns a new control value
+  double Update(double error, double dt);
 
-#endif /* GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H */
\ No newline at end of file
+  /// Returns the last control value calculated
+  double last_control_value() const { return last_control_value_; }
+
+  /// Returns the current error integral (mostly for testing)
+  double error_integral() const { return error_integral_; }
+
+ private:
+  double last_error_ = 0.0;
+  double error_integral_ = 0.0;
+  double last_control_value_;
+  double last_dc_dt_ = 0.0;
+  const Args args_;
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H */
diff --git a/src/core/lib/transport/service_config.h b/src/core/lib/transport/service_config.h
index c485f52..9c43093 100644
--- a/src/core/lib/transport/service_config.h
+++ b/src/core/lib/transport/service_config.h
@@ -67,4 +67,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */
diff --git a/src/core/lib/transport/status_conversion.h b/src/core/lib/transport/status_conversion.h
index fd58a82..8ef91ae 100644
--- a/src/core/lib/transport/status_conversion.h
+++ b/src/core/lib/transport/status_conversion.h
@@ -41,4 +41,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_STATUS_CONVERSION_H */
diff --git a/src/core/lib/transport/timeout_encoding.h b/src/core/lib/transport/timeout_encoding.h
index 25cb663..91cdf0f 100644
--- a/src/core/lib/transport/timeout_encoding.h
+++ b/src/core/lib/transport/timeout_encoding.h
@@ -40,4 +40,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H */
diff --git a/src/core/lib/transport/transport_impl.h b/src/core/lib/transport/transport_impl.h
index 41d34d3..445fb41 100644
--- a/src/core/lib/transport/transport_impl.h
+++ b/src/core/lib/transport/transport_impl.h
@@ -77,4 +77,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_IMPL_H */
\ No newline at end of file
+#endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_IMPL_H */
diff --git a/src/core/tsi/gts_transport_security.h b/src/core/tsi/gts_transport_security.h
index b988c3f..9590038 100644
--- a/src/core/tsi/gts_transport_security.h
+++ b/src/core/tsi/gts_transport_security.h
@@ -42,4 +42,4 @@
 }
 #endif
 
-#endif /* GRPC_CORE_TSI_GTS_TRANSPORT_SECURITY_H */
\ No newline at end of file
+#endif /* GRPC_CORE_TSI_GTS_TRANSPORT_SECURITY_H */
diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc
index e2893c8..de67281 100644
--- a/src/cpp/client/create_channel.cc
+++ b/src/cpp/client/create_channel.cc
@@ -38,8 +38,7 @@
     const grpc::string& target,
     const std::shared_ptr<ChannelCredentials>& creds,
     const ChannelArguments& args) {
-  internal::GrpcLibrary
-      init_lib;  // We need to call init in case of a bad creds.
+  GrpcLibraryCodegen init_lib;  // We need to call init in case of a bad creds.
   return creds
              ? creds->CreateChannel(target, args)
              : CreateChannelInternal("", grpc_lame_client_channel_create(
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index 6bd3ecd..d982a3d 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -266,8 +266,11 @@
 
   WorkStatus PollForWork(void** tag, bool* ok) override {
     *tag = nullptr;
+    // TODO(ctiller): workaround for GPR_TIMESPAN based deadlines not working
+    // right now
     gpr_timespec deadline =
-        gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN);
+        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                     gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN));
 
     switch (server_cq_->AsyncNext(tag, ok, deadline)) {
       case CompletionQueue::TIMEOUT:
diff --git a/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs b/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs
index 087b685..f599896 100644
--- a/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs
+++ b/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs
@@ -36,7 +36,21 @@
         readonly Func<Metadata> getTrailersFunc;
         readonly Action disposeAction;
 
-        internal AsyncClientStreamingCall(IClientStreamWriter<TRequest> requestStream, Task<TResponse> responseAsync, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)
+        /// <summary>
+        /// Creates a new AsyncClientStreamingCall object with the specified properties.
+        /// </summary>
+        /// <param name="requestStream">Stream of request values.</param>
+        /// <param name="responseAsync">The response of the asynchronous call.</param>
+        /// <param name="responseHeadersAsync">Response headers of the asynchronous call.</param>
+        /// <param name="getStatusFunc">Delegate returning the status of the call.</param>
+        /// <param name="getTrailersFunc">Delegate returning the trailing metadata of the call.</param>
+        /// <param name="disposeAction">Delegate to invoke when Dispose is called on the call object.</param>
+        public AsyncClientStreamingCall(IClientStreamWriter<TRequest> requestStream,
+                                        Task<TResponse> responseAsync,
+                                        Task<Metadata> responseHeadersAsync,
+                                        Func<Status> getStatusFunc,
+                                        Func<Metadata> getTrailersFunc,
+                                        Action disposeAction)
         {
             this.requestStream = requestStream;
             this.responseAsync = responseAsync;
diff --git a/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs b/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs
index ce49fb1..1cb1a91 100644
--- a/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs
+++ b/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs
@@ -35,7 +35,21 @@
         readonly Func<Metadata> getTrailersFunc;
         readonly Action disposeAction;
 
-        internal AsyncDuplexStreamingCall(IClientStreamWriter<TRequest> requestStream, IAsyncStreamReader<TResponse> responseStream, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)
+        /// <summary>
+        /// Creates a new AsyncDuplexStreamingCall object with the specified properties.
+        /// </summary>
+        /// <param name="requestStream">Stream of request values.</param>
+        /// <param name="responseStream">Stream of response values.</param>
+        /// <param name="responseHeadersAsync">Response headers of the asynchronous call.</param>
+        /// <param name="getStatusFunc">Delegate returning the status of the call.</param>
+        /// <param name="getTrailersFunc">Delegate returning the trailing metadata of the call.</param>
+        /// <param name="disposeAction">Delegate to invoke when Dispose is called on the call object.</param>
+        public AsyncDuplexStreamingCall(IClientStreamWriter<TRequest> requestStream,
+                                        IAsyncStreamReader<TResponse> responseStream,
+                                        Task<Metadata> responseHeadersAsync,
+                                        Func<Status> getStatusFunc,
+                                        Func<Metadata> getTrailersFunc,
+                                        Action disposeAction)
         {
             this.requestStream = requestStream;
             this.responseStream = responseStream;
diff --git a/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs b/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs
index fbc97b8..4303b0b 100644
--- a/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs
+++ b/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs
@@ -33,7 +33,19 @@
         readonly Func<Metadata> getTrailersFunc;
         readonly Action disposeAction;
 
-        internal AsyncServerStreamingCall(IAsyncStreamReader<TResponse> responseStream, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)
+        /// <summary>
+        /// Creates a new AsyncDuplexStreamingCall object with the specified properties.
+        /// </summary>
+        /// <param name="responseStream">Stream of response values.</param>
+        /// <param name="responseHeadersAsync">Response headers of the asynchronous call.</param>
+        /// <param name="getStatusFunc">Delegate returning the status of the call.</param>
+        /// <param name="getTrailersFunc">Delegate returning the trailing metadata of the call.</param>
+        /// <param name="disposeAction">Delegate to invoke when Dispose is called on the call object.</param>
+        public AsyncServerStreamingCall(IAsyncStreamReader<TResponse> responseStream,
+                                        Task<Metadata> responseHeadersAsync,
+                                        Func<Status> getStatusFunc,
+                                        Func<Metadata> getTrailersFunc,
+                                        Action disposeAction)
         {
             this.responseStream = responseStream;
             this.responseHeadersAsync = responseHeadersAsync;
diff --git a/src/csharp/Grpc.Core/AsyncUnaryCall.cs b/src/csharp/Grpc.Core/AsyncUnaryCall.cs
index 6348f3c..17747f8 100644
--- a/src/csharp/Grpc.Core/AsyncUnaryCall.cs
+++ b/src/csharp/Grpc.Core/AsyncUnaryCall.cs
@@ -34,7 +34,20 @@
         readonly Func<Metadata> getTrailersFunc;
         readonly Action disposeAction;
 
-        internal AsyncUnaryCall(Task<TResponse> responseAsync, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)
+
+        /// <summary>
+        /// Creates a new AsyncUnaryCall object with the specified properties.
+        /// </summary>
+        /// <param name="responseAsync">The response of the asynchronous call.</param>
+        /// <param name="responseHeadersAsync">Response headers of the asynchronous call.</param>
+        /// <param name="getStatusFunc">Delegate returning the status of the call.</param>
+        /// <param name="getTrailersFunc">Delegate returning the trailing metadata of the call.</param>
+        /// <param name="disposeAction">Delegate to invoke when Dispose is called on the call object.</param>
+        public AsyncUnaryCall(Task<TResponse> responseAsync,
+                              Task<Metadata> responseHeadersAsync,
+                              Func<Status> getStatusFunc,
+                              Func<Metadata> getTrailersFunc,
+                              Action disposeAction)
         {
             this.responseAsync = responseAsync;
             this.responseHeadersAsync = responseHeadersAsync;
diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m
index 82ac260..5672bda 100644
--- a/src/objective-c/tests/GRPCClientTests.m
+++ b/src/objective-c/tests/GRPCClientTests.m
@@ -18,6 +18,7 @@
 
 #import <UIKit/UIKit.h>
 #import <XCTest/XCTest.h>
+#import <grpc/grpc.h>
 
 #import <GRPCClient/GRPCCall.h>
 #import <GRPCClient/GRPCCall+ChannelArg.h>
@@ -30,6 +31,8 @@
 #import <RxLibrary/GRXWriter+Immediate.h>
 #import <RxLibrary/GRXBufferedPipe.h>
 
+#import "version.h"
+
 #define TEST_TIMEOUT 16
 
 static NSString * const kHostAddress = @"localhost:5050";
@@ -266,12 +269,38 @@
   id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
     XCTAssertNotNil(value, @"nil value received as response.");
     XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
-    /* This test needs to be more clever in regards to changing the version of the core.
-    XCTAssertEqualObjects(call.responseHeaders[@"x-grpc-test-echo-useragent"],
-                          @"Foo grpc-objc/0.13.0 grpc-c/0.14.0-dev (ios)",
-                          @"Did not receive expected user agent %@",
-                          call.responseHeaders[@"x-grpc-test-echo-useragent"]);
-    */
+
+    NSString *userAgent = call.responseHeaders[@"x-grpc-test-echo-useragent"];
+    NSError *error = nil;
+
+    // Test the regex is correct
+    NSString *expectedUserAgent = @"Foo grpc-objc/";
+    expectedUserAgent =
+        [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING];
+    expectedUserAgent =
+        [expectedUserAgent stringByAppendingString:@" grpc-c/"];
+    expectedUserAgent =
+        [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING];
+    expectedUserAgent =
+        [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "];
+    expectedUserAgent =
+        [expectedUserAgent stringByAppendingString:[NSString stringWithUTF8String:grpc_g_stands_for()]];
+    expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"];
+    XCTAssertEqualObjects(userAgent, expectedUserAgent);
+
+    // Change in format of user-agent field in a direction that does not match the regex will likely
+    // cause problem for certain gRPC users. For details, refer to internal doc https://goo.gl/c2diBc
+    NSRegularExpression *regex =
+        [NSRegularExpression regularExpressionWithPattern:@" grpc-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?/[^ ,]+( \\([^)]*\\))?"
+                                                  options:0
+                                                    error:&error];
+    NSString *customUserAgent =
+        [regex stringByReplacingMatchesInString:userAgent
+                                        options:0
+                                          range:NSMakeRange(0, [userAgent length])
+                                   withTemplate:@""];
+    XCTAssertEqualObjects(customUserAgent, @"Foo");
+
     [response fulfill];
   } completionHandler:^(NSError *errorOrNil) {
     XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
index b01d5ff..2f0c8cf 100644
--- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
+++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj
@@ -144,6 +144,7 @@
 		5EAD6D241E27047400002378 /* CronetUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CronetUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		5EAD6D261E27047400002378 /* CronetUnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CronetUnitTests.m; sourceTree = "<group>"; };
 		5EAD6D281E27047400002378 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		5EAFE8271F8EFB87007F2189 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
 		5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsRemoteWithCronet.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InteropTestsRemoteWithCronet.m; sourceTree = "<group>"; };
 		5EE84BF51D4717E40050C6CC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -398,6 +399,7 @@
 		635697C91B14FC11007A7283 /* Tests */ = {
 			isa = PBXGroup;
 			children = (
+				5EAFE8271F8EFB87007F2189 /* version.h */,
 				6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */,
 				63E240CC1B6C4D3A005F3B0E /* InteropTests.h */,
 				635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */,
@@ -740,9 +742,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -755,9 +760,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-frameworks.sh",
+				"${PODS_ROOT}/CronetFramework/Cronet.framework",
 			);
 			name = "[CP] Embed Pods Frameworks";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Cronet.framework",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -770,13 +778,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-InteropTestsRemote-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		4F5690DC0E6AD6663FE78B8B /* [CP] Embed Pods Frameworks */ = {
@@ -800,13 +811,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-InteropTestsLocalSSL-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		5F14F59509E10C2852014F9E /* [CP] Embed Pods Frameworks */ = {
@@ -830,9 +844,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -845,9 +862,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -860,13 +880,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-InteropTestsLocalCleartext-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		796680C7599CB4ED736DD62A /* [CP] Check Pods Manifest.lock */ = {
@@ -875,13 +898,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-Tests-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		80E2DDD2EC04A4009F45E933 /* [CP] Check Pods Manifest.lock */ = {
@@ -890,13 +916,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-CronetUnitTests-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		8AD3130D3C58A0FB32FF2A36 /* [CP] Copy Pods Resources */ = {
@@ -905,9 +934,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -935,13 +967,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-AllTests-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		A441F71824DCB9D0CA297748 /* [CP] Copy Pods Resources */ = {
@@ -950,9 +985,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-AllTests/Pods-AllTests-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -965,9 +1003,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests-frameworks.sh",
+				"${PODS_ROOT}/CronetFramework/Cronet.framework",
 			);
 			name = "[CP] Embed Pods Frameworks";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Cronet.framework",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -995,9 +1036,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -1010,13 +1054,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-RxLibraryUnitTests-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		C0F7B1FF6F88CC5FBF362F4C /* [CP] Check Pods Manifest.lock */ = {
@@ -1025,13 +1072,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-InteropTestsRemoteWithCronet-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		C2E09DC4BD239F71160F0CC1 /* [CP] Copy Pods Resources */ = {
@@ -1040,9 +1090,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -1070,9 +1123,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -1085,9 +1141,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-resources.sh",
+				$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -1100,9 +1159,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-frameworks.sh",
+				"${PODS_ROOT}/CronetFramework/Cronet.framework",
 			);
 			name = "[CP] Embed Pods Frameworks";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Cronet.framework",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -1115,13 +1177,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-CoreCronetEnd2EndTests-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 /* End PBXShellScriptBuildPhase section */
diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h
new file mode 100644
index 0000000..0251506
--- /dev/null
+++ b/src/objective-c/tests/version.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// This file is autogenerated from a template file. Please make
+// modifications to
+// `templates/src/objective-c/GRPCClient/private/version.h.template`
+// instead. This file can be regenerated from the template by running
+// `tools/buildgen/generate_projects.sh`.
+
+
+#define GRPC_OBJC_VERSION_STRING @"1.8.0-dev"
+#define GRPC_C_VERSION_STRING @"5.0.0-dev"
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index e460377..a65d233 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -169,7 +169,7 @@
 /**
  * Add a http2 over tcp listener.
  * @param string $addr The address to add
- * @return bool True on success, false on failure
+ * @return int Port on success, 0 on failure
  */
 PHP_METHOD(Server, addHttp2Port) {
   const char *addr;
@@ -190,7 +190,7 @@
  * Add a secure http2 over tcp listener.
  * @param string $addr The address to add
  * @param ServerCredentials The ServerCredentials object
- * @return bool True on success, false on failure
+ * @return int Port on success, 0 on failure
  */
 PHP_METHOD(Server, addSecureHttp2Port) {
   const char *addr;
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index b62c2c2..67378a3 100644
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -218,7 +218,7 @@
      *                              (optional)
      * @param array    $options     An array of options (optional)
      *
-     * @return SimpleSurfaceActiveCall The active call object
+     * @return UnaryCall The active call object
      */
     protected function _simpleRequest($method,
                                    $argument,
@@ -253,7 +253,7 @@
      *                              (optional)
      * @param array    $options     An array of options (optional)
      *
-     * @return ClientStreamingSurfaceActiveCall The active call object
+     * @return ClientStreamingCall The active call object
      */
     protected function _clientStreamRequest($method,
                                          $deserialize,
@@ -288,7 +288,7 @@
      *                              (optional)
      * @param array    $options     An array of options (optional)
      *
-     * @return ServerStreamingSurfaceActiveCall The active call object
+     * @return ServerStreamingCall The active call object
      */
     protected function _serverStreamRequest($method,
                                          $argument,
@@ -322,7 +322,7 @@
      *                              (optional)
      * @param array    $options     An array of options (optional)
      *
-     * @return BidiStreamingSurfaceActiveCall The active call object
+     * @return BidiStreamingCall The active call object
      */
     protected function _bidiRequest($method,
                                  $deserialize,
diff --git a/src/proto/grpc/testing/echo_messages.proto b/src/proto/grpc/testing/echo_messages.proto
index c5c5fdb..5396a2f 100644
--- a/src/proto/grpc/testing/echo_messages.proto
+++ b/src/proto/grpc/testing/echo_messages.proto
@@ -45,6 +45,7 @@
   bool server_die = 12; // Server should not see a request with this set.
   string binary_error_details = 13;
   ErrorStatus expected_error = 14;
+  int32 server_sleep_us = 15; // Amount to sleep when invoking server
 }
 
 message EchoRequest {
diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb
index e5ab02b..9d2cf2a 100644
--- a/src/ruby/ext/grpc/extconf.rb
+++ b/src/ruby/ext/grpc/extconf.rb
@@ -41,6 +41,7 @@
 ]
 
 windows = RUBY_PLATFORM =~ /mingw|mswin/
+bsd = RUBY_PLATFORM =~ /bsd/
 
 grpc_root = File.expand_path(File.join(File.dirname(__FILE__), '../../../..'))
 
@@ -70,7 +71,8 @@
   puts 'Building internal gRPC into ' + grpc_lib_dir
   nproc = 4
   nproc = Etc.nprocessors * 2 if Etc.respond_to? :nprocessors
-  system("make -j#{nproc} -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config} Q=")
+  make = bsd ? 'gmake' : 'make'
+  system("#{make} -j#{nproc} -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config} Q=")
   exit 1 unless $? == 0
 end
 
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 29c4a94..e920fc8 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -221,6 +221,7 @@
   TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call);
   if (call != NULL) {
     destroy_call(call);
+    xfree(RTYPEDDATA_DATA(self));
     RTYPEDDATA_DATA(self) = NULL;
   }
   return Qnil;
diff --git a/src/ruby/qps/proxy-worker.rb b/src/ruby/qps/proxy-worker.rb
index fc5db50..4c7c510 100755
--- a/src/ruby/qps/proxy-worker.rb
+++ b/src/ruby/qps/proxy-worker.rb
@@ -31,9 +31,10 @@
 require 'src/proto/grpc/testing/proxy-service_services_pb'
 
 class ProxyBenchmarkClientServiceImpl < Grpc::Testing::ProxyClientService::Service
-  def initialize(port, c_ext)
+  def initialize(port, c_ext, php_client_bin)
     @mytarget = "localhost:" + port.to_s
     @use_c_ext = c_ext
+    @php_client_bin = php_client_bin
   end
   def setup(config)
     @config = config
@@ -49,11 +50,11 @@
           command = "php -d extension=" + File.expand_path(File.dirname(__FILE__)) +
             "/../../php/tests/qps/vendor/google/protobuf/php/ext/google/protobuf/modules/protobuf.so " +
             "-d extension=" + File.expand_path(File.dirname(__FILE__)) + "/../../php/ext/grpc/modules/grpc.so " +
-            File.expand_path(File.dirname(__FILE__)) + "/../../php/tests/qps/client.php " + @mytarget + " #{chan%@config.server_targets.length}"
+            File.expand_path(File.dirname(__FILE__)) + "/" + @php_client_bin + " " + @mytarget + " #{chan%@config.server_targets.length}"
         else
           puts "Use protobuf php extension"
           command = "php -d extension=" + File.expand_path(File.dirname(__FILE__)) + "/../../php/ext/grpc/modules/grpc.so " +
-            File.expand_path(File.dirname(__FILE__)) + "/../../php/tests/qps/client.php " + @mytarget + " #{chan%@config.server_targets.length}"
+            File.expand_path(File.dirname(__FILE__)) + "/" + @php_client_bin + " " + @mytarget + " #{chan%@config.server_targets.length}"
         end
         puts "[ruby proxy] Starting #{chan}th php-client command use c protobuf #{@use_c_ext}: " + command
         @php_pid[chan] = spawn(command)
@@ -145,7 +146,8 @@
 
 def proxymain
   options = {
-    'driver_port' => 0
+    'driver_port' => 0,
+    'php_client_bin' => '../../php/tests/qps/client.php'
   }
   OptionParser.new do |opts|
     opts.banner = 'Usage: [--driver_port <port>]'
@@ -155,6 +157,10 @@
     opts.on("-c", "--[no-]use_protobuf_c_extension", "Use protobuf C-extention") do |c|
       options[:c_ext] = c
     end
+    opts.on("-b", "--php_client_bin [FILE]",
+      "PHP client to execute; path relative to this script") do |c|
+      options['php_client_bin'] = c
+    end
   end.parse!
 
   # Configure any errors with client or server child threads to surface
@@ -164,7 +170,7 @@
   s = GRPC::RpcServer.new(pool_size: 1024)
   port = s.add_http2_port("0.0.0.0:" + options['driver_port'].to_s,
                           :this_port_is_insecure)
-  bmc = ProxyBenchmarkClientServiceImpl.new(port, options[:c_ext])
+  bmc = ProxyBenchmarkClientServiceImpl.new(port, options[:c_ext], options['php_client_bin'])
   s.handle(bmc)
   s.handle(ProxyWorkerServiceImpl.new(s, bmc))
   s.run
diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template
index 567bd3b..2ed7c90 100644
--- a/templates/CMakeLists.txt.template
+++ b/templates/CMakeLists.txt.template
@@ -73,7 +73,7 @@
   set(PACKAGE_TARNAME   "<%text>${PACKAGE_NAME}-${PACKAGE_VERSION}</%text>")
   set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
   project(<%text>${PACKAGE_NAME}</%text> C CXX)
-  
+
   set(gRPC_INSTALL_BINDIR "<%text>${CMAKE_INSTALL_PREFIX}</%text>/bin" CACHE PATH "Installation directory for executables")
   set(gRPC_INSTALL_LIBDIR "<%text>${CMAKE_INSTALL_PREFIX}</%text>/lib" CACHE PATH "Installation directory for libraries")
   set(gRPC_INSTALL_INCLUDEDIR "<%text>${CMAKE_INSTALL_PREFIX}</%text>/include" CACHE PATH "Installation directory for headers")
@@ -522,6 +522,7 @@
     PRIVATE <%text>${CARES_INCLUDE_DIR}</%text>
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/cares/cares
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/gflags/include
+    PRIVATE <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/third_party/abseil-cpp
   % if lib.build in ['test', 'private'] and lib.language == 'c++':
     PRIVATE third_party/googletest/googletest/include
     PRIVATE third_party/googletest/googletest
@@ -593,6 +594,7 @@
     PRIVATE <%text>${CARES_INCLUDE_DIR}</%text>
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/cares/cares
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/gflags/include
+    PRIVATE <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/third_party/abseil-cpp
   % if tgt.build in ['test', 'private'] and tgt.language == 'c++':
     PRIVATE third_party/googletest/googletest/include
     PRIVATE third_party/googletest/googletest
diff --git a/templates/src/objective-c/tests/version.h.template b/templates/src/objective-c/tests/version.h.template
new file mode 100644
index 0000000..72774ab
--- /dev/null
+++ b/templates/src/objective-c/tests/version.h.template
@@ -0,0 +1,29 @@
+%YAML 1.2
+--- |
+  /*
+   *
+   * Copyright 2015 gRPC authors.
+   *
+   * Licensed under the Apache License, Version 2.0 (the "License");
+   * you may not use this file except in compliance with the License.
+   * You may obtain a copy of the License at
+   *
+   *     http://www.apache.org/licenses/LICENSE-2.0
+   *
+   * Unless required by applicable law or agreed to in writing, software
+   * distributed under the License is distributed on an "AS IS" BASIS,
+   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   * See the License for the specific language governing permissions and
+   * limitations under the License.
+   *
+   */
+
+  // This file is autogenerated from a template file. Please make
+  // modifications to
+  // `templates/src/objective-c/GRPCClient/private/version.h.template`
+  // instead. This file can be regenerated from the template by running
+  // `tools/buildgen/generate_projects.sh`.
+
+
+  #define GRPC_OBJC_VERSION_STRING @"${settings.version}"
+  #define GRPC_C_VERSION_STRING @"${settings.core_version}"
diff --git a/templates/tools/run_tests/generated/tests.json.template b/templates/tools/run_tests/generated/tests.json.template
index 10ab2e4..c5dc26f 100644
--- a/templates/tools/run_tests/generated/tests.json.template
+++ b/templates/tools/run_tests/generated/tests.json.template
@@ -9,11 +9,13 @@
            "platforms": tgt.platforms,
            "ci_platforms": tgt.ci_platforms,
            "gtest": tgt.gtest,
+           "benchmark": tgt.get("benchmark", False),
            "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)}
+           "cpu_cost": tgt.get("cpu_cost", 1.0),
+           "uses_polling": tgt.get("uses_polling", True)}
     timeout_seconds = tgt.get("timeout_seconds", None)
     if timeout_seconds:
       out['timeout_seconds'] = timeout_seconds
diff --git a/test/core/bad_client/gen_build_yaml.py b/test/core/bad_client/gen_build_yaml.py
index dbd5277..61cf1f7 100755
--- a/test/core/bad_client/gen_build_yaml.py
+++ b/test/core/bad_client/gen_build_yaml.py
@@ -30,7 +30,7 @@
     'headers': default_test_options._replace(cpu_cost=0.2),
     'initial_settings_frame': default_test_options._replace(cpu_cost=0.2),
     'head_of_line_blocking': default_test_options,
-    'large_metadata': default_test_options,
+    # 'large_metadata': default_test_options, #disabling as per issue #11745
     'server_registered_method': default_test_options,
     'simple_request': default_test_options,
     'window_overflow': default_test_options,
diff --git a/test/core/bad_client/generate_tests.bzl b/test/core/bad_client/generate_tests.bzl
index 1aeb81c..58b48d6 100755
--- a/test/core/bad_client/generate_tests.bzl
+++ b/test/core/bad_client/generate_tests.bzl
@@ -28,7 +28,7 @@
     'headers': test_options(),
     'initial_settings_frame': test_options(),
     'head_of_line_blocking': test_options(),
-    'large_metadata': test_options(),
+    # 'large_metadata': test_options(), # disabling as per issue #11745
     'server_registered_method': test_options(),
     'simple_request': test_options(),
     'window_overflow': test_options(),
diff --git a/test/core/debug/stats_test.cc b/test/core/debug/stats_test.cc
index c85ab35..5015819 100644
--- a/test/core/debug/stats_test.cc
+++ b/test/core/debug/stats_test.cc
@@ -20,7 +20,11 @@
 #include "src/core/lib/debug/stats.h"
 }
 
+#include <mutex>
+#include <thread>
+
 #include <grpc/grpc.h>
+#include <grpc/support/cpu.h>
 #include <grpc/support/log.h>
 #include <gtest/gtest.h>
 
@@ -79,38 +83,59 @@
          grpc_stats_histo_bucket_boundaries[i] - 1;
 }
 
-TEST(StatsTest, IncHistogram) {
-  for (int i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
-    std::vector<int> test_values;
-    for (int j = -1000;
-         j <
-         grpc_stats_histo_bucket_boundaries[i]
-                                           [grpc_stats_histo_buckets[i] - 1] +
-             1000;
-         j++) {
-      test_values.push_back(j);
-    }
-    std::random_shuffle(test_values.begin(), test_values.end());
-    if (test_values.size() > 10000) {
-      test_values.resize(10000);
-    }
+class HistogramTest : public ::testing::TestWithParam<int> {};
+
+TEST_P(HistogramTest, IncHistogram) {
+  const int kHistogram = GetParam();
+  std::vector<std::thread> threads;
+  int cur_bucket = 0;
+  auto run = [kHistogram](const std::vector<int>& test_values,
+                          int expected_bucket) {
+    gpr_log(GPR_DEBUG, "expected_bucket:%d nvalues=%" PRIdPTR, expected_bucket,
+            test_values.size());
     for (auto j : test_values) {
       Snapshot snapshot;
 
-      int expected_bucket = FindExpectedBucket(i, j);
-
       grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-      grpc_stats_inc_histogram[i](&exec_ctx, j);
+      grpc_stats_inc_histogram[kHistogram](&exec_ctx, j);
       grpc_exec_ctx_finish(&exec_ctx);
 
       auto delta = snapshot.delta();
 
-      EXPECT_EQ(delta.histograms[grpc_stats_histo_start[i] + expected_bucket],
-                1);
+      EXPECT_EQ(
+          delta
+              .histograms[grpc_stats_histo_start[kHistogram] + expected_bucket],
+          1)
+          << "\nhistogram:" << kHistogram
+          << "\nexpected_bucket:" << expected_bucket << "\nj:" << j;
     }
+  };
+  std::vector<int> test_values;
+  for (int j = -1000;
+       j <
+       grpc_stats_histo_bucket_boundaries[kHistogram]
+                                         [grpc_stats_histo_buckets[kHistogram] -
+                                          1] +
+           1000;
+       j++) {
+    int expected_bucket = FindExpectedBucket(kHistogram, j);
+    if (cur_bucket != expected_bucket) {
+      threads.emplace_back(
+          [test_values, run, cur_bucket]() { run(test_values, cur_bucket); });
+      cur_bucket = expected_bucket;
+      test_values.clear();
+    }
+    test_values.push_back(j);
+  }
+  run(test_values, cur_bucket);
+  for (auto& t : threads) {
+    t.join();
   }
 }
 
+INSTANTIATE_TEST_CASE_P(HistogramTestCases, HistogramTest,
+                        ::testing::Range<int>(0, GRPC_STATS_HISTOGRAM_COUNT));
+
 }  // namespace testing
 }  // namespace grpc
 
diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c
index eeabc76..2070fa5 100644
--- a/test/core/end2end/bad_server_response_test.c
+++ b/test/core/end2end/bad_server_response_test.c
@@ -62,8 +62,6 @@
 #define HTTP2_DETAIL_MSG(STATUS_CODE) \
   "Received http2 header with status: " #STATUS_CODE
 
-#define UNPARSEABLE_DETAIL_MSG "Failed parsing HTTP/2"
-
 #define HTTP1_DETAIL_MSG "Trying to connect an http1.x server"
 
 /* TODO(zyc) Check the content of incomming data instead of using this length */
@@ -208,8 +206,10 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == expected_status);
-  GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string(
-                                                 expected_detail)));
+  if (expected_detail != NULL) {
+    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);
@@ -330,8 +330,8 @@
            HTTP2_DETAIL_MSG(502));
 
   /* unparseable response */
-  run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1,
-           GRPC_STATUS_UNAVAILABLE, UNPARSEABLE_DETAIL_MSG);
+  run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1, GRPC_STATUS_UNKNOWN,
+           NULL);
 
   /* http1 response */
   run_test(HTTP1_RESP, sizeof(HTTP1_RESP) - 1, GRPC_STATUS_UNAVAILABLE,
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 33fd97f..f7f996d 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -24,15 +24,15 @@
 
 FixtureOptions = collections.namedtuple(
     'FixtureOptions',
-    'fullstack includes_proxy dns_resolver name_resolution secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression supports_compression is_inproc is_http2 supports_proxy_auth')
+    'fullstack includes_proxy dns_resolver name_resolution secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression supports_compression is_inproc is_http2 supports_proxy_auth supports_write_buffering')
 default_unsecure_fixture_options = FixtureOptions(
-    True, False, True, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True, False, True, False, True, False)
+    True, False, True, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True, False, True, False, True, False, True)
 socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace(fullstack=False, dns_resolver=False)
 default_secure_fixture_options = default_unsecure_fixture_options._replace(secure=True)
 uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, platforms=['linux', 'mac', 'posix'], exclude_iomgrs=['uv'])
 fd_unsecure_fixture_options = default_unsecure_fixture_options._replace(
     dns_resolver=False, fullstack=False, platforms=['linux', 'mac', 'posix'], exclude_iomgrs=['uv'])
-inproc_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, fullstack=False, name_resolution=False, supports_compression=False, is_inproc=True, is_http2=False)
+inproc_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, fullstack=False, name_resolution=False, supports_compression=False, is_inproc=True, is_http2=False, supports_write_buffering=False)
 
 # maps fixture name to whether it requires the security library
 END2END_FIXTURES = {
@@ -60,7 +60,6 @@
     'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace(
         ci_mac=False, tracing=True, large_writes=False, exclude_iomgrs=['uv']),
     'h2_ssl': default_secure_fixture_options,
-    'h2_ssl_cert': default_secure_fixture_options,
     'h2_ssl_proxy': default_secure_fixture_options._replace(
         includes_proxy=True, ci_mac=False, exclude_iomgrs=['uv']),
     'h2_uds': uds_fixture_options,
@@ -69,8 +68,8 @@
 
 TestOptions = collections.namedtuple(
     'TestOptions',
-    'needs_fullstack needs_dns needs_names proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allows_compression needs_compression exclude_inproc needs_http2 needs_proxy_auth')
-default_test_options = TestOptions(False, False, False, True, False, True, 1.0, [], False, False, True, False, False, False, False)
+    'needs_fullstack needs_dns needs_names proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allows_compression needs_compression exclude_inproc needs_http2 needs_proxy_auth needs_write_buffering')
+default_test_options = TestOptions(False, False, False, True, False, True, 1.0, [], False, False, True, False, False, False, False, False)
 connectivity_test_options = default_test_options._replace(needs_fullstack=True)
 
 LOWCPU = 0.1
@@ -147,8 +146,10 @@
     'streaming_error_response': default_test_options._replace(cpu_cost=LOWCPU),
     'trailing_metadata': default_test_options,
     'workaround_cronet_compression': default_test_options,
-    'write_buffering': default_test_options._replace(cpu_cost=LOWCPU),
-    'write_buffering_at_end': default_test_options._replace(cpu_cost=LOWCPU),
+    'write_buffering': default_test_options._replace(cpu_cost=LOWCPU,
+                                                     needs_write_buffering=True),
+    'write_buffering_at_end': default_test_options._replace(cpu_cost=LOWCPU,
+                                                     needs_write_buffering=True),
 }
 
 
@@ -186,6 +187,9 @@
   if END2END_TESTS[t].needs_proxy_auth:
     if not END2END_FIXTURES[f].supports_proxy_auth:
       return False
+  if END2END_TESTS[t].needs_write_buffering:
+    if not END2END_FIXTURES[f].supports_write_buffering:
+      return False
   return True
 
 
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 9bbba26..89a95ed 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -21,7 +21,8 @@
 def fixture_options(fullstack=True, includes_proxy=False, dns_resolver=True,
                     name_resolution=True, secure=True, tracing=False,
                     platforms=['windows', 'linux', 'mac', 'posix'],
-                    is_inproc=False, is_http2=True, supports_proxy_auth=False):
+                    is_inproc=False, is_http2=True, supports_proxy_auth=False,
+                    supports_write_buffering=True):
   return struct(
     fullstack=fullstack,
     includes_proxy=includes_proxy,
@@ -31,7 +32,8 @@
     tracing=tracing,
     is_inproc=is_inproc,
     is_http2=is_http2,
-    supports_proxy_auth=supports_proxy_auth
+    supports_proxy_auth=supports_proxy_auth,
+    supports_write_buffering=supports_write_buffering
     #platforms=platforms
   )
 
@@ -56,20 +58,19 @@
     'h2_sockpair+trace': fixture_options(fullstack=False, dns_resolver=False,
                                          tracing=True),
     'h2_ssl': fixture_options(secure=True),
-    'h2_ssl_cert': fixture_options(secure=True),
     'h2_ssl_proxy': fixture_options(includes_proxy=True, secure=True),
     'h2_uds': fixture_options(dns_resolver=False,
                               platforms=['linux', 'mac', 'posix']),
     'inproc': fixture_options(fullstack=False, dns_resolver=False,
                               name_resolution=False, is_inproc=True,
-                              is_http2=False),
+                              is_http2=False, supports_write_buffering=False),
 }
 
 
 def test_options(needs_fullstack=False, needs_dns=False, needs_names=False,
                  proxyable=True, secure=False, traceable=False,
                  exclude_inproc=False, needs_http2=False,
-                 needs_proxy_auth=False):
+                 needs_proxy_auth=False, needs_write_buffering=False):
   return struct(
     needs_fullstack=needs_fullstack,
     needs_dns=needs_dns,
@@ -79,7 +80,8 @@
     traceable=traceable,
     exclude_inproc=exclude_inproc,
     needs_http2=needs_http2,
-    needs_proxy_auth=needs_proxy_auth
+    needs_proxy_auth=needs_proxy_auth,
+    needs_write_buffering=needs_write_buffering
   )
 
 
@@ -145,8 +147,8 @@
     'authority_not_supported': test_options(),
     'filter_latency': test_options(),
     'workaround_cronet_compression': test_options(),
-    'write_buffering': test_options(),
-    'write_buffering_at_end': test_options(),
+    'write_buffering': test_options(needs_write_buffering=True),
+    'write_buffering_at_end': test_options(needs_write_buffering=True),
 }
 
 
@@ -175,6 +177,9 @@
   if topt.needs_proxy_auth:
     if not fopt.supports_proxy_auth:
       return False
+  if topt.needs_write_buffering:
+    if not fopt.supports_write_buffering:
+      return False
   return True
 
 
diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/h2_ssl_cert_test.cc
similarity index 88%
rename from test/core/end2end/fixtures/h2_ssl_cert.c
rename to test/core/end2end/h2_ssl_cert_test.cc
index f0a2ee5..6da5e83 100644
--- a/test/core/end2end/fixtures/h2_ssl_cert.c
+++ b/test/core/end2end/h2_ssl_cert_test.cc
@@ -16,7 +16,9 @@
  *
  */
 
+extern "C" {
 #include "test/core/end2end/end2end_tests.h"
+}
 
 #include <stdio.h>
 #include <string.h>
@@ -25,6 +27,7 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 
+extern "C" {
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/support/env.h"
@@ -34,8 +37,12 @@
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
+}
 
-extern void simple_request(grpc_end2end_test_config config);
+#include <gtest/gtest.h>
+
+namespace grpc {
+namespace testing {
 
 typedef struct fullstack_secure_fixture_data {
   char *localaddr;
@@ -46,7 +53,8 @@
   grpc_end2end_test_fixture f;
   int port = grpc_pick_unused_port_or_die();
   fullstack_secure_fixture_data *ffd =
-      gpr_malloc(sizeof(fullstack_secure_fixture_data));
+      static_cast<fullstack_secure_fixture_data *>(
+          gpr_malloc(sizeof(fullstack_secure_fixture_data)));
   memset(&f, 0, sizeof(f));
 
   gpr_join_host_port(&ffd->localaddr, "localhost", port);
@@ -69,7 +77,8 @@
 static void chttp2_init_client_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
     grpc_channel_credentials *creds) {
-  fullstack_secure_fixture_data *ffd = f->fixture_data;
+  fullstack_secure_fixture_data *ffd =
+      static_cast<fullstack_secure_fixture_data *>(f->fixture_data);
   f->client =
       grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL);
   GPR_ASSERT(f->client != NULL);
@@ -79,7 +88,8 @@
 static void chttp2_init_server_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *server_args,
     grpc_server_credentials *server_creds) {
-  fullstack_secure_fixture_data *ffd = f->fixture_data;
+  fullstack_secure_fixture_data *ffd =
+      static_cast<fullstack_secure_fixture_data *>(f->fixture_data);
   if (f->server) {
     grpc_server_destroy(f->server);
   }
@@ -92,7 +102,8 @@
 }
 
 void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
-  fullstack_secure_fixture_data *ffd = f->fixture_data;
+  fullstack_secure_fixture_data *ffd =
+      static_cast<fullstack_secure_fixture_data *>(f->fixture_data);
   gpr_free(ffd->localaddr);
   gpr_free(ffd);
 }
@@ -166,9 +177,10 @@
     }                                                                        \
     ssl_creds =                                                              \
         grpc_ssl_credentials_create(test_root_cert, key_cert_pair, NULL);    \
-    grpc_arg ssl_name_override = {GRPC_ARG_STRING,                           \
-                                  GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,         \
-                                  {"foo.test.google.fr"}};                   \
+    grpc_arg ssl_name_override = {                                           \
+        GRPC_ARG_STRING,                                                     \
+        const_cast<char *>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),               \
+        {const_cast<char *>("foo.test.google.fr")}};                         \
     grpc_channel_args *new_client_args =                                     \
         grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);  \
     chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds);      \
@@ -248,18 +260,6 @@
 
 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);
 }
@@ -332,15 +332,40 @@
   cq_verifier_destroy(cqv);
 }
 
+class H2SslCertTest
+    : public ::testing::TestWithParam<grpc_end2end_test_config_wrapper> {
+ protected:
+  H2SslCertTest() {
+    gpr_log(GPR_INFO, "SSL_CERT_tests/%s", GetParam().config.name);
+  }
+  void SetUp() override {
+    fixture_ = GetParam().config.create_fixture(nullptr, nullptr);
+    GetParam().config.init_server(&fixture_, nullptr);
+    GetParam().config.init_client(&fixture_, nullptr);
+  }
+  void TearDown() override {
+    end_test(&fixture_);
+    GetParam().config.tear_down_data(&fixture_);
+  }
+
+  grpc_end2end_test_fixture fixture_;
+};
+
+TEST_P(H2SslCertTest, SimpleRequestBody) {
+  simple_request_body(fixture_, GetParam().result);
+}
+
+INSTANTIATE_TEST_CASE_P(H2SslCert, H2SslCertTest, ::testing::ValuesIn(configs));
+
+}  // namespace testing
+}  // namespace grpc
+
 int main(int argc, char **argv) {
-  size_t i;
   FILE *roots_file;
   size_t roots_size = strlen(test_root_cert);
   char *roots_filename;
 
   grpc_test_init(argc, argv);
-  grpc_end2end_tests_pre_init();
-
   /* Set the SSL roots env var. */
   roots_file =
       gpr_tmpfile("chttp2_simple_ssl_cert_fullstack_test", &roots_filename);
@@ -351,21 +376,13 @@
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename);
 
   grpc_init();
-
-  for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
-    grpc_end2end_test_fixture f =
-        begin_test(configs[i].config, "SSL_CERT_tests", NULL, NULL);
-
-    simple_request_body(f, configs[i].result);
-    end_test(&f);
-    configs[i].config.tear_down_data(&f);
-  }
-
+  ::testing::InitGoogleTest(&argc, argv);
+  int ret = RUN_ALL_TESTS();
   grpc_shutdown();
 
   /* Cleanup. */
   remove(roots_filename);
   gpr_free(roots_filename);
 
-  return 0;
+  return ret;
 }
diff --git a/test/core/end2end/tests/bad_ping.c b/test/core/end2end/tests/bad_ping.c
index d442f12..34cc8e7 100644
--- a/test/core/end2end/tests/bad_ping.c
+++ b/test/core/end2end/tests/bad_ping.c
@@ -203,7 +203,6 @@
   // The connection should be closed immediately after the misbehaved pings,
   // the in-progress RPC should fail.
   GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "Endpoint read failed"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c
index c428014..0053368 100644
--- a/test/core/end2end/tests/keepalive_timeout.c
+++ b/test/core/end2end/tests/keepalive_timeout.c
@@ -193,7 +193,7 @@
 
   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(status == GRPC_STATUS_INTERNAL);
   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,
diff --git a/test/core/end2end/tests/max_connection_age.c b/test/core/end2end/tests/max_connection_age.c
index 4119087..b6daa59 100644
--- a/test/core/end2end/tests/max_connection_age.c
+++ b/test/core/end2end/tests/max_connection_age.c
@@ -203,8 +203,7 @@
 
   /* The connection should be closed immediately after the max age grace period,
      the in-progress RPC should fail. */
-  GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
-  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "Endpoint read failed"));
+  GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c
index cef571b..f90359f 100644
--- a/test/core/end2end/tests/shutdown_finishes_calls.c
+++ b/test/core/end2end/tests/shutdown_finishes_calls.c
@@ -159,7 +159,9 @@
 
   grpc_server_destroy(f.server);
 
-  GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
+  // new code should give INTERNAL, some older code will give UNAVAILABLE
+  GPR_ASSERT(status == GRPC_STATUS_INTERNAL ||
+             status == GRPC_STATUS_UNAVAILABLE);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
diff --git a/test/core/end2end/tests/streaming_error_response.c b/test/core/end2end/tests/streaming_error_response.c
index 9d562b9..8891b86 100644
--- a/test/core/end2end/tests/streaming_error_response.c
+++ b/test/core/end2end/tests/streaming_error_response.c
@@ -183,7 +183,6 @@
   GPR_ASSERT(GRPC_CALL_OK == error);
 
   CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
-  cq_verify(cqv);
 
   if (!request_status_early) {
     memset(ops, 0, sizeof(ops));
diff --git a/test/core/iomgr/pollset_set_test.c b/test/core/iomgr/pollset_set_test.c
index 3dd4bc8..cddc146 100644
--- a/test/core/iomgr/pollset_set_test.c
+++ b/test/core/iomgr/pollset_set_test.c
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
@@ -430,14 +431,13 @@
 }
 
 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(&exec_ctx);
-  grpc_iomgr_start(&exec_ctx);
+  grpc_init();
+  const char *poll_strategy = grpc_get_poll_strategy_name();
 
   if (poll_strategy != NULL &&
-      (strcmp(poll_strategy, "epoll") == 0 ||
+      (strcmp(poll_strategy, "epollsig") == 0 ||
        strcmp(poll_strategy, "epoll-threadpool") == 0)) {
     pollset_set_test_basic();
     pollset_set_test_dup_fds();
@@ -449,8 +449,8 @@
             poll_strategy);
   }
 
-  grpc_iomgr_shutdown(&exec_ctx);
   grpc_exec_ctx_finish(&exec_ctx);
+  grpc_shutdown();
   return 0;
 }
 #else /* defined(GRPC_LINUX_EPOLL) */
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
index dc41759..83b1747 100644
--- a/test/core/security/BUILD
+++ b/test/core/security/BUILD
@@ -91,6 +91,18 @@
     ],
 )
 
+grpc_cc_test(
+    name = "ssl_credentials_test",
+    srcs = ["ssl_credentials_test.c"],
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ]
+)
+
 grpc_cc_binary(
     name = "create_jwt",
     srcs = ["create_jwt.c"],
diff --git a/test/core/security/ssl_credentials_test.c b/test/core/security/ssl_credentials_test.c
new file mode 100644
index 0000000..3c838fa
--- /dev/null
+++ b/test/core/security/ssl_credentials_test.c
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/security/credentials/ssl/ssl_credentials.h"
+#include "src/core/tsi/ssl_transport_security.h"
+#include "test/core/util/test_config.h"
+
+static void test_convert_grpc_to_tsi_cert_pairs() {
+  grpc_ssl_pem_key_cert_pair grpc_pairs[] = {{"private_key1", "cert_chain1"},
+                                             {"private_key2", "cert_chain2"},
+                                             {"private_key3", "cert_chain3"}};
+  const size_t num_pairs = 3;
+
+  {
+    tsi_ssl_pem_key_cert_pair *tsi_pairs =
+        grpc_convert_grpc_to_tsi_cert_pairs(grpc_pairs, 0);
+    GPR_ASSERT(tsi_pairs == NULL);
+  }
+
+  {
+    tsi_ssl_pem_key_cert_pair *tsi_pairs =
+        grpc_convert_grpc_to_tsi_cert_pairs(grpc_pairs, num_pairs);
+
+    GPR_ASSERT(tsi_pairs != NULL);
+    for (size_t i = 0; i < num_pairs; i++) {
+      GPR_ASSERT(strncmp(grpc_pairs[i].private_key, tsi_pairs[i].private_key,
+                         strlen(grpc_pairs[i].private_key)) == 0);
+      GPR_ASSERT(strncmp(grpc_pairs[i].cert_chain, tsi_pairs[i].cert_chain,
+                         strlen(grpc_pairs[i].cert_chain)) == 0);
+    }
+
+    grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_pairs, num_pairs);
+  }
+}
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+  grpc_init();
+
+  test_convert_grpc_to_tsi_cert_pairs();
+
+  grpc_shutdown();
+  return 0;
+}
diff --git a/test/core/support/BUILD b/test/core/support/BUILD
index 407c3ef..3bdc1c4 100644
--- a/test/core/support/BUILD
+++ b/test/core/support/BUILD
@@ -197,3 +197,29 @@
         "//test/core/util:gpr_test_util",
     ],
 )
+
+grpc_cc_test(
+    name = "memory_test",
+    srcs = ["memory_test.cc"],
+    language = "C++",
+    deps = [
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
+)
+
+grpc_cc_test(
+    name = "vector_test",
+    srcs = ["vector_test.cc"],
+    language = "C++",
+    deps = [
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
+)
diff --git a/test/core/support/vector_test.cc b/test/core/support/vector_test.cc
new file mode 100644
index 0000000..aad9f3b
--- /dev/null
+++ b/test/core/support/vector_test.cc
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "src/core/lib/support/vector.h"
+#include <gtest/gtest.h>
+#include "test/core/util/test_config.h"
+
+namespace grpc_core {
+namespace testing {
+
+TEST(InlinedVectorTest, CreateAndIterate) {
+  InlinedVector<int, 1> v{1, 2, 3};
+  int sum = 0;
+  for (auto i : v) {
+    sum += i;
+  }
+  EXPECT_EQ(6, sum);
+}
+
+}  // namespace testing
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  grpc_test_init(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/core/surface/init_test.c b/test/core/surface/init_test.c
index a9e8057..b835a2a 100644
--- a/test/core/surface/init_test.c
+++ b/test/core/surface/init_test.c
@@ -53,7 +53,7 @@
 }
 
 static void test_repeatedly() {
-  for (int i = 0; i < 100000; i++) {
+  for (int i = 0; i < 1000; i++) {
     grpc_init();
     grpc_shutdown();
   }
diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD
index 12e3613..edd27b8 100644
--- a/test/core/transport/BUILD
+++ b/test/core/transport/BUILD
@@ -20,14 +20,17 @@
 
 grpc_cc_test(
     name = "bdp_estimator_test",
-    srcs = ["bdp_estimator_test.c"],
-    language = "C",
+    srcs = ["bdp_estimator_test.cc"],
+    language = "C++",
     deps = [
         "//:gpr",
         "//:grpc",
         "//test/core/util:gpr_test_util",
         "//test/core/util:grpc_test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
 grpc_cc_test(
@@ -68,14 +71,17 @@
 
 grpc_cc_test(
     name = "pid_controller_test",
-    srcs = ["pid_controller_test.c"],
-    language = "C",
+    srcs = ["pid_controller_test.cc"],
+    language = "C++",
     deps = [
         "//:gpr",
         "//:grpc",
         "//test/core/util:gpr_test_util",
         "//test/core/util:grpc_test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
 grpc_cc_test(
diff --git a/test/core/transport/bdp_estimator_test.c b/test/core/transport/bdp_estimator_test.c
deleted file mode 100644
index 4912ad5..0000000
--- a/test/core/transport/bdp_estimator_test.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- *
- * Copyright 2016 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "src/core/lib/transport/bdp_estimator.h"
-
-#include <grpc/grpc.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/iomgr/timer_manager.h"
-#include "src/core/lib/support/string.h"
-#include "test/core/util/test_config.h"
-
-extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
-
-static int g_clock = 0;
-
-static gpr_timespec fake_gpr_now(gpr_clock_type clock_type) {
-  return (gpr_timespec){
-      .tv_sec = g_clock, .tv_nsec = 0, .clock_type = clock_type,
-  };
-}
-
-static void inc_time(void) { g_clock += 30; }
-
-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) {
-  grpc_bdp_estimator_add_incoming_bytes(estimator, 1234567);
-  inc_time();
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GPR_ASSERT(grpc_bdp_estimator_need_ping(&exec_ctx, estimator) == true);
-  grpc_bdp_estimator_schedule_ping(estimator);
-  grpc_bdp_estimator_start_ping(estimator);
-  for (size_t i = 0; i < n; i++) {
-    grpc_bdp_estimator_add_incoming_bytes(estimator, samples[i]);
-    GPR_ASSERT(grpc_bdp_estimator_need_ping(&exec_ctx, estimator) == false);
-  }
-  gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                               gpr_time_from_millis(1, GPR_TIMESPAN)));
-  grpc_bdp_estimator_complete_ping(&exec_ctx, estimator);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-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");
-  const int kMaxSample = 65535;
-  int min = kMaxSample;
-  int max = 0;
-  for (size_t i = 0; i < n; i++) {
-    int sample = rand() % (kMaxSample + 1);
-    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) <= GPR_MAX(65536, 2 * next_pow_2(max)));
-    }
-  }
-}
-
-int main(int argc, char **argv) {
-  grpc_test_init(argc, argv);
-  gpr_now_impl = fake_gpr_now;
-  grpc_init();
-  grpc_timer_manager_set_threading(false);
-  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);
-  }
-  grpc_shutdown();
-  return 0;
-}
diff --git a/test/core/transport/bdp_estimator_test.cc b/test/core/transport/bdp_estimator_test.cc
new file mode 100644
index 0000000..2c4fc45
--- /dev/null
+++ b/test/core/transport/bdp_estimator_test.cc
@@ -0,0 +1,149 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "src/core/lib/transport/bdp_estimator.h"
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+#include <gtest/gtest.h>
+#include <limits.h>
+#include "src/core/lib/iomgr/timer_manager.h"
+#include "src/core/lib/support/string.h"
+#include "test/core/util/test_config.h"
+
+extern "C" gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
+
+namespace grpc_core {
+namespace testing {
+namespace {
+int g_clock = 0;
+
+gpr_timespec fake_gpr_now(gpr_clock_type clock_type) {
+  gpr_timespec ts;
+  ts.tv_sec = g_clock;
+  ts.tv_nsec = 0;
+  ts.clock_type = clock_type;
+  return ts;
+}
+
+void inc_time(void) { g_clock += 30; }
+}  // namespace
+
+TEST(BdpEstimatorTest, NoOp) { BdpEstimator est("test"); }
+
+TEST(BdpEstimatorTest, EstimateBdpNoSamples) {
+  BdpEstimator est("test");
+  est.EstimateBdp();
+}
+
+namespace {
+void AddSamples(BdpEstimator *estimator, int64_t *samples, size_t n) {
+  estimator->AddIncomingBytes(1234567);
+  inc_time();
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  estimator->SchedulePing();
+  estimator->StartPing();
+  for (size_t i = 0; i < n; i++) {
+    estimator->AddIncomingBytes(samples[i]);
+  }
+  gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                               gpr_time_from_millis(1, GPR_TIMESPAN)));
+  grpc_exec_ctx_invalidate_now(&exec_ctx);
+  estimator->CompletePing(&exec_ctx);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+void AddSample(BdpEstimator *estimator, int64_t sample) {
+  AddSamples(estimator, &sample, 1);
+}
+}  // namespace
+
+TEST(BdpEstimatorTest, GetEstimate1Sample) {
+  BdpEstimator est("test");
+  AddSample(&est, 100);
+  est.EstimateBdp();
+}
+
+TEST(BdpEstimatorTest, GetEstimate2Samples) {
+  BdpEstimator est("test");
+  AddSample(&est, 100);
+  AddSample(&est, 100);
+  est.EstimateBdp();
+}
+
+TEST(BdpEstimatorTest, GetEstimate3Samples) {
+  BdpEstimator est("test");
+  AddSample(&est, 100);
+  AddSample(&est, 100);
+  AddSample(&est, 100);
+  est.EstimateBdp();
+}
+
+namespace {
+int64_t NextPow2(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;
+}
+}  // namespace
+
+class BdpEstimatorRandomTest : public ::testing::TestWithParam<size_t> {};
+
+TEST_P(BdpEstimatorRandomTest, GetEstimateRandomValues) {
+  BdpEstimator est("test");
+  const int kMaxSample = 65535;
+  int min = kMaxSample;
+  int max = 0;
+  for (size_t i = 0; i < GetParam(); i++) {
+    int sample = rand() % (kMaxSample + 1);
+    if (sample < min) min = sample;
+    if (sample > max) max = sample;
+    AddSample(&est, sample);
+    if (i >= 3) {
+      EXPECT_LE(est.EstimateBdp(), GPR_MAX(65536, 2 * NextPow2(max)))
+          << " min:" << min << " max:" << max << " sample:" << sample;
+    }
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(TooManyNames, BdpEstimatorRandomTest,
+                        ::testing::Values(3, 4, 6, 9, 13, 19, 28, 42, 63, 94,
+                                          141, 211, 316, 474, 711));
+
+}  // namespace testing
+}  // namespace grpc_core
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+  gpr_now_impl = grpc_core::testing::fake_gpr_now;
+  grpc_init();
+  grpc_timer_manager_set_threading(false);
+  ::testing::InitGoogleTest(&argc, argv);
+  int ret = RUN_ALL_TESTS();
+  grpc_shutdown();
+  return ret;
+}
diff --git a/test/core/transport/chttp2/hpack_encoder_test.c b/test/core/transport/chttp2/hpack_encoder_test.c
index ed51dd1..a2af83b 100644
--- a/test/core/transport/chttp2/hpack_encoder_test.c
+++ b/test/core/transport/chttp2/hpack_encoder_test.c
@@ -43,10 +43,15 @@
 size_t num_to_delete = 0;
 size_t cap_to_delete = 0;
 
+typedef struct {
+  bool eof;
+  bool use_true_binary_metadata;
+  bool only_intern_key;
+} verify_params;
+
 /* verify that the output generated by encoding the stream matches the
    hexstring passed in */
-static void verify(grpc_exec_ctx *exec_ctx, size_t window_available, bool eof,
-                   bool use_true_binary_metadata, size_t expect_window_used,
+static void verify(grpc_exec_ctx *exec_ctx, const verify_params params,
                    const char *expected, size_t nheaders, ...) {
   grpc_slice_buffer output;
   grpc_slice merged;
@@ -66,9 +71,13 @@
       e[i - 1].next = &e[i];
       e[i].prev = &e[i - 1];
     }
+    grpc_slice value_slice = grpc_slice_from_static_string(value);
+    if (!params.only_intern_key) {
+      value_slice = grpc_slice_intern(value_slice);
+    }
     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)));
+        value_slice);
   }
   e[0].prev = NULL;
   e[nheaders - 1].next = NULL;
@@ -90,8 +99,8 @@
   memset(&stats, 0, sizeof(stats));
   grpc_encode_header_options hopt = {
       .stream_id = 0xdeadbeef,
-      .is_eof = eof,
-      .use_true_binary_metadata = use_true_binary_metadata,
+      .is_eof = params.eof,
+      .use_true_binary_metadata = params.use_true_binary_metadata,
       .max_frame_size = 16384,
       .stats = &stats,
   };
@@ -119,28 +128,27 @@
 static void test_basic_headers(grpc_exec_ctx *exec_ctx) {
   int i;
 
-  verify(exec_ctx, 0, false, false, 0, "000005 0104 deadbeef 40 0161 0161", 1,
-         "a", "a");
-  verify(exec_ctx, 0, false, false, 0, "000001 0104 deadbeef be", 1, "a", "a");
-  verify(exec_ctx, 0, false, false, 0, "000001 0104 deadbeef be", 1, "a", "a");
-  verify(exec_ctx, 0, false, false, 0, "000006 0104 deadbeef be 40 0162 0163",
-         2, "a", "a", "b", "c");
-  verify(exec_ctx, 0, false, false, 0, "000002 0104 deadbeef bf be", 2, "a",
-         "a", "b", "c");
-  verify(exec_ctx, 0, false, false, 0, "000004 0104 deadbeef 7f 00 0164", 1,
-         "a", "d");
+  verify_params params = {
+      .eof = false, .use_true_binary_metadata = false, .only_intern_key = false,
+  };
+  verify(exec_ctx, params, "000005 0104 deadbeef 40 0161 0161", 1, "a", "a");
+  verify(exec_ctx, params, "000001 0104 deadbeef be", 1, "a", "a");
+  verify(exec_ctx, params, "000001 0104 deadbeef be", 1, "a", "a");
+  verify(exec_ctx, params, "000006 0104 deadbeef be 40 0162 0163", 2, "a", "a",
+         "b", "c");
+  verify(exec_ctx, params, "000002 0104 deadbeef bf be", 2, "a", "a", "b", "c");
+  verify(exec_ctx, params, "000004 0104 deadbeef 7f 00 0164", 1, "a", "d");
 
   /* flush out what's there to make a few values look very popular */
   for (i = 0; i < 350; i++) {
-    verify(exec_ctx, 0, false, false, 0, "000003 0104 deadbeef c0 bf be", 3,
-           "a", "a", "b", "c", "a", "d");
+    verify(exec_ctx, params, "000003 0104 deadbeef c0 bf be", 3, "a", "a", "b",
+           "c", "a", "d");
   }
 
-  verify(exec_ctx, 0, false, false, 0, "000006 0104 deadbeef c0 00 016b 0176",
-         2, "a", "a", "k", "v");
+  verify(exec_ctx, params, "000006 0104 deadbeef c0 00 016b 0176", 2, "a", "a",
+         "k", "v");
   /* this could be 000004 0104 deadbeef 0f 30 0176 also */
-  verify(exec_ctx, 0, false, false, 0, "000004 0104 deadbeef 0f 2f 0176", 1,
-         "a", "v");
+  verify(exec_ctx, params, "000004 0104 deadbeef 0f 2f 0176", 1, "a", "v");
 }
 
 static void encode_int_to_str(int i, char *p) {
@@ -156,6 +164,10 @@
   char key[3], value[3];
   char *expect;
 
+  verify_params params = {
+      .eof = false, .use_true_binary_metadata = false, .only_intern_key = false,
+  };
+
   for (i = 0; i < 114; i++) {
     encode_int_to_str(i, key);
     encode_int_to_str(i + 1, value);
@@ -174,27 +186,28 @@
     }
 
     if (i > 0) {
-      verify(exec_ctx, 0, false, false, 0, expect, 2, "aa", "ba", key, value);
+      verify(exec_ctx, params, expect, 2, "aa", "ba", key, value);
     } else {
-      verify(exec_ctx, 0, false, false, 0, expect, 1, key, value);
+      verify(exec_ctx, params, expect, 1, key, value);
     }
     gpr_free(expect);
   }
 
   /* if the above passes, then we must have just knocked this pair out of the
      decoder stack, and so we'll be forced to re-encode it */
-  verify(exec_ctx, 0, false, false, 0, "000007 0104 deadbeef 40 026161 026261",
-         1, "aa", "ba");
+  verify(exec_ctx, params, "000007 0104 deadbeef 40 026161 026261", 1, "aa",
+         "ba");
 }
 
 static void verify_table_size_change_match_elem_size(grpc_exec_ctx *exec_ctx,
                                                      const char *key,
-                                                     const char *value) {
+                                                     const char *value,
+                                                     bool use_true_binary) {
   grpc_slice_buffer output;
   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 elem_size = grpc_mdelem_get_size_in_hpack_table(elem, use_true_binary);
   size_t initial_table_size = g_compressor.table_size;
   grpc_linked_mdelem *e = gpr_malloc(sizeof(*e));
   grpc_metadata_batch b;
@@ -209,11 +222,12 @@
 
   grpc_transport_one_way_stats stats;
   memset(&stats, 0, sizeof(stats));
-  grpc_encode_header_options hopt = {.stream_id = 0xdeadbeef,
-                                     .is_eof = false,
-                                     .use_true_binary_metadata = false,
-                                     .max_frame_size = 16384,
-                                     .stats = &stats};
+  grpc_encode_header_options hopt = {
+      .stream_id = 0xdeadbeef,
+      .is_eof = false,
+      .use_true_binary_metadata = use_true_binary,
+      .max_frame_size = 16384,
+      .stats = &stats};
   grpc_chttp2_encode_header(exec_ctx, &g_compressor, NULL, 0, &b, &hopt,
                             &output);
   grpc_slice_buffer_destroy_internal(exec_ctx, &output);
@@ -224,8 +238,24 @@
 }
 
 static void test_encode_header_size(grpc_exec_ctx *exec_ctx) {
-  verify_table_size_change_match_elem_size(exec_ctx, "hello", "world");
-  verify_table_size_change_match_elem_size(exec_ctx, "hello-bin", "world");
+  verify_table_size_change_match_elem_size(exec_ctx, "hello", "world", false);
+  verify_table_size_change_match_elem_size(exec_ctx, "hello-bin", "world",
+                                           false);
+  verify_table_size_change_match_elem_size(exec_ctx, "true-binary-bin",
+                                           "I_am_true_binary_value", true);
+}
+
+static void test_interned_key_indexed(grpc_exec_ctx *exec_ctx) {
+  int i;
+  verify_params params = {
+      .eof = false, .use_true_binary_metadata = false, .only_intern_key = true,
+  };
+  verify(exec_ctx, params, "000009 0104 deadbeef 40 0161 0162 0f2f 0163", 2,
+         "a", "b", "a", "c");
+  for (i = 0; i < 10; i++) {
+    verify(exec_ctx, params, "000008 0104 deadbeef 0f2f 0162 0f2f 0163", 2, "a",
+           "b", "a", "c");
+  }
 }
 
 static void run_test(void (*test)(grpc_exec_ctx *exec_ctx), const char *name) {
@@ -245,6 +275,7 @@
   TEST(test_basic_headers);
   TEST(test_decode_table_overflow);
   TEST(test_encode_header_size);
+  TEST(test_interned_key_indexed);
   grpc_shutdown();
   for (i = 0; i < num_to_delete; i++) {
     gpr_free(to_delete[i]);
diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c
index cb06fce..f7124d2 100644
--- a/test/core/transport/metadata_test.c
+++ b/test/core/transport/metadata_test.c
@@ -302,7 +302,7 @@
   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 elem_size = grpc_mdelem_get_size_in_hpack_table(elem, false);
   size_t expected_size = 32 + strlen(key) + strlen(value);
   GPR_ASSERT(expected_size == elem_size);
   GRPC_MDELEM_UNREF(exec_ctx, elem);
@@ -316,7 +316,7 @@
       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);
+  size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem, false);
   grpc_slice value_slice =
       grpc_slice_from_copied_buffer((const char *)value, value_len);
   grpc_slice base64_encoded = grpc_chttp2_base64_encode(value_slice);
diff --git a/test/core/transport/pid_controller_test.c b/test/core/transport/pid_controller_test.c
deleted file mode 100644
index 831c4b4..0000000
--- a/test/core/transport/pid_controller_test.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *
- * Copyright 2016 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "src/core/lib/transport/pid_controller.h"
-
-#include <float.h>
-#include <math.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/support/string.h"
-#include "test/core/util/test_config.h"
-
-static void test_noop(void) {
-  gpr_log(GPR_INFO, "test_noop");
-  grpc_pid_controller pid;
-  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,
-                                    double dt, double set_point, double start) {
-  gpr_log(GPR_INFO,
-          "test_simple_convergence(p=%lf, i=%lf, d=%lf); dt=%lf set_point=%lf "
-          "start=%lf",
-          gain_p, gain_i, gain_d, dt, set_point, start);
-  grpc_pid_controller pid;
-  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});
-
-  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 - 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) {
-  grpc_test_init(argc, argv);
-  test_noop();
-  test_simple_convergence(0.2, 0, 0, 1, 100, 0);
-  test_simple_convergence(0.2, 0.1, 0, 1, 100, 0);
-  test_simple_convergence(0.2, 0.1, 0.1, 1, 100, 0);
-  return 0;
-}
diff --git a/test/core/transport/pid_controller_test.cc b/test/core/transport/pid_controller_test.cc
new file mode 100644
index 0000000..081d034
--- /dev/null
+++ b/test/core/transport/pid_controller_test.cc
@@ -0,0 +1,91 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "src/core/lib/transport/pid_controller.h"
+
+#include <float.h>
+#include <math.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+#include <gtest/gtest.h>
+#include "src/core/lib/support/string.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc_core {
+namespace testing {
+
+TEST(PidController, NoOp) {
+  PidController pid(PidController::Args()
+                        .set_gain_p(1)
+                        .set_gain_i(1)
+                        .set_gain_d(1)
+                        .set_initial_control_value(1));
+}
+
+struct SimpleConvergenceTestArgs {
+  double gain_p;
+  double gain_i;
+  double gain_d;
+  double dt;
+  double set_point;
+  double start;
+};
+
+std::ostream& operator<<(std::ostream& out, SimpleConvergenceTestArgs args) {
+  return out << "gain_p:" << args.gain_p << " gain_i:" << args.gain_i
+             << " gain_d:" << args.gain_d << " dt:" << args.dt
+             << " set_point:" << args.set_point << " start:" << args.start;
+}
+
+class SimpleConvergenceTest
+    : public ::testing::TestWithParam<SimpleConvergenceTestArgs> {};
+
+TEST_P(SimpleConvergenceTest, Converges) {
+  PidController pid(PidController::Args()
+                        .set_gain_p(GetParam().gain_p)
+                        .set_gain_i(GetParam().gain_i)
+                        .set_gain_d(GetParam().gain_d)
+                        .set_initial_control_value(GetParam().start));
+
+  for (int i = 0; i < 100000; i++) {
+    pid.Update(GetParam().set_point - pid.last_control_value(), GetParam().dt);
+  }
+
+  EXPECT_LT(fabs(GetParam().set_point - pid.last_control_value()), 0.1);
+  if (GetParam().gain_i > 0) {
+    EXPECT_LT(fabs(pid.error_integral()), 0.1);
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(
+    X, SimpleConvergenceTest,
+    ::testing::Values(SimpleConvergenceTestArgs{0.2, 0, 0, 1, 100, 0},
+                      SimpleConvergenceTestArgs{0.2, 0.1, 0, 1, 100, 0},
+                      SimpleConvergenceTestArgs{0.2, 0.1, 0.1, 1, 100, 0}));
+
+}  // namespace testing
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  grpc_test_init(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/core/util/BUILD b/test/core/util/BUILD
index abb50a0..5844a17 100644
--- a/test/core/util/BUILD
+++ b/test/core/util/BUILD
@@ -32,9 +32,22 @@
 )
 
 grpc_cc_library(
+    name = "grpc_debugger_macros",
+    srcs = [
+        "debugger_macros.cc",
+    ],
+    hdrs = [
+        "debugger_macros.h",
+    ],
+    deps = [
+        ":gpr_test_util",
+        "//:grpc_common",
+    ],
+)
+
+grpc_cc_library(
     name = "grpc_test_util_base",
     srcs = [
-        "debugger_macros.c",
         "grpc_profiler.c",
         "mock_endpoint.c",
         "parse_hexstring.c",
@@ -47,7 +60,6 @@
         "trickle_endpoint.c",
     ],
     hdrs = [
-        "debugger_macros.h",
         "grpc_profiler.h",
         "mock_endpoint.h",
         "parse_hexstring.h",
@@ -63,6 +75,7 @@
     deps = [
         ":gpr_test_util",
         "//:grpc_common",
+        ":grpc_debugger_macros"
     ],
 )
 
diff --git a/test/core/util/debugger_macros.c b/test/core/util/debugger_macros.cc
similarity index 96%
rename from test/core/util/debugger_macros.c
rename to test/core/util/debugger_macros.cc
index ebe74f1..72384f2 100644
--- a/test/core/util/debugger_macros.c
+++ b/test/core/util/debugger_macros.cc
@@ -29,7 +29,7 @@
 #include "src/core/lib/channel/connected_channel.h"
 #include "src/core/lib/surface/call.h"
 
-void grpc_summon_debugger_macros() {}
+extern "C" 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);
diff --git a/test/core/util/debugger_macros.h b/test/core/util/debugger_macros.h
index c6b3720..24718d9 100644
--- a/test/core/util/debugger_macros.h
+++ b/test/core/util/debugger_macros.h
@@ -19,6 +19,14 @@
 #ifndef GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H
 #define GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif /*  __cplusplus */
+
 void grpc_summon_debugger_macros();
 
+#ifdef __cplusplus
+}
+#endif /*  __cplusplus */
+
 #endif /* GRPC_TEST_CORE_UTIL_DEBUGGER_MACROS_H */
diff --git a/test/core/util/mock_endpoint.c b/test/core/util/mock_endpoint.c
index bd386b2..7cae5c0 100644
--- a/test/core/util/mock_endpoint.c
+++ b/test/core/util/mock_endpoint.c
@@ -69,6 +69,10 @@
 static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                                   grpc_pollset_set *pollset) {}
 
+static void me_delete_from_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,
                         grpc_error *why) {
   grpc_mock_endpoint *m = (grpc_mock_endpoint *)ep;
@@ -103,8 +107,15 @@
 static int me_get_fd(grpc_endpoint *ep) { return -1; }
 
 static const grpc_endpoint_vtable vtable = {
-    me_read,     me_write,   me_add_to_pollset,    me_add_to_pollset_set,
-    me_shutdown, me_destroy, me_get_resource_user, me_get_peer,
+    me_read,
+    me_write,
+    me_add_to_pollset,
+    me_add_to_pollset_set,
+    me_delete_from_pollset_set,
+    me_shutdown,
+    me_destroy,
+    me_get_resource_user,
+    me_get_peer,
     me_get_fd,
 };
 
diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c
index 38a4758..1bf2888 100644
--- a/test/core/util/passthru_endpoint.c
+++ b/test/core/util/passthru_endpoint.c
@@ -107,6 +107,10 @@
 static void me_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                                   grpc_pollset_set *pollset) {}
 
+static void me_delete_from_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,
                         grpc_error *why) {
   half *m = (half *)ep;
@@ -160,8 +164,15 @@
 }
 
 static const grpc_endpoint_vtable vtable = {
-    me_read,     me_write,   me_add_to_pollset,    me_add_to_pollset_set,
-    me_shutdown, me_destroy, me_get_resource_user, me_get_peer,
+    me_read,
+    me_write,
+    me_add_to_pollset,
+    me_add_to_pollset_set,
+    me_delete_from_pollset_set,
+    me_shutdown,
+    me_destroy,
+    me_get_resource_user,
+    me_get_peer,
     me_get_fd,
 };
 
diff --git a/test/core/util/trickle_endpoint.c b/test/core/util/trickle_endpoint.c
index fc066f9..d761f72 100644
--- a/test/core/util/trickle_endpoint.c
+++ b/test/core/util/trickle_endpoint.c
@@ -89,6 +89,13 @@
   grpc_endpoint_add_to_pollset_set(exec_ctx, te->wrapped, pollset_set);
 }
 
+static void te_delete_from_pollset_set(grpc_exec_ctx *exec_ctx,
+                                       grpc_endpoint *ep,
+                                       grpc_pollset_set *pollset_set) {
+  trickle_endpoint *te = (trickle_endpoint *)ep;
+  grpc_endpoint_delete_from_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;
@@ -135,10 +142,16 @@
   gpr_mu_unlock(&te->mu);
 }
 
-static const grpc_endpoint_vtable vtable = {
-    te_read,     te_write,   te_add_to_pollset,    te_add_to_pollset_set,
-    te_shutdown, te_destroy, te_get_resource_user, te_get_peer,
-    te_get_fd};
+static const grpc_endpoint_vtable vtable = {te_read,
+                                            te_write,
+                                            te_add_to_pollset,
+                                            te_add_to_pollset_set,
+                                            te_delete_from_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) {
diff --git a/test/core/util/trickle_endpoint.h b/test/core/util/trickle_endpoint.h
index 78f1eee..ca39638 100644
--- a/test/core/util/trickle_endpoint.h
+++ b/test/core/util/trickle_endpoint.h
@@ -21,6 +21,10 @@
 
 #include "src/core/lib/iomgr/endpoint.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
 grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap,
                                             double bytes_per_second);
 
@@ -30,4 +34,8 @@
 
 size_t grpc_trickle_get_backlog(grpc_endpoint *endpoint);
 
+#ifdef __cplusplus
+}
+#endif  // __cplusplus
+
 #endif
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index f938aea..2a33e8a 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -102,14 +102,23 @@
   explicit Verifier(bool spin) : spin_(spin) {}
   // Expect sets the expected ok value for a specific tag
   Verifier& Expect(int i, bool expect_ok) {
-    expectations_[tag(i)] = expect_ok;
+    return ExpectUnless(i, expect_ok, false);
+  }
+  // ExpectUnless sets the expected ok value for a specific tag
+  // unless the tag was already marked seen (as a result of ExpectMaybe)
+  Verifier& ExpectUnless(int i, bool expect_ok, bool seen) {
+    if (!seen) {
+      expectations_[tag(i)] = expect_ok;
+    }
     return *this;
   }
-  // AcceptOnce sets the expected ok value for a specific tag, but does not
+  // ExpectMaybe sets the expected ok value for a specific tag, but does not
   // require it to appear
   // If it does, sets *seen to true
-  Verifier& AcceptOnce(int i, bool expect_ok, bool* seen) {
-    maybe_expectations_[tag(i)] = MaybeExpect{expect_ok, seen};
+  Verifier& ExpectMaybe(int i, bool expect_ok, bool* seen) {
+    if (!*seen) {
+      maybe_expectations_[tag(i)] = MaybeExpect{expect_ok, seen};
+    }
     return *this;
   }
 
@@ -569,13 +578,13 @@
 
   Verifier(GetParam().disable_blocking)
       .Expect(2, true)
-      .AcceptOnce(3, true, &seen3)
+      .ExpectMaybe(3, true, &seen3)
       .Verify(cq_.get());
 
   srv_stream.Read(&recv_request, tag(4));
 
   Verifier(GetParam().disable_blocking)
-      .AcceptOnce(3, true, &seen3)
+      .ExpectUnless(3, true, seen3)
       .Expect(4, true)
       .Verify(cq_.get());
 
@@ -602,7 +611,6 @@
 
   EXPECT_EQ(send_response.message(), recv_response.message());
   EXPECT_TRUE(recv_status.ok());
-  EXPECT_TRUE(seen3);
 }
 
 // One ping, two pongs.
@@ -853,13 +861,13 @@
 
   Verifier(GetParam().disable_blocking)
       .Expect(2, true)
-      .AcceptOnce(3, true, &seen3)
+      .ExpectMaybe(3, true, &seen3)
       .Verify(cq_.get());
 
   srv_stream.Read(&recv_request, tag(4));
 
   Verifier(GetParam().disable_blocking)
-      .AcceptOnce(3, true, &seen3)
+      .ExpectUnless(3, true, seen3)
       .Expect(4, true)
       .Verify(cq_.get());
   EXPECT_EQ(send_request.message(), recv_request.message());
@@ -880,7 +888,6 @@
   Verifier(GetParam().disable_blocking).Expect(8, true).Verify(cq_.get());
 
   EXPECT_TRUE(recv_status.ok());
-  EXPECT_TRUE(seen3);
 }
 
 // One ping, one pong. Using server:WriteLast api
@@ -910,13 +917,13 @@
 
   Verifier(GetParam().disable_blocking)
       .Expect(2, true)
-      .AcceptOnce(3, true, &seen3)
+      .ExpectMaybe(3, true, &seen3)
       .Verify(cq_.get());
 
   srv_stream.Read(&recv_request, tag(4));
 
   Verifier(GetParam().disable_blocking)
-      .AcceptOnce(3, true, &seen3)
+      .ExpectUnless(3, true, seen3)
       .Expect(4, true)
       .Verify(cq_.get());
   EXPECT_EQ(send_request.message(), recv_request.message());
@@ -939,7 +946,6 @@
   Verifier(GetParam().disable_blocking).Expect(9, true).Verify(cq_.get());
 
   EXPECT_TRUE(recv_status.ok());
-  EXPECT_TRUE(seen3);
 }
 
 // Metadata tests
@@ -1298,7 +1304,6 @@
       ServerTryCancelRequestPhase server_try_cancel) {
     ResetStub();
 
-    EchoRequest send_request;
     EchoRequest recv_request;
     EchoResponse send_response;
     EchoResponse recv_response;
@@ -1309,31 +1314,24 @@
     ServerAsyncReader<EchoResponse, EchoRequest> srv_stream(&srv_ctx);
 
     // Initiate the 'RequestStream' call on client
+    CompletionQueue cli_cq;
+
     std::unique_ptr<ClientAsyncWriter<EchoRequest>> cli_stream(
-        stub_->AsyncRequestStream(&cli_ctx, &recv_response, cq_.get(), tag(1)));
-    Verifier(GetParam().disable_blocking).Expect(1, true).Verify(cq_.get());
+        stub_->AsyncRequestStream(&cli_ctx, &recv_response, &cli_cq, tag(1)));
 
     // On the server, request to be notified of 'RequestStream' calls
     // and receive the 'RequestStream' call just made by the client
     srv_ctx.AsyncNotifyWhenDone(tag(11));
     service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
                                    tag(2));
+    std::thread t1([this, &cli_cq] {
+      Verifier(GetParam().disable_blocking).Expect(1, true).Verify(&cli_cq);
+    });
     Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
-
-    // Client sends 3 messages (tags 3, 4 and 5)
-    for (int tag_idx = 3; tag_idx <= 5; tag_idx++) {
-      send_request.set_message("Ping " + grpc::to_string(tag_idx));
-      cli_stream->Write(send_request, tag(tag_idx));
-      Verifier(GetParam().disable_blocking)
-          .Expect(tag_idx, true)
-          .Verify(cq_.get());
-    }
-    cli_stream->WritesDone(tag(6));
-    Verifier(GetParam().disable_blocking).Expect(6, true).Verify(cq_.get());
+    t1.join();
 
     bool expected_server_cq_result = true;
-    bool ignore_cq_result = false;
-    bool want_done_tag = false;
+    bool expected_client_cq_result = true;
 
     if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
       srv_ctx.TryCancel();
@@ -1341,10 +1339,36 @@
       EXPECT_TRUE(srv_ctx.IsCancelled());
 
       // Since cancellation is done before server reads any results, we know
-      // for sure that all cq results will return false from this point forward
+      // for sure that all server cq results will return false from this
+      // point forward
       expected_server_cq_result = false;
+      expected_client_cq_result = false;
     }
 
+    bool ignore_client_cq_result =
+        (server_try_cancel == CANCEL_DURING_PROCESSING) ||
+        (server_try_cancel == CANCEL_BEFORE_PROCESSING);
+
+    std::thread cli_thread([&cli_cq, &cli_stream, &expected_client_cq_result,
+                            &ignore_client_cq_result, this] {
+      EchoRequest send_request;
+      // Client sends 3 messages (tags 3, 4 and 5)
+      for (int tag_idx = 3; tag_idx <= 5; tag_idx++) {
+        send_request.set_message("Ping " + grpc::to_string(tag_idx));
+        cli_stream->Write(send_request, tag(tag_idx));
+        Verifier(GetParam().disable_blocking)
+            .Expect(tag_idx, expected_client_cq_result)
+            .Verify(&cli_cq, ignore_client_cq_result);
+      }
+      cli_stream->WritesDone(tag(6));
+      // Ignore ok on WritesDone since cancel can affect it
+      Verifier(GetParam().disable_blocking)
+          .Expect(6, expected_client_cq_result)
+          .Verify(&cli_cq, ignore_client_cq_result);
+    });
+
+    bool ignore_cq_result = false;
+    bool want_done_tag = false;
     std::thread* server_try_cancel_thd = nullptr;
 
     auto verif = Verifier(GetParam().disable_blocking);
@@ -1381,6 +1405,8 @@
       }
     }
 
+    cli_thread.join();
+
     if (server_try_cancel_thd != nullptr) {
       server_try_cancel_thd->join();
       delete server_try_cancel_thd;
@@ -1409,9 +1435,15 @@
 
     // Client will see the cancellation
     cli_stream->Finish(&recv_status, tag(10));
-    Verifier(GetParam().disable_blocking).Expect(10, true).Verify(cq_.get());
+    Verifier(GetParam().disable_blocking).Expect(10, true).Verify(&cli_cq);
     EXPECT_FALSE(recv_status.ok());
     EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code());
+
+    cli_cq.Shutdown();
+    void* dummy_tag;
+    bool dummy_ok;
+    while (cli_cq.Next(&dummy_tag, &dummy_ok)) {
+    }
   }
 
   // Helper for testing server-streaming RPCs which are cancelled on the server.
@@ -1433,7 +1465,6 @@
     EchoRequest send_request;
     EchoRequest recv_request;
     EchoResponse send_response;
-    EchoResponse recv_response;
     Status recv_status;
     ClientContext cli_ctx;
     ServerContext srv_ctx;
@@ -1441,20 +1472,29 @@
 
     send_request.set_message("Ping");
     // Initiate the 'ResponseStream' call on the client
+    CompletionQueue cli_cq;
     std::unique_ptr<ClientAsyncReader<EchoResponse>> cli_stream(
-        stub_->AsyncResponseStream(&cli_ctx, send_request, cq_.get(), tag(1)));
-    Verifier(GetParam().disable_blocking).Expect(1, true).Verify(cq_.get());
+        stub_->AsyncResponseStream(&cli_ctx, send_request, &cli_cq, tag(1)));
     // On the server, request to be notified of 'ResponseStream' calls and
     // receive the call just made by the client
     srv_ctx.AsyncNotifyWhenDone(tag(11));
     service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
                                     cq_.get(), cq_.get(), tag(2));
+
+    std::thread t1([this, &cli_cq] {
+      Verifier(GetParam().disable_blocking).Expect(1, true).Verify(&cli_cq);
+    });
     Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
+    t1.join();
+
     EXPECT_EQ(send_request.message(), recv_request.message());
 
     bool expected_cq_result = true;
     bool ignore_cq_result = false;
     bool want_done_tag = false;
+    bool expected_client_cq_result = true;
+    bool ignore_client_cq_result =
+        (server_try_cancel != CANCEL_BEFORE_PROCESSING);
 
     if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
       srv_ctx.TryCancel();
@@ -1464,8 +1504,21 @@
       // We know for sure that all cq results will be false from this point
       // since the server cancelled the RPC
       expected_cq_result = false;
+      expected_client_cq_result = false;
     }
 
+    std::thread cli_thread([&cli_cq, &cli_stream, &expected_client_cq_result,
+                            &ignore_client_cq_result, this] {
+      // Client attempts to read the three messages from the server
+      for (int tag_idx = 6; tag_idx <= 8; tag_idx++) {
+        EchoResponse recv_response;
+        cli_stream->Read(&recv_response, tag(tag_idx));
+        Verifier(GetParam().disable_blocking)
+            .Expect(tag_idx, expected_client_cq_result)
+            .Verify(&cli_cq, ignore_client_cq_result);
+      }
+    });
+
     std::thread* server_try_cancel_thd = nullptr;
 
     auto verif = Verifier(GetParam().disable_blocking);
@@ -1513,10 +1566,6 @@
       srv_ctx.TryCancel();
       want_done_tag = true;
       verif.Expect(11, true);
-
-      // Client reads may fail bacause it is notified that the stream is
-      // cancelled.
-      ignore_cq_result = true;
     }
 
     if (want_done_tag) {
@@ -1525,13 +1574,7 @@
       want_done_tag = false;
     }
 
-    // Client attemts to read the three messages from the server
-    for (int tag_idx = 6; tag_idx <= 8; tag_idx++) {
-      cli_stream->Read(&recv_response, tag(tag_idx));
-      Verifier(GetParam().disable_blocking)
-          .Expect(tag_idx, expected_cq_result)
-          .Verify(cq_.get(), ignore_cq_result);
-    }
+    cli_thread.join();
 
     // The RPC has been cancelled at this point for sure (i.e irrespective of
     // the value of `server_try_cancel` is). So, from this point forward, we
@@ -1543,9 +1586,15 @@
 
     // Client will see the cancellation
     cli_stream->Finish(&recv_status, tag(10));
-    Verifier(GetParam().disable_blocking).Expect(10, true).Verify(cq_.get());
+    Verifier(GetParam().disable_blocking).Expect(10, true).Verify(&cli_cq);
     EXPECT_FALSE(recv_status.ok());
     EXPECT_EQ(::grpc::StatusCode::CANCELLED, recv_status.error_code());
+
+    cli_cq.Shutdown();
+    void* dummy_tag;
+    bool dummy_ok;
+    while (cli_cq.Next(&dummy_tag, &dummy_ok)) {
+    }
   }
 
   // Helper for testing bidirectinal-streaming RPCs which are cancelled on the
@@ -1578,38 +1627,52 @@
     // Initiate the call from the client side
     std::unique_ptr<ClientAsyncReaderWriter<EchoRequest, EchoResponse>>
         cli_stream(stub_->AsyncBidiStream(&cli_ctx, cq_.get(), tag(1)));
-    Verifier(GetParam().disable_blocking).Expect(1, true).Verify(cq_.get());
 
     // On the server, request to be notified of the 'BidiStream' call and
     // receive the call just made by the client
     srv_ctx.AsyncNotifyWhenDone(tag(11));
     service_->RequestBidiStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
                                 tag(2));
-    Verifier(GetParam().disable_blocking).Expect(2, true).Verify(cq_.get());
+    Verifier(GetParam().disable_blocking)
+        .Expect(1, true)
+        .Expect(2, true)
+        .Verify(cq_.get());
+
+    auto verif = Verifier(GetParam().disable_blocking);
 
     // Client sends the first and the only message
     send_request.set_message("Ping");
     cli_stream->Write(send_request, tag(3));
-    Verifier(GetParam().disable_blocking).Expect(3, true).Verify(cq_.get());
+    verif.Expect(3, true);
 
     bool expected_cq_result = true;
     bool ignore_cq_result = false;
     bool want_done_tag = false;
 
+    int got_tag, got_tag2;
+    bool tag_3_done = false;
+
     if (server_try_cancel == CANCEL_BEFORE_PROCESSING) {
       srv_ctx.TryCancel();
-      Verifier(GetParam().disable_blocking).Expect(11, true).Verify(cq_.get());
-      EXPECT_TRUE(srv_ctx.IsCancelled());
-
-      // We know for sure that all cq results will be false from this point
-      // since the server cancelled the RPC
+      verif.Expect(11, true);
+      // We know for sure that all server cq results will be false from
+      // this point since the server cancelled the RPC. However, we can't
+      // say for sure about the client
       expected_cq_result = false;
+      ignore_cq_result = true;
+
+      do {
+        got_tag = verif.Next(cq_.get(), ignore_cq_result);
+        GPR_ASSERT(((got_tag == 3) && !tag_3_done) || (got_tag == 11));
+        if (got_tag == 3) {
+          tag_3_done = true;
+        }
+      } while (got_tag != 11);
+      EXPECT_TRUE(srv_ctx.IsCancelled());
     }
 
     std::thread* server_try_cancel_thd = nullptr;
 
-    auto verif = Verifier(GetParam().disable_blocking);
-
     if (server_try_cancel == CANCEL_DURING_PROCESSING) {
       server_try_cancel_thd =
           new std::thread(&ServerContext::TryCancel, &srv_ctx);
@@ -1624,39 +1687,42 @@
       verif.Expect(11, true);
     }
 
-    int got_tag;
     srv_stream.Read(&recv_request, tag(4));
     verif.Expect(4, expected_cq_result);
-    got_tag = verif.Next(cq_.get(), ignore_cq_result);
-    GPR_ASSERT((got_tag == 4) || (got_tag == 11 && want_done_tag));
-    if (got_tag == 11) {
+    got_tag = tag_3_done ? 3 : verif.Next(cq_.get(), ignore_cq_result);
+    got_tag2 = verif.Next(cq_.get(), ignore_cq_result);
+    GPR_ASSERT((got_tag == 3) || (got_tag == 4) ||
+               (got_tag == 11 && want_done_tag));
+    GPR_ASSERT((got_tag2 == 3) || (got_tag2 == 4) ||
+               (got_tag2 == 11 && want_done_tag));
+    // If we get 3 and 4, we don't need to wait for 11, but if
+    // we get 11, we should also clear 3 and 4
+    if (got_tag + got_tag2 != 7) {
       EXPECT_TRUE(srv_ctx.IsCancelled());
       want_done_tag = false;
-      // Now get the other entry that we were waiting on
-      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 4);
+      got_tag = verif.Next(cq_.get(), ignore_cq_result);
+      GPR_ASSERT((got_tag == 3) || (got_tag == 4));
     }
 
     send_response.set_message("Pong");
     srv_stream.Write(send_response, tag(5));
     verif.Expect(5, expected_cq_result);
-    got_tag = verif.Next(cq_.get(), ignore_cq_result);
-    GPR_ASSERT((got_tag == 5) || (got_tag == 11 && want_done_tag));
-    if (got_tag == 11) {
-      EXPECT_TRUE(srv_ctx.IsCancelled());
-      want_done_tag = false;
-      // Now get the other entry that we were waiting on
-      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 5);
-    }
 
     cli_stream->Read(&recv_response, tag(6));
     verif.Expect(6, expected_cq_result);
     got_tag = verif.Next(cq_.get(), ignore_cq_result);
-    GPR_ASSERT((got_tag == 6) || (got_tag == 11 && want_done_tag));
-    if (got_tag == 11) {
+    got_tag2 = verif.Next(cq_.get(), ignore_cq_result);
+    GPR_ASSERT((got_tag == 5) || (got_tag == 6) ||
+               (got_tag == 11 && want_done_tag));
+    GPR_ASSERT((got_tag2 == 5) || (got_tag2 == 6) ||
+               (got_tag2 == 11 && want_done_tag));
+    // If we get 5 and 6, we don't need to wait for 11, but if
+    // we get 11, we should also clear 5 and 6
+    if (got_tag + got_tag2 != 11) {
       EXPECT_TRUE(srv_ctx.IsCancelled());
       want_done_tag = false;
-      // Now get the other entry that we were waiting on
-      EXPECT_EQ(verif.Next(cq_.get(), ignore_cq_result), 6);
+      got_tag = verif.Next(cq_.get(), ignore_cq_result);
+      GPR_ASSERT((got_tag == 5) || (got_tag == 6));
     }
 
     // This is expected to succeed in all cases
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 810ee30..1aa547d 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -220,7 +220,8 @@
   End2endTest()
       : is_server_started_(false),
         kMaxMessageSize_(8192),
-        special_service_("special") {
+        special_service_("special"),
+        first_picked_port_(0) {
     GetParam().Log();
   }
 
@@ -229,10 +230,14 @@
       server_->Shutdown();
       if (proxy_server_) proxy_server_->Shutdown();
     }
+    if (first_picked_port_ > 0) {
+      grpc_recycle_unused_port(first_picked_port_);
+    }
   }
 
   void StartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) {
     int port = grpc_pick_unused_port_or_die();
+    first_picked_port_ = port;
     server_address_ << "127.0.0.1:" << port;
     // Setup server
     BuildAndStartServer(processor);
@@ -328,6 +333,7 @@
   TestServiceImpl special_service_;
   TestServiceImplDupPkg dup_pkg_service_;
   grpc::string user_agent_prefix_;
+  int first_picked_port_;
 };
 
 static void SendRpc(grpc::testing::EchoTestService::Stub* stub, int num_rpcs,
@@ -1280,6 +1286,8 @@
   EchoResponse response;
   request.set_message("Hello");
   request.mutable_param()->set_skip_cancelled_check(true);
+  // Let server sleep for 2 ms first to guarantee expiry
+  request.mutable_param()->set_server_sleep_us(2 * 1000);
 
   ClientContext context;
   std::chrono::system_clock::time_point deadline =
@@ -1407,6 +1415,10 @@
 }
 
 TEST_P(ProxyEnd2endTest, Peer) {
+  // Peer is not meaningful for inproc
+  if (GetParam().inproc) {
+    return;
+  }
   ResetStub();
   EchoRequest request;
   EchoResponse response;
@@ -1775,11 +1787,10 @@
     credentials_types.push_back(kInsecureCredentialsType);
   }
   GPR_ASSERT(!credentials_types.empty());
-  for (auto it = credentials_types.begin(); it != credentials_types.end();
-       ++it) {
-    scenarios.emplace_back(false, false, *it);
+  for (const auto& cred : credentials_types) {
+    scenarios.emplace_back(false, false, cred);
     if (use_proxy) {
-      scenarios.emplace_back(true, false, *it);
+      scenarios.emplace_back(true, false, cred);
     }
   }
   if (test_inproc && insec_ok()) {
@@ -1798,7 +1809,7 @@
 
 INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest,
                         ::testing::ValuesIn(CreateTestScenarios(true, true,
-                                                                true, false)));
+                                                                true, true)));
 
 INSTANTIATE_TEST_CASE_P(SecureEnd2end, SecureEnd2endTest,
                         ::testing::ValuesIn(CreateTestScenarios(false, false,
diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc
index f73a9c1..c370302 100644
--- a/test/cpp/end2end/grpclb_end2end_test.cc
+++ b/test/cpp/end2end/grpclb_end2end_test.cc
@@ -332,8 +332,7 @@
         num_backends_(num_backends),
         num_balancers_(num_balancers),
         client_load_reporting_interval_seconds_(
-            client_load_reporting_interval_seconds),
-        kRequestMessage_("Live long and prosper.") {}
+            client_load_reporting_interval_seconds) {}
 
   void SetUp() override {
     response_generator_ = grpc_fake_resolver_response_generator_create();
@@ -559,7 +558,6 @@
     std::unique_ptr<std::thread> thread_;
   };
 
-  const grpc::string kMessage_ = "Live long and prosper.";
   const grpc::string server_host_;
   const size_t num_backends_;
   const size_t num_balancers_;
@@ -571,7 +569,7 @@
   std::vector<ServerThread<BackendService>> backend_servers_;
   std::vector<ServerThread<BalancerService>> balancer_servers_;
   grpc_fake_resolver_response_generator* response_generator_;
-  const grpc::string kRequestMessage_;
+  const grpc::string kRequestMessage_ = "Live long and prosper.";
 };
 
 class SingleBalancerTest : public GrpclbEnd2endTest {
@@ -1086,7 +1084,7 @@
     } else {
       EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
                                << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kMessage_);
+      EXPECT_EQ(response.message(), kRequestMessage_);
     }
   }
   EXPECT_EQ(kNumRpcsPerAddress * num_of_drop_addresses, num_drops);
@@ -1210,7 +1208,7 @@
     } else {
       EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
                                << " message=" << status.error_message();
-      EXPECT_EQ(response.message(), kMessage_);
+      EXPECT_EQ(response.message(), kRequestMessage_);
     }
   }
   EXPECT_EQ(kNumRpcsPerAddress * num_of_drop_addresses, num_drops);
diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc
index 4fa98c2..e4f7c08 100644
--- a/test/cpp/end2end/test_service_impl.cc
+++ b/test/cpp/end2end/test_service_impl.cc
@@ -73,6 +73,14 @@
 
 Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request,
                              EchoResponse* response) {
+  // A bit of sleep to make sure that short deadline tests fail
+  if (request->has_param() && request->param().server_sleep_us() > 0) {
+    gpr_sleep_until(
+        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                     gpr_time_from_micros(request->param().server_sleep_us(),
+                                          GPR_TIMESPAN)));
+  }
+
   if (request->has_param() && request->param().server_die()) {
     gpr_log(GPR_ERROR, "The request should not reach application handler.");
     GPR_ASSERT(0);
diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
index adbfa4d..bc2157b 100644
--- a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
+++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
@@ -28,12 +28,22 @@
 #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"
+#include "src/core/lib/transport/timeout_encoding.h"
 }
 #include "test/cpp/microbenchmarks/helpers.h"
 #include "third_party/benchmark/include/benchmark/benchmark.h"
 
 auto &force_library_initialization = Library::get();
 
+static grpc_slice MakeSlice(std::vector<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;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // HPACK encoder
 //
@@ -52,6 +62,48 @@
 }
 BENCHMARK(BM_HpackEncoderInitDestroy);
 
+static void BM_HpackEncoderEncodeDeadline(benchmark::State &state) {
+  TrackCounters track_counters;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_millis saved_now = grpc_exec_ctx_now(&exec_ctx);
+
+  grpc_metadata_batch b;
+  grpc_metadata_batch_init(&b);
+  b.deadline = saved_now + 30 * 1000;
+
+  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_encode_header_options hopt = {
+        static_cast<uint32_t>(state.iterations()),
+        true,
+        false,
+        (size_t)1024,
+        &stats,
+    };
+    grpc_chttp2_encode_header(&exec_ctx, &c, NULL, 0, &b, &hopt, &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()));
+  track_counters.AddLabel(label.str());
+  track_counters.Finish(state);
+}
+BENCHMARK(BM_HpackEncoderEncodeDeadline);
+
 template <class Fixture>
 static void BM_HpackEncoderEncodeHeader(benchmark::State &state) {
   TrackCounters track_counters;
@@ -104,7 +156,7 @@
                                      static_cast<double>(state.iterations()))
         << " header_bytes/iter:" << (static_cast<double>(stats.header_bytes) /
                                      static_cast<double>(state.iterations()));
-  state.SetLabel(label.str());
+  track_counters.AddLabel(label.str());
   track_counters.Finish(state);
 }
 
@@ -220,6 +272,45 @@
   }
 };
 
+// This fixture reflects how initial metadata are sent by a production client,
+// with non-indexed :path and binary headers. The metadata here are the same as
+// the corresponding parser benchmark below.
+class MoreRepresentativeClientInitialMetadata {
+ public:
+  static constexpr bool kEnableTrueBinary = true;
+  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(
+                                    "/grpc.test.FooService/BarMethod"))),
+        grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY,
+                                grpc_slice_intern(grpc_slice_from_static_string(
+                                    "foo.test.google.fr:1234"))),
+        grpc_mdelem_from_slices(
+            exec_ctx, GRPC_MDSTR_GRPC_TRACE_BIN,
+            grpc_slice_from_static_string("\x00\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")),
+        grpc_mdelem_from_slices(
+            exec_ctx, GRPC_MDSTR_GRPC_TAGS_BIN,
+            grpc_slice_from_static_string("\x00\x01\x02\x03\x04\x05\x06\x07\x08"
+                                          "\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+                                          "\x10\x11\x12\x13")),
+        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 constexpr bool kEnableTrueBinary = true;
@@ -317,6 +408,9 @@
                    RepresentativeClientInitialMetadata)
     ->Args({0, 16384});
 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
+                   MoreRepresentativeClientInitialMetadata)
+    ->Args({0, 16384});
+BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
                    RepresentativeServerInitialMetadata)
     ->Args({0, 16384});
 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
@@ -348,7 +442,7 @@
   GRPC_MDELEM_UNREF(exec_ctx, md);
 }
 
-template <class Fixture>
+template <class Fixture, void (*OnHeader)(grpc_exec_ctx *, void *, grpc_mdelem)>
 static void BM_HpackParserParseHeader(benchmark::State &state) {
   TrackCounters track_counters;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -356,14 +450,16 @@
   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 = OnHeader;
   p.on_header_user_data = nullptr;
   for (auto slice : init_slices) {
-    grpc_chttp2_hpack_parser_parse(&exec_ctx, &p, slice);
+    GPR_ASSERT(GRPC_ERROR_NONE ==
+               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);
+      GPR_ASSERT(GRPC_ERROR_NONE ==
+                 grpc_chttp2_hpack_parser_parse(&exec_ctx, &p, slice));
     }
     grpc_exec_ctx_flush(&exec_ctx);
   }
@@ -376,15 +472,6 @@
 
 namespace hpack_parser_fixtures {
 
-static grpc_slice MakeSlice(std::vector<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 {}; }
@@ -572,6 +659,54 @@
   }
 };
 
+// This fixture reflects how initial metadata are sent by a production client,
+// with non-indexed :path and binary headers. The metadata here are the same as
+// the corresponding encoder benchmark above.
+class MoreRepresentativeClientInitialMetadata {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {MakeSlice(
+        {0x40, 0x07, ':',  's',  'c',  'h',  'e',  'm',  'e',  0x04, 'h',  't',
+         't',  'p',  0x40, 0x07, ':',  'm',  'e',  't',  'h',  'o',  'd',  0x04,
+         'P',  'O',  'S',  'T',  0x40, 0x05, ':',  'p',  'a',  't',  'h',  0x1f,
+         '/',  'g',  'r',  'p',  'c',  '.',  't',  'e',  's',  't',  '.',  'F',
+         'o',  'o',  'S',  'e',  'r',  'v',  'i',  'c',  'e',  '/',  'B',  'a',
+         'r',  'M',  'e',  't',  'h',  'o',  'd',  0x40, 0x0a, ':',  'a',  'u',
+         't',  'h',  'o',  'r',  'i',  't',  'y',  0x09, 'l',  'o',  'c',  'a',
+         'l',  'h',  'o',  's',  't',  0x40, 0x0e, 'g',  'r',  'p',  'c',  '-',
+         't',  'r',  'a',  'c',  'e',  '-',  'b',  'i',  'n',  0x31, 0x00, 0x01,
+         0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+         0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+         0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+         0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x40,
+         0x0d, 'g',  'r',  'p',  'c',  '-',  't',  'a',  'g',  's',  '-',  'b',
+         'i',  'n',  0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+         0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x40,
+         0x0c, 'c',  'o',  'n',  't',  'e',  'n',  't',  '-',  't',  'y',  'p',
+         'e',  0x10, 'a',  'p',  'p',  'l',  'i',  'c',  'a',  't',  'i',  'o',
+         'n',  '/',  'g',  'r',  'p',  'c',  0x40, 0x14, 'g',  'r',  'p',  'c',
+         '-',  'a',  'c',  'c',  'e',  'p',  't',  '-',  'e',  'n',  'c',  'o',
+         'd',  'i',  'n',  'g',  0x15, 'i',  'd',  'e',  'n',  't',  'i',  't',
+         'y',  ',',  'd',  'e',  'f',  'l',  'a',  't',  'e',  ',',  'g',  'z',
+         'i',  'p',  0x40, 0x02, 't',  'e',  0x08, 't',  'r',  'a',  'i',  'l',
+         'e',  'r',  's',  0x40, 0x0a, 'u',  's',  'e',  'r',  '-',  'a',  'g',
+         'e',  'n',  't',  0x22, 'b',  'a',  'd',  '-',  'c',  'l',  'i',  'e',
+         'n',  't',  ' ',  'g',  'r',  'p',  'c',  '-',  'c',  '/',  '0',  '.',
+         '1',  '2',  '.',  '0',  '.',  '0',  ' ',  '(',  'l',  'i',  'n',  'u',
+         'x',  ')'})};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    return {MakeSlice(
+        {0xc7, 0xc6, 0xc5, 0xc4, 0x7f, 0x04, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04,
+         0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+         0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
+         0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+         0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x7f, 0x03, 0x14, 0x00,
+         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+         0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0xc1, 0xc0, 0xbf, 0xbe})};
+  }
+};
+
 class RepresentativeServerInitialMetadata {
  public:
   static std::vector<grpc_slice> GetInitSlices() {
@@ -625,30 +760,97 @@
   }
 };
 
-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, NonIndexedBinaryElem<1, false>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, false>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, false>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, false>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, false>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, true>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, true>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, true>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, true>);
-BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, true>);
+static void free_timeout(void *p) { gpr_free(p); }
+
+// New implementation.
+static void OnHeaderNew(grpc_exec_ctx *exec_ctx, void *user_data,
+                        grpc_mdelem md) {
+  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
+    grpc_millis *cached_timeout =
+        static_cast<grpc_millis *>(grpc_mdelem_get_user_data(md, free_timeout));
+    grpc_millis timeout;
+    if (cached_timeout != NULL) {
+      timeout = *cached_timeout;
+    } else {
+      if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout)) {
+        char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
+        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
+        gpr_free(val);
+        timeout = GRPC_MILLIS_INF_FUTURE;
+      }
+      if (GRPC_MDELEM_IS_INTERNED(md)) {
+        /* not already parsed: parse it now, and store the
+         * result away */
+        cached_timeout = (grpc_millis *)gpr_malloc(sizeof(grpc_millis));
+        *cached_timeout = timeout;
+        grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
+      }
+    }
+    benchmark::DoNotOptimize(timeout);
+    GRPC_MDELEM_UNREF(exec_ctx, md);
+  } else {
+    GPR_ASSERT(0);
+  }
+}
+
+// Send the same deadline repeatedly
+class SameDeadline {
+ public:
+  static std::vector<grpc_slice> GetInitSlices() {
+    return {
+        grpc_slice_from_static_string("@\x0cgrpc-timeout\x03"
+                                      "30S")};
+  }
+  static std::vector<grpc_slice> GetBenchmarkSlices() {
+    // Use saved key and literal value.
+    return {MakeSlice({0x0f, 0x2f, 0x03, '3', '0', 'S'})};
+  }
+};
+
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, EmptyBatch, UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleStaticElem,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleStaticElem,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleStaticElem,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleInternedElem,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleInternedElem,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleInternedElem,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedElem, UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, false>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, false>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, false>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, false>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, false>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, true>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, true>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, true>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, true>,
+                   UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, true>,
+                   UnrefHeader);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   RepresentativeClientInitialMetadata);
+                   RepresentativeClientInitialMetadata, UnrefHeader);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   RepresentativeServerInitialMetadata);
+                   MoreRepresentativeClientInitialMetadata, UnrefHeader);
 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
-                   RepresentativeServerTrailingMetadata);
+                   RepresentativeServerInitialMetadata, UnrefHeader);
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
+                   RepresentativeServerTrailingMetadata, UnrefHeader);
+
+BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline, OnHeaderNew);
 
 }  // namespace hpack_parser_fixtures
 
diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
index 6f9dee7..e9f537f 100644
--- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc
+++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
@@ -26,14 +26,12 @@
 #include <memory>
 #include <queue>
 #include <sstream>
-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/iomgr/closure.h"
 #include "src/core/lib/iomgr/resource_quota.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/static_metadata.h"
-}
 #include "test/cpp/microbenchmarks/helpers.h"
 #include "third_party/benchmark/include/benchmark/benchmark.h"
 
@@ -46,10 +44,16 @@
 class DummyEndpoint : public grpc_endpoint {
  public:
   DummyEndpoint() {
-    static const grpc_endpoint_vtable my_vtable = {
-        read,     write,   add_to_pollset,    add_to_pollset_set,
-        shutdown, destroy, get_resource_user, get_peer,
-        get_fd};
+    static const grpc_endpoint_vtable my_vtable = {read,
+                                                   write,
+                                                   add_to_pollset,
+                                                   add_to_pollset_set,
+                                                   delete_from_pollset_set,
+                                                   shutdown,
+                                                   destroy,
+                                                   get_resource_user,
+                                                   get_peer,
+                                                   get_fd};
     grpc_endpoint::vtable = &my_vtable;
     ru_ = grpc_resource_user_create(Library::get().rq(), "dummy_endpoint");
   }
@@ -104,6 +108,10 @@
   static void add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                                  grpc_pollset_set *pollset) {}
 
+  static void delete_from_pollset_set(grpc_exec_ctx *exec_ctx,
+                                      grpc_endpoint *ep,
+                                      grpc_pollset_set *pollset) {}
+
   static void shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                        grpc_error *why) {
     grpc_resource_user_shutdown(exec_ctx,
@@ -430,9 +438,8 @@
           return;
         }
         // force outgoing window to be yuge
-        s->chttp2_stream()->flow_control.remote_window_delta =
-            1024 * 1024 * 1024;
-        f.chttp2_transport()->flow_control.remote_window = 1024 * 1024 * 1024;
+        s->chttp2_stream()->flow_control->TestOnlyForceHugeWindow();
+        f.chttp2_transport()->flow_control->TestOnlyForceHugeWindow();
         grpc_slice_buffer_stream_init(&send_stream, &send_buffer, 0);
         reset_op();
         op.on_complete = c.get();
@@ -562,22 +569,21 @@
   std::unique_ptr<Closure> drain_continue;
   grpc_slice recv_slice;
 
-  std::unique_ptr<Closure> c = MakeClosure([&](grpc_exec_ctx *exec_ctx,
-                                               grpc_error *error) {
-    if (!state.KeepRunning()) return;
-    // force outgoing window to be yuge
-    s.chttp2_stream()->flow_control.local_window_delta = 1024 * 1024 * 1024;
-    s.chttp2_stream()->flow_control.announced_window_delta = 1024 * 1024 * 1024;
-    f.chttp2_transport()->flow_control.announced_window = 1024 * 1024 * 1024;
-    received = 0;
-    reset_op();
-    op.on_complete = do_nothing.get();
-    op.recv_message = true;
-    op.payload->recv_message.recv_message = &recv_stream;
-    op.payload->recv_message.recv_message_ready = drain_start.get();
-    s.Op(exec_ctx, &op);
-    f.PushInput(grpc_slice_ref(incoming_data));
-  });
+  std::unique_ptr<Closure> c =
+      MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
+        if (!state.KeepRunning()) return;
+        // force outgoing window to be yuge
+        s.chttp2_stream()->flow_control->TestOnlyForceHugeWindow();
+        f.chttp2_transport()->flow_control->TestOnlyForceHugeWindow();
+        received = 0;
+        reset_op();
+        op.on_complete = do_nothing.get();
+        op.recv_message = true;
+        op.payload->recv_message.recv_message = &recv_stream;
+        op.payload->recv_message.recv_message_ready = drain_start.get();
+        s.Op(exec_ctx, &op);
+        f.PushInput(grpc_slice_ref(incoming_data));
+      });
 
   drain_start = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
     if (recv_stream == NULL) {
diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
index adb5e66..389b8c9 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
@@ -21,17 +21,15 @@
 #include <benchmark/benchmark.h>
 #include <gflags/gflags.h>
 #include <fstream>
-#include "src/core/lib/profiling/timers.h"
-#include "src/proto/grpc/testing/echo.grpc.pb.h"
-#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
-#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
-#include "test/cpp/util/test_config.h"
-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/iomgr/timer_manager.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/trickle_endpoint.h"
-}
+#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
+#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "test/cpp/util/test_config.h"
 
 DEFINE_bool(log, false, "Log state to CSV files");
 DEFINE_int32(
@@ -144,15 +142,18 @@
         client->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != nullptr,
         server->lists[GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT].head != nullptr,
         server->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != nullptr,
-        client->flow_control.remote_window, server->flow_control.remote_window,
-        client->flow_control.announced_window,
-        server->flow_control.announced_window,
-        client_stream ? client_stream->flow_control.remote_window_delta : -1,
-        server_stream ? server_stream->flow_control.remote_window_delta : -1,
-        client_stream ? client_stream->flow_control.local_window_delta : -1,
-        server_stream ? server_stream->flow_control.local_window_delta : -1,
-        client_stream ? client_stream->flow_control.announced_window_delta : -1,
-        server_stream ? server_stream->flow_control.announced_window_delta : -1,
+        client->flow_control->remote_window(),
+        server->flow_control->remote_window(),
+        client->flow_control->announced_window(),
+        server->flow_control->announced_window(),
+        client_stream ? client_stream->flow_control->remote_window_delta() : -1,
+        server_stream ? server_stream->flow_control->remote_window_delta() : -1,
+        client_stream ? client_stream->flow_control->local_window_delta() : -1,
+        server_stream ? server_stream->flow_control->local_window_delta() : -1,
+        client_stream ? client_stream->flow_control->announced_window_delta()
+                      : -1,
+        server_stream ? server_stream->flow_control->announced_window_delta()
+                      : -1,
         client->settings[GRPC_PEER_SETTINGS]
                         [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
         client->settings[GRPC_LOCAL_SETTINGS]
diff --git a/test/cpp/microbenchmarks/helpers.cc b/test/cpp/microbenchmarks/helpers.cc
index b0caa48..6802a0a 100644
--- a/test/cpp/microbenchmarks/helpers.cc
+++ b/test/cpp/microbenchmarks/helpers.cc
@@ -20,6 +20,9 @@
 
 void TrackCounters::Finish(benchmark::State &state) {
   std::ostringstream out;
+  for (const auto &l : labels_) {
+    out << l << ' ';
+  }
   AddToLabel(out, state);
   std::string label = out.str();
   if (label.length() && label[0] == ' ') {
@@ -28,6 +31,10 @@
   state.SetLabel(label.c_str());
 }
 
+void TrackCounters::AddLabel(const grpc::string &label) {
+  labels_.push_back(label);
+}
+
 void TrackCounters::AddToLabel(std::ostream &out, benchmark::State &state) {
   grpc_stats_data stats_end;
   grpc_stats_collect(&stats_end);
diff --git a/test/cpp/microbenchmarks/helpers.h b/test/cpp/microbenchmarks/helpers.h
index 07dd611..b6cea7c 100644
--- a/test/cpp/microbenchmarks/helpers.h
+++ b/test/cpp/microbenchmarks/helpers.h
@@ -20,6 +20,7 @@
 #define TEST_CPP_MICROBENCHMARKS_COUNTERS_H
 
 #include <sstream>
+#include <vector>
 
 extern "C" {
 #include <grpc/support/port_platform.h>
@@ -65,10 +66,12 @@
  public:
   TrackCounters() { grpc_stats_collect(&stats_begin_); }
   virtual void Finish(benchmark::State& state);
+  virtual void AddLabel(const grpc::string& label);
   virtual void AddToLabel(std::ostream& out, benchmark::State& state);
 
  private:
   grpc_stats_data stats_begin_;
+  std::vector<grpc::string> labels_;
 #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_ =
diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD
index 3352269..0d91d52 100644
--- a/test/cpp/qps/BUILD
+++ b/test/cpp/qps/BUILD
@@ -109,6 +109,18 @@
     deps = ["//:gpr"],
 )
 
+grpc_cc_test(
+    name = "inproc_sync_unary_ping_pong_test",
+    srcs = ["inproc_sync_unary_ping_pong_test.cc"],
+    deps = [
+        ":benchmark_config",
+        ":driver_impl",
+        "//:grpc++",
+        "//test/cpp/util:test_config",
+        "//test/cpp/util:test_util",
+    ],
+)
+
 grpc_cc_library(
     name = "interarrival",
     hdrs = ["interarrival.h"],
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index 7fbaf63..a5049e5 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -37,10 +37,14 @@
 #include "src/cpp/util/core_stats.h"
 #include "test/cpp/qps/histogram.h"
 #include "test/cpp/qps/interarrival.h"
+#include "test/cpp/qps/qps_worker.h"
+#include "test/cpp/qps/server.h"
 #include "test/cpp/qps/usage_timer.h"
 #include "test/cpp/util/create_test_channel.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
+#define INPROC_NAME_PREFIX "qpsinproc:"
+
 namespace grpc {
 namespace testing {
 
@@ -226,6 +230,7 @@
   }
 
   virtual void DestroyMultithreading() = 0;
+  virtual void InitThreadFunc(size_t thread_idx) = 0;
   virtual bool ThreadFunc(HistogramEntry* histogram, size_t thread_idx) = 0;
 
   void SetupLoadTest(const ClientConfig& config, size_t num_threads) {
@@ -299,13 +304,18 @@
     Thread& operator=(const Thread&);
 
     void ThreadFunc() {
+      int wait_loop = 0;
       while (!gpr_event_wait(
           &client_->start_requests_,
           gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                       gpr_time_from_seconds(1, GPR_TIMESPAN)))) {
-        gpr_log(GPR_INFO, "Waiting for benchmark to start");
+                       gpr_time_from_seconds(20, GPR_TIMESPAN)))) {
+        gpr_log(GPR_INFO, "%" PRIdPTR ": Waiting for benchmark to start (%d)",
+                idx_, wait_loop);
+        wait_loop++;
       }
 
+      client_->InitThreadFunc(idx_);
+
       for (;;) {
         // run the loop body
         HistogramEntry entry;
@@ -380,6 +390,13 @@
           config.server_targets(i % config.server_targets_size()), config,
           create_stub_, i);
     }
+    std::vector<std::unique_ptr<std::thread>> connecting_threads;
+    for (auto& c : channels_) {
+      connecting_threads.emplace_back(c.WaitForReady());
+    }
+    for (auto& t : connecting_threads) {
+      t->join();
+    }
 
     ClientRequestCreator<RequestType> create_req(&request_,
                                                  config.payload_config());
@@ -409,19 +426,36 @@
         type = config.security_params().cred_type();
       }
 
-      channel_ = CreateTestChannel(
-          target, type, config.security_params().server_host_override(),
-          !config.security_params().use_test_ca(),
-          std::shared_ptr<CallCredentials>(), args);
-      gpr_log(GPR_INFO, "Connecting to %s", target.c_str());
-      GPR_ASSERT(channel_->WaitForConnected(
-          gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                       gpr_time_from_seconds(300, GPR_TIMESPAN))));
+      grpc::string inproc_pfx(INPROC_NAME_PREFIX);
+      if (target.find(inproc_pfx) != 0) {
+        channel_ = CreateTestChannel(
+            target, type, config.security_params().server_host_override(),
+            !config.security_params().use_test_ca(),
+            std::shared_ptr<CallCredentials>(), args);
+        gpr_log(GPR_INFO, "Connecting to %s", target.c_str());
+        is_inproc_ = false;
+      } else {
+        grpc::string tgt = target;
+        tgt.erase(0, inproc_pfx.length());
+        int srv_num = std::stoi(tgt);
+        channel_ = (*g_inproc_servers)[srv_num]->InProcessChannel(args);
+        is_inproc_ = true;
+      }
       stub_ = create_stub(channel_);
     }
     Channel* get_channel() { return channel_.get(); }
     StubType* get_stub() { return stub_.get(); }
 
+    std::unique_ptr<std::thread> WaitForReady() {
+      return std::unique_ptr<std::thread>(new std::thread([this]() {
+        if (!is_inproc_) {
+          GPR_ASSERT(channel_->WaitForConnected(
+              gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                           gpr_time_from_seconds(10, GPR_TIMESPAN))));
+        }
+      }));
+    }
+
    private:
     void set_channel_args(const ClientConfig& config, ChannelArguments* args) {
       for (auto channel_arg : config.channel_args()) {
@@ -437,6 +471,7 @@
 
     std::shared_ptr<Channel> channel_;
     std::unique_ptr<StubType> stub_;
+    bool is_inproc_;
   };
   std::vector<ClientChannelInfo> channels_;
   std::function<std::unique_ptr<StubType>(const std::shared_ptr<Channel>&)>
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index f5807da..9ed4e0b 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -236,6 +236,7 @@
     this->EndThreads();  // this needed for resolution
   }
 
+  void InitThreadFunc(size_t thread_idx) override final {}
   bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override final {
     void* got_tag;
     bool ok;
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index 5d212f1..94554a4 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -103,6 +103,8 @@
   }
   ~SynchronousUnaryClient() {}
 
+  void InitThreadFunc(size_t thread_idx) override {}
+
   bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override {
     if (!WaitToIssue(thread_idx)) {
       return true;
@@ -174,13 +176,7 @@
           grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>> {
  public:
   SynchronousStreamingPingPongClient(const ClientConfig& config)
-      : SynchronousStreamingClient(config) {
-    for (size_t thread_idx = 0; thread_idx < num_threads_; thread_idx++) {
-      auto* stub = channels_[thread_idx % channels_.size()].get_stub();
-      stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]);
-      messages_issued_[thread_idx] = 0;
-    }
-  }
+      : SynchronousStreamingClient(config) {}
   ~SynchronousStreamingPingPongClient() {
     std::vector<std::thread> cleanup_threads;
     for (size_t i = 0; i < num_threads_; i++) {
@@ -196,6 +192,12 @@
     }
   }
 
+  void InitThreadFunc(size_t thread_idx) override {
+    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
+    stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]);
+    messages_issued_[thread_idx] = 0;
+  }
+
   bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override {
     if (!WaitToIssue(thread_idx)) {
       return true;
@@ -228,14 +230,7 @@
     : public SynchronousStreamingClient<grpc::ClientWriter<SimpleRequest>> {
  public:
   SynchronousStreamingFromClientClient(const ClientConfig& config)
-      : SynchronousStreamingClient(config), last_issue_(num_threads_) {
-    for (size_t thread_idx = 0; thread_idx < num_threads_; thread_idx++) {
-      auto* stub = channels_[thread_idx % channels_.size()].get_stub();
-      stream_[thread_idx] = stub->StreamingFromClient(&context_[thread_idx],
-                                                      &responses_[thread_idx]);
-      last_issue_[thread_idx] = UsageTimer::Now();
-    }
-  }
+      : SynchronousStreamingClient(config), last_issue_(num_threads_) {}
   ~SynchronousStreamingFromClientClient() {
     std::vector<std::thread> cleanup_threads;
     for (size_t i = 0; i < num_threads_; i++) {
@@ -251,6 +246,13 @@
     }
   }
 
+  void InitThreadFunc(size_t thread_idx) override {
+    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
+    stream_[thread_idx] = stub->StreamingFromClient(&context_[thread_idx],
+                                                    &responses_[thread_idx]);
+    last_issue_[thread_idx] = UsageTimer::Now();
+  }
+
   bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override {
     // Figure out how to make histogram sensible if this is rate-paced
     if (!WaitToIssue(thread_idx)) {
@@ -279,13 +281,12 @@
     : public SynchronousStreamingClient<grpc::ClientReader<SimpleResponse>> {
  public:
   SynchronousStreamingFromServerClient(const ClientConfig& config)
-      : SynchronousStreamingClient(config), last_recv_(num_threads_) {
-    for (size_t thread_idx = 0; thread_idx < num_threads_; thread_idx++) {
-      auto* stub = channels_[thread_idx % channels_.size()].get_stub();
-      stream_[thread_idx] =
-          stub->StreamingFromServer(&context_[thread_idx], request_);
-      last_recv_[thread_idx] = UsageTimer::Now();
-    }
+      : SynchronousStreamingClient(config), last_recv_(num_threads_) {}
+  void InitThreadFunc(size_t thread_idx) override {
+    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
+    stream_[thread_idx] =
+        stub->StreamingFromServer(&context_[thread_idx], request_);
+    last_recv_[thread_idx] = UsageTimer::Now();
   }
   bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override {
     GPR_TIMER_SCOPE("SynchronousStreamingFromServerClient::ThreadFunc", 0);
@@ -311,12 +312,7 @@
           grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>> {
  public:
   SynchronousStreamingBothWaysClient(const ClientConfig& config)
-      : SynchronousStreamingClient(config) {
-    for (size_t thread_idx = 0; thread_idx < num_threads_; thread_idx++) {
-      auto* stub = channels_[thread_idx % channels_.size()].get_stub();
-      stream_[thread_idx] = stub->StreamingBothWays(&context_[thread_idx]);
-    }
-  }
+      : SynchronousStreamingClient(config) {}
   ~SynchronousStreamingBothWaysClient() {
     std::vector<std::thread> cleanup_threads;
     for (size_t i = 0; i < num_threads_; i++) {
@@ -332,6 +328,10 @@
     }
   }
 
+  void InitThreadFunc(size_t thread_idx) override {
+    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
+    stream_[thread_idx] = stub->StreamingBothWays(&context_[thread_idx]);
+  }
   bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override {
     // TODO (vjpai): Do this
     return true;
diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc
index 4458e38..5504c0b 100644
--- a/test/cpp/qps/driver.cc
+++ b/test/cpp/qps/driver.cc
@@ -36,6 +36,7 @@
 #include "src/proto/grpc/testing/services.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
+#include "test/cpp/qps/client.h"
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/histogram.h"
 #include "test/cpp/qps/qps_worker.h"
@@ -63,11 +64,11 @@
 }
 
 static deque<string> get_workers(const string& env_name) {
+  deque<string> out;
   char* env = gpr_getenv(env_name.c_str());
   if (!env) {
     env = gpr_strdup("");
   }
-  deque<string> out;
   char* p = env;
   if (strlen(env) != 0) {
     for (;;) {
@@ -187,12 +188,17 @@
       client_queries_per_cpu_sec);
 }
 
+std::vector<grpc::testing::Server*>* g_inproc_servers = nullptr;
+
 std::unique_ptr<ScenarioResult> RunScenario(
     const ClientConfig& initial_client_config, size_t num_clients,
     const ServerConfig& initial_server_config, size_t num_servers,
     int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count,
     const grpc::string& qps_server_target_override,
-    const grpc::string& credential_type) {
+    const grpc::string& credential_type, bool run_inproc) {
+  if (run_inproc) {
+    g_inproc_servers = new std::vector<grpc::testing::Server*>;
+  }
   // Log everything from the driver
   gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG);
 
@@ -210,8 +216,8 @@
   ClientConfig result_client_config;
   const ServerConfig result_server_config = initial_server_config;
 
-  // Get client, server lists
-  auto workers = get_workers("QPS_WORKERS");
+  // Get client, server lists; ignore if inproc test
+  auto workers = (!run_inproc) ? get_workers("QPS_WORKERS") : deque<string>();
   ClientConfig client_config = initial_client_config;
 
   // Spawn some local workers if desired
@@ -227,9 +233,10 @@
       called_init = true;
     }
 
-    int driver_port = grpc_pick_unused_port_or_die();
-    local_workers.emplace_back(new QpsWorker(driver_port, 0, credential_type));
     char addr[256];
+    // we use port # of -1 to indicate inproc
+    int driver_port = (!run_inproc) ? grpc_pick_unused_port_or_die() : -1;
+    local_workers.emplace_back(new QpsWorker(driver_port, 0, credential_type));
     sprintf(addr, "localhost:%d", driver_port);
     if (spawn_local_worker_count < 0) {
       workers.push_front(addr);
@@ -265,9 +272,14 @@
   for (size_t i = 0; i < num_servers; i++) {
     gpr_log(GPR_INFO, "Starting server on %s (worker #%" PRIuPTR ")",
             workers[i].c_str(), i);
-    servers[i].stub = WorkerService::NewStub(CreateChannel(
-        workers[i], GetCredentialsProvider()->GetChannelCredentials(
-                        credential_type, &channel_args)));
+    if (!run_inproc) {
+      servers[i].stub = WorkerService::NewStub(CreateChannel(
+          workers[i], GetCredentialsProvider()->GetChannelCredentials(
+                          credential_type, &channel_args)));
+    } else {
+      servers[i].stub = WorkerService::NewStub(
+          local_workers[i]->InProcessChannel(channel_args));
+    }
 
     ServerConfig server_config = initial_server_config;
     if (server_config.core_limit() != 0) {
@@ -289,6 +301,10 @@
       // overriding the qps server target only works if there is 1 server
       GPR_ASSERT(num_servers == 1);
       client_config.add_server_targets(qps_server_target_override);
+    } else if (run_inproc) {
+      std::string cli_target(INPROC_NAME_PREFIX);
+      cli_target += std::to_string(i);
+      client_config.add_server_targets(cli_target);
     } else {
       std::string host;
       char* cli_target;
@@ -312,9 +328,14 @@
     const auto& worker = workers[i + num_servers];
     gpr_log(GPR_INFO, "Starting client on %s (worker #%" PRIuPTR ")",
             worker.c_str(), i + num_servers);
-    clients[i].stub = WorkerService::NewStub(
-        CreateChannel(worker, GetCredentialsProvider()->GetChannelCredentials(
-                                  credential_type, &channel_args)));
+    if (!run_inproc) {
+      clients[i].stub = WorkerService::NewStub(
+          CreateChannel(worker, GetCredentialsProvider()->GetChannelCredentials(
+                                    credential_type, &channel_args)));
+    } else {
+      clients[i].stub = WorkerService::NewStub(
+          local_workers[i + num_servers]->InProcessChannel(channel_args));
+    }
     ClientConfig per_client_config = client_config;
 
     if (initial_client_config.core_limit() != 0) {
@@ -495,6 +516,9 @@
     }
   }
 
+  if (g_inproc_servers != nullptr) {
+    delete g_inproc_servers;
+  }
   postprocess_scenario_result(result.get());
   return result;
 }
diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h
index 29f2776..fede4d8 100644
--- a/test/cpp/qps/driver.h
+++ b/test/cpp/qps/driver.h
@@ -32,7 +32,7 @@
     const grpc::testing::ServerConfig& server_config, size_t num_servers,
     int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count,
     const grpc::string& qps_server_target_override,
-    const grpc::string& credential_type);
+    const grpc::string& credential_type, bool run_inproc);
 
 bool RunQuit(const grpc::string& credential_type);
 }  // namespace testing
diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py
index 8575fe5..1ef8f65 100755
--- a/test/cpp/qps/gen_build_yaml.py
+++ b/test/cpp/qps/gen_build_yaml.py
@@ -78,12 +78,31 @@
       'cpu_cost': guess_cpu(scenario_json, False),
       'exclude_configs': ['tsan', 'asan'],
       'timeout_seconds': 2*60,
-      'excluded_poll_engines': scenario_json.get('EXCLUDED_POLL_ENGINES', [])
+      'excluded_poll_engines': scenario_json.get('EXCLUDED_POLL_ENGINES', []),
+      'auto_timeout_scaling': False
     }
     for scenario_json in scenario_config.CXXLanguage().scenarios()
     if 'scalable' in scenario_json.get('CATEGORIES', [])
   ] + [
     {
+      'name': 'qps_json_driver',
+      'shortname': 'qps_json_driver:inproc_%s' % scenario_json['name'],
+      'args': ['--run_inproc', '--scenarios_json', _scenario_json_string(scenario_json, False)],
+      'ci_platforms': ['linux'],
+      'platforms': ['linux'],
+      'flaky': False,
+      'language': 'c++',
+      'boringssl': True,
+      'defaults': 'boringssl',
+      'cpu_cost': guess_cpu(scenario_json, False),
+      'exclude_configs': ['tsan', 'asan'],
+      'timeout_seconds': 6*60,
+      'excluded_poll_engines': scenario_json.get('EXCLUDED_POLL_ENGINES', [])
+    }
+    for scenario_json in scenario_config.CXXLanguage().scenarios()
+    if 'inproc' in scenario_json.get('CATEGORIES', [])
+  ] + [
+    {
       'name': 'json_run_localhost',
       'shortname': 'json_run_localhost:%s_low_thread_count' % scenario_json['name'],
       'args': ['--scenarios_json', _scenario_json_string(scenario_json, True)],
@@ -95,8 +114,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': 2*60,
-      'excluded_poll_engines': scenario_json.get('EXCLUDED_POLL_ENGINES', [])
+      'timeout_seconds': 10*60,
+      'excluded_poll_engines': scenario_json.get('EXCLUDED_POLL_ENGINES', []),
+      'auto_timeout_scaling': False
    }
     for scenario_json in scenario_config.CXXLanguage().scenarios()
     if 'scalable' in scenario_json.get('CATEGORIES', [])
diff --git a/test/cpp/qps/inproc_sync_unary_ping_pong_test.cc b/test/cpp/qps/inproc_sync_unary_ping_pong_test.cc
new file mode 100644
index 0000000..f2e977d
--- /dev/null
+++ b/test/cpp/qps/inproc_sync_unary_ping_pong_test.cc
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <set>
+
+#include <grpc/support/log.h>
+
+#include "test/cpp/qps/benchmark_config.h"
+#include "test/cpp/qps/driver.h"
+#include "test/cpp/qps/report.h"
+#include "test/cpp/qps/server.h"
+#include "test/cpp/util/test_config.h"
+#include "test/cpp/util/test_credentials_provider.h"
+
+namespace grpc {
+namespace testing {
+
+static const int WARMUP = 5;
+static const int BENCHMARK = 5;
+
+static void RunSynchronousUnaryPingPong() {
+  gpr_log(GPR_INFO, "Running Synchronous Unary Ping Pong");
+
+  ClientConfig client_config;
+  client_config.set_client_type(SYNC_CLIENT);
+  client_config.set_outstanding_rpcs_per_channel(1);
+  client_config.set_client_channels(1);
+  client_config.set_rpc_type(UNARY);
+  client_config.mutable_load_params()->mutable_closed_loop();
+
+  ServerConfig server_config;
+  server_config.set_server_type(SYNC_SERVER);
+
+  const auto result =
+      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2, "",
+                  kInsecureCredentialsType, true);
+
+  GetReporter()->ReportQPS(*result);
+  GetReporter()->ReportLatency(*result);
+}
+
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  grpc::testing::InitTest(&argc, &argv, true);
+
+  grpc::testing::RunSynchronousUnaryPingPong();
+
+  return 0;
+}
diff --git a/test/cpp/qps/json_run_localhost.cc b/test/cpp/qps/json_run_localhost.cc
index 1d394b2..4b788ea 100644
--- a/test/cpp/qps/json_run_localhost.cc
+++ b/test/cpp/qps/json_run_localhost.cc
@@ -117,8 +117,14 @@
     }
   }
 
-  delete g_driver;
-  g_driver = NULL;
-  for (int i = 0; i < kNumWorkers; ++i) delete g_workers[i];
+  if (g_driver != nullptr) {
+    delete g_driver;
+  }
+  g_driver = nullptr;
+  for (int i = 0; i < kNumWorkers; ++i) {
+    if (g_workers[i] != nullptr) {
+      delete g_workers[i];
+    }
+  }
   GPR_ASSERT(driver_join_status == 0);
 }
diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc
index cca59f6..1672527 100644
--- a/test/cpp/qps/qps_json_driver.cc
+++ b/test/cpp/qps/qps_json_driver.cc
@@ -30,6 +30,7 @@
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/parse_json.h"
 #include "test/cpp/qps/report.h"
+#include "test/cpp/qps/server.h"
 #include "test/cpp/util/test_config.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
@@ -64,6 +65,7 @@
 
 DEFINE_string(credential_type, grpc::testing::kInsecureCredentialsType,
               "Credential type for communication with workers");
+DEFINE_bool(run_inproc, false, "Perform an in-process transport test");
 
 namespace grpc {
 namespace testing {
@@ -75,8 +77,9 @@
       RunScenario(scenario.client_config(), scenario.num_clients(),
                   scenario.server_config(), scenario.num_servers(),
                   scenario.warmup_seconds(), scenario.benchmark_seconds(),
-                  scenario.spawn_local_worker_count(),
-                  FLAGS_qps_server_target_override, FLAGS_credential_type);
+                  !FLAGS_run_inproc ? scenario.spawn_local_worker_count() : -2,
+                  FLAGS_qps_server_target_override, FLAGS_credential_type,
+                  FLAGS_run_inproc);
 
   // Amend the result with scenario config. Eventually we should adjust
   // RunScenario contract so we don't need to touch the result here.
diff --git a/test/cpp/qps/qps_openloop_test.cc b/test/cpp/qps/qps_openloop_test.cc
index 069b3fa..df929b9 100644
--- a/test/cpp/qps/qps_openloop_test.cc
+++ b/test/cpp/qps/qps_openloop_test.cc
@@ -24,6 +24,7 @@
 #include "test/cpp/qps/benchmark_config.h"
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/report.h"
+#include "test/cpp/qps/server.h"
 #include "test/cpp/util/test_config.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
@@ -49,8 +50,9 @@
   server_config.set_server_type(ASYNC_SERVER);
   server_config.set_async_server_threads(8);
 
-  const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP,
-                                  BENCHMARK, -2, "", kInsecureCredentialsType);
+  const auto result =
+      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2, "",
+                  kInsecureCredentialsType, false);
 
   GetReporter()->ReportQPSPerCore(*result);
   GetReporter()->ReportLatency(*result);
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index d20bc1b..c288b03 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -225,11 +225,14 @@
     if (!args.has_setup()) {
       return Status(StatusCode::INVALID_ARGUMENT, "Bad server creation args");
     }
-    if (server_port_ != 0) {
+    if (server_port_ > 0) {
       args.mutable_setup()->set_port(server_port_);
     }
     gpr_log(GPR_INFO, "RunServerBody: about to create server");
     auto server = CreateServer(args.setup());
+    if (g_inproc_servers != nullptr) {
+      g_inproc_servers->push_back(server.get());
+    }
     if (!server) {
       return Status(StatusCode::INVALID_ARGUMENT, "Couldn't create server");
     }
@@ -269,17 +272,17 @@
   impl_.reset(new WorkerServiceImpl(server_port, this));
   gpr_atm_rel_store(&done_, static_cast<gpr_atm>(0));
 
-  char* server_address = NULL;
-  gpr_join_host_port(&server_address, "::", driver_port);
-
   ServerBuilder builder;
-  builder.AddListeningPort(
-      server_address,
-      GetCredentialsProvider()->GetServerCredentials(credential_type));
+  if (driver_port >= 0) {
+    char* server_address = nullptr;
+    gpr_join_host_port(&server_address, "::", driver_port);
+    builder.AddListeningPort(
+        server_address,
+        GetCredentialsProvider()->GetServerCredentials(credential_type));
+    gpr_free(server_address);
+  }
   builder.RegisterService(impl_.get());
 
-  gpr_free(server_address);
-
   server_ = builder.BuildAndStart();
 }
 
diff --git a/test/cpp/qps/qps_worker.h b/test/cpp/qps/qps_worker.h
index 360125f..a516742 100644
--- a/test/cpp/qps/qps_worker.h
+++ b/test/cpp/qps/qps_worker.h
@@ -21,17 +21,21 @@
 
 #include <memory>
 
+#include <grpc++/server.h>
+#include <grpc++/support/channel_arguments.h>
 #include <grpc++/support/config.h>
 #include <grpc/support/atm.h>
 
-namespace grpc {
+#include "test/cpp/qps/server.h"
 
-class Server;
+namespace grpc {
 
 namespace testing {
 
 class WorkerServiceImpl;
 
+extern std::vector<grpc::testing::Server*>* g_inproc_servers;
+
 class QpsWorker {
  public:
   explicit QpsWorker(int driver_port, int server_port,
@@ -41,9 +45,13 @@
   bool Done() const;
   void MarkDone();
 
+  std::shared_ptr<Channel> InProcessChannel(const ChannelArguments& args) {
+    return server_->InProcessChannel(args);
+  }
+
  private:
   std::unique_ptr<WorkerServiceImpl> impl_;
-  std::unique_ptr<Server> server_;
+  std::unique_ptr<grpc::Server> server_;
 
   gpr_atm done_;
 };
diff --git a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
index 137b33e..bb415e9 100644
--- a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
+++ b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
@@ -23,6 +23,7 @@
 #include "test/cpp/qps/benchmark_config.h"
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/report.h"
+#include "test/cpp/qps/server.h"
 #include "test/cpp/util/test_config.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
@@ -52,8 +53,9 @@
   client_config.mutable_security_params()->CopyFrom(security);
   server_config.mutable_security_params()->CopyFrom(security);
 
-  const auto result = RunScenario(client_config, 1, server_config, 1, WARMUP,
-                                  BENCHMARK, -2, "", kInsecureCredentialsType);
+  const auto result =
+      RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2, "",
+                  kInsecureCredentialsType, false);
 
   GetReporter()->ReportQPS(*result);
   GetReporter()->ReportLatency(*result);
diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h
index 16d101d..9da3356 100644
--- a/test/cpp/qps/server.h
+++ b/test/cpp/qps/server.h
@@ -42,10 +42,9 @@
   explicit Server(const ServerConfig& config)
       : timer_(new UsageTimer), last_reset_poll_count_(0) {
     cores_ = gpr_cpu_num_cores();
-    if (config.port()) {
+    if (config.port()) {  // positive for a fixed port, negative for inproc
       port_ = config.port();
-
-    } else {
+    } else {  // zero for dynamic port
       port_ = grpc_pick_unused_port_or_die();
     }
   }
@@ -115,6 +114,9 @@
     return 0;
   }
 
+  virtual std::shared_ptr<Channel> InProcessChannel(
+      const ChannelArguments& args) = 0;
+
  protected:
   static void ApplyConfigToBuilder(const ServerConfig& config,
                                    ServerBuilder* builder) {
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 4a82f98..776371a 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -74,14 +74,17 @@
                                  ResponseType *)>
           process_rpc)
       : Server(config) {
-    char *server_address = NULL;
-
-    gpr_join_host_port(&server_address, "::", port());
-
     ServerBuilder builder;
-    builder.AddListeningPort(server_address,
-                             Server::CreateServerCredentials(config));
-    gpr_free(server_address);
+
+    auto port_num = port();
+    // Negative port number means inproc server, so no listen port needed
+    if (port_num >= 0) {
+      char *server_address = NULL;
+      gpr_join_host_port(&server_address, "::", port_num);
+      builder.AddListeningPort(server_address,
+                               Server::CreateServerCredentials(config));
+      gpr_free(server_address);
+    }
 
     register_service(&builder, &async_service_);
 
@@ -183,6 +186,11 @@
     return count;
   }
 
+  std::shared_ptr<Channel> InProcessChannel(
+      const ChannelArguments &args) override {
+    return server_->InProcessChannel(args);
+  }
+
  private:
   void ShutdownThreadFunc() {
     // TODO (vpai): Remove this deadline and allow Shutdown to finish properly
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index 9954e2c..4ef57bd 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -156,12 +156,15 @@
   explicit SynchronousServer(const ServerConfig& config) : Server(config) {
     ServerBuilder builder;
 
-    char* server_address = NULL;
-
-    gpr_join_host_port(&server_address, "::", port());
-    builder.AddListeningPort(server_address,
-                             Server::CreateServerCredentials(config));
-    gpr_free(server_address);
+    auto port_num = port();
+    // Negative port number means inproc server, so no listen port needed
+    if (port_num >= 0) {
+      char* server_address = NULL;
+      gpr_join_host_port(&server_address, "::", port_num);
+      builder.AddListeningPort(server_address,
+                               Server::CreateServerCredentials(config));
+      gpr_free(server_address);
+    }
 
     ApplyConfigToBuilder(config, &builder);
 
@@ -170,6 +173,11 @@
     impl_ = builder.BuildAndStart();
   }
 
+  std::shared_ptr<Channel> InProcessChannel(
+      const ChannelArguments& args) override {
+    return impl_->InProcessChannel(args);
+  }
+
  private:
   BenchmarkServiceImpl service_;
   std::unique_ptr<grpc::Server> impl_;
diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc
index 27010b7..3828746 100644
--- a/test/cpp/qps/worker.cc
+++ b/test/cpp/qps/worker.cc
@@ -20,6 +20,7 @@
 
 #include <chrono>
 #include <thread>
+#include <vector>
 
 #include <gflags/gflags.h>
 #include <grpc/grpc.h>
@@ -41,6 +42,8 @@
 namespace grpc {
 namespace testing {
 
+std::vector<grpc::testing::Server*>* g_inproc_servers = nullptr;
+
 static void RunServer() {
   QpsWorker worker(FLAGS_driver_port, FLAGS_server_port, FLAGS_credential_type);
 
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index 34b6d60..4d04747 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -74,7 +74,7 @@
   ChannelArguments channel_args(args);
   std::shared_ptr<ChannelCredentials> channel_creds;
   if (cred_type.empty()) {
-    return CreateChannel(server, InsecureChannelCredentials());
+    return CreateCustomChannel(server, InsecureChannelCredentials(), args);
   } else if (cred_type == testing::kTlsCredentialsType) {  // cred_type == "ssl"
     if (use_prod_roots) {
       gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType);
@@ -101,7 +101,7 @@
         cred_type, &channel_args);
     GPR_ASSERT(channel_creds != nullptr);
 
-    return CreateChannel(server, channel_creds);
+    return CreateCustomChannel(server, channel_creds, args);
   }
 }
 
diff --git a/third_party/abseil-cpp b/third_party/abseil-cpp
new file mode 160000
index 0000000..cc4bed2
--- /dev/null
+++ b/third_party/abseil-cpp
@@ -0,0 +1 @@
+Subproject commit cc4bed2d74f7c8717e31f9579214ab52a9c9c610
diff --git a/third_party/cares/config_openbsd/ares_config.h b/third_party/cares/config_openbsd/ares_config.h
new file mode 100644
index 0000000..3b3320d
--- /dev/null
+++ b/third_party/cares/config_openbsd/ares_config.h
@@ -0,0 +1,502 @@
+/* ares_config.h.  Generated from ares_config.h.in by configure.  */
+/* ares_config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* define this if ares is built for a big endian system */
+/* #undef ARES_BIG_ENDIAN */
+
+/* when building as static part of libcurl */
+/* #undef BUILDING_LIBCURL */
+
+/* Defined for build that exposes internal static functions for testing. */
+/* #undef CARES_EXPOSE_STATICS */
+
+/* Defined for build with symbol hiding. */
+#define CARES_SYMBOL_HIDING 1
+
+/* Definition to make a library symbol externally visible. */
+#define CARES_SYMBOL_SCOPE_EXTERN __attribute__ ((__visibility__ ("default")))
+
+/* the signed version of size_t */
+#define CARES_TYPEOF_ARES_SSIZE_T ssize_t
+
+/* Use resolver library to configure cares */
+/* #undef CARES_USE_LIBRESOLV */
+
+/* if a /etc/inet dir is being used */
+/* #undef ETC_INET */
+
+/* Define to the type of arg 2 for gethostname. */
+#define GETHOSTNAME_TYPE_ARG2 size_t
+
+/* Define to the type qualifier of arg 1 for getnameinfo. */
+#define GETNAMEINFO_QUAL_ARG1 const
+
+/* Define to the type of arg 1 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
+
+/* Define to the type of arg 2 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG2 socklen_t
+
+/* Define to the type of args 4 and 6 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG46 size_t
+
+/* Define to the type of arg 7 for getnameinfo. */
+#define GETNAMEINFO_TYPE_ARG7 int
+
+/* Specifies the number of arguments to getservbyport_r */
+#define GETSERVBYPORT_R_ARGS 4
+
+/* Specifies the size of the buffer to pass to getservbyport_r */
+#define GETSERVBYPORT_R_BUFSIZE sizeof(struct servent_data)
+
+/* Define to 1 if you have AF_INET6. */
+#define HAVE_AF_INET6 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/nameser_compat.h> header file. */
+/* #undef HAVE_ARPA_NAMESER_COMPAT_H */
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `bitncmp' function. */
+/* #undef HAVE_BITNCMP */
+
+/* Define to 1 if bool is an available type. */
+#define HAVE_BOOL_T 1
+
+/* Define to 1 if you have the clock_gettime function and monotonic timer. */
+#define HAVE_CLOCK_GETTIME_MONOTONIC 1
+
+/* Define to 1 if you have the closesocket function. */
+/* #undef HAVE_CLOSESOCKET */
+
+/* Define to 1 if you have the CloseSocket camel case function. */
+/* #undef HAVE_CLOSESOCKET_CAMEL */
+
+/* Define to 1 if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* define if the compiler supports basic C++11 syntax */
+/* #undef HAVE_CXX11 */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
+#define HAVE_FCNTL_O_NONBLOCK 1
+
+/* Define to 1 if you have the freeaddrinfo function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define to 1 if you have a working getaddrinfo function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if the getaddrinfo function is threadsafe. */
+/* #undef HAVE_GETADDRINFO_THREADSAFE */
+
+/* Define to 1 if you have the getenv function. */
+#define HAVE_GETENV 1
+
+/* Define to 1 if you have the gethostbyaddr function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the gethostbyname function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have the getnameinfo function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the getservbyport_r function. */
+#define HAVE_GETSERVBYPORT_R 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `if_indextoname' function. */
+#define HAVE_IF_INDEXTONAME 1
+
+/* Define to 1 if you have a IPv6 capable working inet_net_pton function. */
+/* #undef HAVE_INET_NET_PTON */
+
+/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have a IPv6 capable working inet_pton function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the ioctl function. */
+#define HAVE_IOCTL 1
+
+/* Define to 1 if you have the ioctlsocket function. */
+/* #undef HAVE_IOCTLSOCKET */
+
+/* Define to 1 if you have the IoctlSocket camel case function. */
+/* #undef HAVE_IOCTLSOCKET_CAMEL */
+
+/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
+   */
+/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */
+
+/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
+/* #undef HAVE_IOCTLSOCKET_FIONBIO */
+
+/* Define to 1 if you have a working ioctl FIONBIO function. */
+#define HAVE_IOCTL_FIONBIO 1
+
+/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
+#define HAVE_IOCTL_SIOCGIFADDR 1
+
+/* Define to 1 if you have the `resolve' library (-lresolve). */
+/* #undef HAVE_LIBRESOLVE */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* if your compiler supports LL */
+#define HAVE_LL 1
+
+/* Define to 1 if the compiler supports the 'long long' data type. */
+#define HAVE_LONGLONG 1
+
+/* Define to 1 if you have the malloc.h header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the memory.h header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the MSG_NOSIGNAL flag. */
+#define HAVE_MSG_NOSIGNAL 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have PF_INET6. */
+#define HAVE_PF_INET6 1
+
+/* Define to 1 if you have the recv function. */
+#define HAVE_RECV 1
+
+/* Define to 1 if you have the recvfrom function. */
+#define HAVE_RECVFROM 1
+
+/* Define to 1 if you have the send function. */
+#define HAVE_SEND 1
+
+/* Define to 1 if you have the setsockopt function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
+/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if sig_atomic_t is an available typedef. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if sig_atomic_t is already defined as volatile. */
+/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */
+
+/* Define to 1 if your struct sockaddr_in6 has sin6_scope_id. */
+#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+
+/* Define to 1 if you have the socket function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the <socket.h> header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the strcmpi function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the stricmp function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the strncmpi function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the strnicmp function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define to 1 if you have struct addrinfo. */
+#define HAVE_STRUCT_ADDRINFO 1
+
+/* Define to 1 if you have struct in6_addr. */
+#define HAVE_STRUCT_IN6_ADDR 1
+
+/* Define to 1 if you have struct sockaddr_in6. */
+#define HAVE_STRUCT_SOCKADDR_IN6 1
+
+/* if struct sockaddr_storage is defined */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if you have the timeval struct. */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the windows.h header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if you have the winsock2.h header file. */
+/* #undef HAVE_WINSOCK2_H */
+
+/* Define to 1 if you have the winsock.h header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define to 1 if you have the writev function. */
+#define HAVE_WRITEV 1
+
+/* Define to 1 if you have the ws2tcpip.h header file. */
+/* #undef HAVE_WS2TCPIP_H */
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if you need the malloc.h header file even with stdlib.h */
+/* #undef NEED_MALLOC_H */
+
+/* Define to 1 if you need the memory.h header file even with stdlib.h */
+/* #undef NEED_MEMORY_H */
+
+/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
+/* #undef NEED_REENTRANT */
+
+/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
+/* #undef NEED_THREAD_SAFE */
+
+/* cpu-machine-OS */
+#define OS "x86_64-unknown-openbsd6.2"
+
+/* Name of package */
+#define PACKAGE "c-ares"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "c-ares mailing list: http://cool.haxx.se/mailman/listinfo/c-ares"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "c-ares"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "c-ares 1.13.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "c-ares"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.13.0"
+
+/* a suitable file/device to read random data from */
+#define RANDOM_FILE "/dev/urandom"
+
+/* Define to the type qualifier pointed by arg 5 for recvfrom. */
+#define RECVFROM_QUAL_ARG5 
+
+/* Define to the type of arg 1 for recvfrom. */
+#define RECVFROM_TYPE_ARG1 int
+
+/* Define to the type pointed by arg 2 for recvfrom. */
+#define RECVFROM_TYPE_ARG2 void
+
+/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
+#define RECVFROM_TYPE_ARG2_IS_VOID 1
+
+/* Define to the type of arg 3 for recvfrom. */
+#define RECVFROM_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recvfrom. */
+#define RECVFROM_TYPE_ARG4 int
+
+/* Define to the type pointed by arg 5 for recvfrom. */
+#define RECVFROM_TYPE_ARG5 struct sockaddr
+
+/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
+/* #undef RECVFROM_TYPE_ARG5_IS_VOID */
+
+/* Define to the type pointed by arg 6 for recvfrom. */
+#define RECVFROM_TYPE_ARG6 socklen_t
+
+/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
+/* #undef RECVFROM_TYPE_ARG6_IS_VOID */
+
+/* Define to the function return type for recvfrom. */
+#define RECVFROM_TYPE_RETV ssize_t
+
+/* Define to the type of arg 1 for recv. */
+#define RECV_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for recv. */
+#define RECV_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for recv. */
+#define RECV_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for recv. */
+#define RECV_TYPE_ARG4 int
+
+/* Define to the function return type for recv. */
+#define RECV_TYPE_RETV ssize_t
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the type qualifier of arg 2 for send. */
+#define SEND_QUAL_ARG2 const
+
+/* Define to the type of arg 1 for send. */
+#define SEND_TYPE_ARG1 int
+
+/* Define to the type of arg 2 for send. */
+#define SEND_TYPE_ARG2 void *
+
+/* Define to the type of arg 3 for send. */
+#define SEND_TYPE_ARG3 size_t
+
+/* Define to the type of arg 4 for send. */
+#define SEND_TYPE_ARG4 int
+
+/* Define to the function return type for send. */
+#define SEND_TYPE_RETV ssize_t
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to disable non-blocking sockets. */
+/* #undef USE_BLOCKING_SOCKETS */
+
+/* Version number of package */
+#define VERSION "1.13.0"
+
+/* Define to avoid automatic inclusion of winsock.h */
+/* #undef WIN32_LEAN_AND_MEAN */
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* #  undef WORDS_BIGENDIAN */
+# endif
+#endif
+
+/* Define to 1 if OS is AIX. */
+#ifndef _ALL_SOURCE
+/* #  undef _ALL_SOURCE */
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Type to use in place of in_addr_t when system does not provide it. */
+/* #undef in_addr_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
diff --git a/tools/debug/core/error_ref_leak.py b/tools/debug/core/error_ref_leak.py
new file mode 100644
index 0000000..6582328
--- /dev/null
+++ b/tools/debug/core/error_ref_leak.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python2.7
+#
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Reads stdin to find error_refcount log lines, and prints reference leaks
+# to stdout
+
+# usege: python error_ref_leak < logfile.txt
+
+import sys
+import re
+
+data = sys.stdin.readlines()
+
+errs = []
+for line in data:
+  # if we care about the line
+  if re.search(r'error.cc', line):
+    # str manip to cut off left part of log line
+    line = line.partition('error.cc:')[-1]
+    line = re.sub(r'\d+] ', r'', line)
+    line = line.strip().split()
+    err = line[0].strip(":")
+    if line[1] == "create":
+      assert(err not in errs)
+      errs.append(err)
+    elif line[0] == "realloc":
+      errs.remove(line[1])
+      errs.append(line[3])
+    # explicitly look for the last dereference 
+    elif line[1] == "1" and line[3] == "0":
+      assert(err in errs)
+      errs.remove(err)
+
+print "leaked:", errs
diff --git a/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh
index 93aab40..c16efc1 100755
--- a/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh
+++ b/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh
@@ -17,17 +17,18 @@
 set -e
 
 mkdir -p /var/local/git
-git clone /var/local/jenkins/grpc /var/local/git/grpc
+git clone /var/local/jenkins/grpc-node /var/local/git/grpc-node
 # clone gRPC submodules, use data from locally cloned submodules where possible
-(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \
-&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \
+(cd /var/local/jenkins/grpc-node/ && git submodule foreach 'cd /var/local/git/grpc-node \
+&& git submodule update --init --recursive --reference /var/local/jenkins/grpc-node/${name} \
 ${name}')
 
 # copy service account keys if available
 cp -r /var/local/jenkins/service_account $HOME || true
 
-cd /var/local/git/grpc
+cd /var/local/git/grpc-node
 
 # build Node interop client & server
-npm install -g node-gyp
-npm install --unsafe-perm --build-from-source
+npm install -g node-gyp gulp
+npm install
+gulp setup
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 0f7e8cd..c9c6439 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1031,6 +1031,7 @@
 src/core/lib/support/atomic_with_atm.h \
 src/core/lib/support/atomic_with_std.h \
 src/core/lib/support/env.h \
+src/core/lib/support/manual_constructor.h \
 src/core/lib/support/memory.h \
 src/core/lib/support/mpscq.h \
 src/core/lib/support/murmur_hash.h \
@@ -1040,6 +1041,7 @@
 src/core/lib/support/string_windows.h \
 src/core/lib/support/time_precise.h \
 src/core/lib/support/tmpfile.h \
+src/core/lib/support/vector.h \
 src/core/lib/surface/alarm_internal.h \
 src/core/lib/surface/api_trace.h \
 src/core/lib/surface/call.h \
diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core
index b8514fe..c8fd2ee 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -772,6 +772,7 @@
 doc/connection-backoff.md \
 doc/connectivity-semantics-and-api.md \
 doc/core/grpc-error.md \
+doc/core/moving-to-c++.md \
 doc/core/pending_api_cleanups.md \
 doc/cpp-style-guide.md \
 doc/environment_variables.md \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index d465403..e053642 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -772,6 +772,7 @@
 doc/connection-backoff.md \
 doc/connectivity-semantics-and-api.md \
 doc/core/grpc-error.md \
+doc/core/moving-to-c++.md \
 doc/core/pending_api_cleanups.md \
 doc/cpp-style-guide.md \
 doc/environment_variables.md \
@@ -1019,6 +1020,7 @@
 src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
 src/core/ext/transport/chttp2/transport/chttp2_transport.h \
 src/core/ext/transport/chttp2/transport/flow_control.cc \
+src/core/ext/transport/chttp2/transport/flow_control.h \
 src/core/ext/transport/chttp2/transport/frame.h \
 src/core/ext/transport/chttp2/transport/frame_data.cc \
 src/core/ext/transport/chttp2/transport/frame_data.h \
@@ -1320,6 +1322,7 @@
 src/core/lib/support/log_linux.cc \
 src/core/lib/support/log_posix.cc \
 src/core/lib/support/log_windows.cc \
+src/core/lib/support/manual_constructor.h \
 src/core/lib/support/memory.h \
 src/core/lib/support/mpscq.cc \
 src/core/lib/support/mpscq.h \
@@ -1352,6 +1355,7 @@
 src/core/lib/support/tmpfile_msys.cc \
 src/core/lib/support/tmpfile_posix.cc \
 src/core/lib/support/tmpfile_windows.cc \
+src/core/lib/support/vector.h \
 src/core/lib/support/wrap_memcpy.cc \
 src/core/lib/surface/README.md \
 src/core/lib/surface/alarm.cc \
diff --git a/tools/gce/create_linux_kokoro_performance_worker.sh b/tools/gce/create_linux_kokoro_performance_worker.sh
new file mode 100755
index 0000000..0fdb43c
--- /dev/null
+++ b/tools/gce/create_linux_kokoro_performance_worker.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Creates a performance worker on GCE to be used on Kokoro.
+
+set -ex
+
+cd $(dirname $0)
+
+CLOUD_PROJECT=grpc-testing
+ZONE=us-central1-b  # this zone allows 32core machines
+
+INSTANCE_NAME="${1:-grpc-kokoro-performance-server1}"
+MACHINE_TYPE=n1-standard-32
+
+gcloud compute instances create $INSTANCE_NAME \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    --machine-type $MACHINE_TYPE \
+    --image-project ubuntu-os-cloud \
+    --image-family ubuntu-1704 \
+    --boot-disk-size 300 \
+    --scopes https://www.googleapis.com/auth/bigquery \
+    --tags=allow-ssh
+
+echo 'Created GCE instance, waiting 60 seconds for it to come online.'
+sleep 60
+
+gcloud compute copy-files \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    kokoro_performance.pub linux_kokoro_performance_worker_init.sh kbuilder@${INSTANCE_NAME}:~
+
+gcloud compute ssh \
+    --project="$CLOUD_PROJECT" \
+    --zone "$ZONE" \
+    kbuilder@${INSTANCE_NAME} --command "./linux_kokoro_performance_worker_init.sh"
diff --git a/tools/gce/kokoro_performance.pub b/tools/gce/kokoro_performance.pub
new file mode 100644
index 0000000..1154deb
--- /dev/null
+++ b/tools/gce/kokoro_performance.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKQ5UEX4AFefec9BKICupFS7x9Hoq4ZyLKy+QX0J31I49ew9mG2AJlr3sp8ql15eX+A2Ml9MKJkmgZGHpJtw+SfvmI94SmomSyiCLAK92sQ85NMzaRdo4b9e30E9nhXnAvAaemvIEQbgCMYFvzk0C8AtXj6+htCrN4jFaLqTCPISJhX3ETc4TgX1qaHQHyl31tdaXHYlITvBDsfokcGcZQnhmCUDtD8wyaSC8GFk9gZbXshkfaYCuuLPPA0vwWGBw+YPbonHsFCsOog1IYSzYPCkIjq8dt6evsusK6Kaoyw/Z+l2kYty2FKTj+wU3l06QMoxwcfNT4WxdhcnVbY71r kbuilder@kokoro-performance-driver
diff --git a/tools/gce/linux_kokoro_performance_worker_init.sh b/tools/gce/linux_kokoro_performance_worker_init.sh
new file mode 100755
index 0000000..ac3d393
--- /dev/null
+++ b/tools/gce/linux_kokoro_performance_worker_init.sh
@@ -0,0 +1,181 @@
+#!/bin/bash
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Initializes a fresh GCE VM to become a Kokoro Linux performance worker.
+# You shouldn't run this script on your own,
+# use create_linux_kokoro_performance_worker.sh instead.
+
+set -ex
+
+sudo apt-get update
+
+# Install Java 8 JDK (to build gRPC Java)
+sudo apt-get install -y openjdk-8-jdk
+sudo apt-get install -y unzip lsof
+
+sudo apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  gyp \
+  lcov \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libcurl4-openssl-dev \
+  libgtest-dev \
+  libreadline-dev \
+  libssl-dev \
+  libtool \
+  make \
+  strace \
+  pypy \
+  python-dev \
+  python-pip \
+  python-setuptools \
+  python-yaml \
+  python3-dev \
+  python3-pip \
+  python3-setuptools \
+  python3-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip \
+  zlib1g-dev
+
+# perftools
+sudo apt-get install -y google-perftools libgoogle-perftools-dev
+
+# netperf
+sudo apt-get install -y netperf
+
+# C++ dependencies
+sudo apt-get install -y libgflags-dev libgtest-dev libc++-dev clang
+
+# Python dependencies
+sudo pip install --upgrade pip==9.0.1
+sudo pip install tabulate
+sudo pip install google-api-python-client
+sudo pip install virtualenv
+
+# Building gRPC Python depends on python3.4 being installed, but python3.4
+# is not available on Ubuntu 16.10, so install from source
+curl -O https://www.python.org/ftp/python/3.4.6/Python-3.4.6.tgz
+tar xzvf Python-3.4.6.tgz
+cd Python-3.4.6
+./configure --enable-shared --prefix=/usr/local LDFLAGS="-Wl,--rpath=/usr/local/lib"
+sudo make altinstall
+cd ..
+rm Python-3.4.6.tgz
+
+curl -O https://bootstrap.pypa.io/get-pip.py
+sudo pypy get-pip.py
+sudo pypy -m pip install tabulate
+sudo pip install google-api-python-client
+
+# Node dependencies (nvm has to be installed under user kbuilder)
+touch .profile
+curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
+source ~/.nvm/nvm.sh
+nvm install 0.12 && npm config set cache /tmp/npm-cache
+nvm install 4 && npm config set cache /tmp/npm-cache
+nvm install 5 && npm config set cache /tmp/npm-cache
+nvm alias default 4
+
+# C# mono dependencies (http://www.mono-project.com/docs/getting-started/install/linux/#debian-ubuntu-and-derivatives)
+sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
+sudo apt-get update
+sudo apt-get install -y mono-devel nuget
+
+# C# .NET Core dependencies (https://www.microsoft.com/net/core#ubuntu)
+sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ yakkety main" > /etc/apt/sources.list.d/dotnetdev.list'
+sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
+sudo apt-get update
+sudo apt-get install -y dotnet-dev-1.0.0-preview2.1-003155
+sudo apt-get install -y dotnet-dev-1.0.1
+
+# Ruby dependencies
+gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
+curl -sSL https://get.rvm.io | bash -s stable --ruby
+source ~/.rvm/scripts/rvm
+
+git clone https://github.com/rbenv/rbenv.git ~/.rbenv
+export PATH="$HOME/.rbenv/bin:$PATH"
+eval "$(rbenv init -)"
+
+git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
+export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"
+
+rbenv install 2.4.0
+rbenv global 2.4.0
+ruby -v
+
+# Install bundler (prerequisite for gRPC Ruby)
+gem install bundler
+
+# PHP dependencies
+sudo apt-get install -y php php-dev phpunit php-pear unzip zlib1g-dev
+curl -sS https://getcomposer.org/installer | php
+sudo mv composer.phar /usr/local/bin/composer
+
+# Java dependencies - nothing as we already have Java JDK 8
+
+# Go dependencies
+# Currently, the golang package available via apt-get doesn't have the latest go.
+# Significant performance improvements with grpc-go have been observed after
+# upgrading from go 1.5 to a later version, so a later go version is preferred.
+# Following go install instructions from https://golang.org/doc/install
+GO_VERSION=1.8
+OS=linux
+ARCH=amd64
+curl -O https://storage.googleapis.com/golang/go${GO_VERSION}.${OS}-${ARCH}.tar.gz
+sudo tar -C /usr/local -xzf go$GO_VERSION.$OS-$ARCH.tar.gz
+# Put go on the PATH, keep the usual installation dir
+sudo ln -s /usr/local/go/bin/go /usr/bin/go
+rm go$GO_VERSION.$OS-$ARCH.tar.gz
+
+# Install perf, to profile benchmarks. (need to get the right linux-tools-<> for kernel version)
+sudo apt-get install -y linux-tools-common linux-tools-generic linux-tools-`uname -r`
+# see http://unix.stackexchange.com/questions/14227/do-i-need-root-admin-permissions-to-run-userspace-perf-tool-perf-events-ar
+echo 0 | sudo tee /proc/sys/kernel/perf_event_paranoid
+# see http://stackoverflow.com/questions/21284906/perf-couldnt-record-kernel-reference-relocation-symbol
+echo 0 | sudo tee /proc/sys/kernel/kptr_restrict
+
+# qps workers under perf appear to need a lot of mmap pages under certain scenarios and perf args in
+# order to not lose perf events or time out
+echo 4096 | sudo tee /proc/sys/kernel/perf_event_mlock_kb
+
+# Fetch scripts to generate flame graphs from perf data collected
+# on benchmarks
+git clone -v https://github.com/brendangregg/FlameGraph ~/FlameGraph
+
+# Install scipy and numpy for benchmarking scripts
+sudo apt-get install -y python-scipy python-numpy
+
+# Add pubkey of Kokoro driver VM to allow SSH
+cat kokoro_performance.pub | sudo tee --append ~kbuilder/.ssh/authorized_keys
+
+# Restart for VM to pick up kernel update
+echo 'Successfully initialized the linux worker, going for reboot in 10 seconds'
+sleep 10
+sudo reboot
diff --git a/tools/internal_ci/helper_scripts/gen_report_index.sh b/tools/internal_ci/helper_scripts/gen_report_index.sh
index 0af89c3..576ff67 100755
--- a/tools/internal_ci/helper_scripts/gen_report_index.sh
+++ b/tools/internal_ci/helper_scripts/gen_report_index.sh
@@ -26,7 +26,7 @@
 
 echo '<html><head></head><body>' > reports/kokoro_index.html
 echo '<h1>'${KOKORO_JOB_NAME}', build '#${KOKORO_BUILD_NUMBER}'</h1>' >> reports/kokoro_index.html
-echo '<h2><a href="https://kokoro.corp.google.com/job/'${KOKORO_JOB_PATH}'/'${KOKORO_BUILD_NUMBER}'/">Kokoro build dashboard (internal only)</a></h2>' >> reports/kokoro_index.html
+echo '<h2><a href="https://kokoro2.corp.google.com/job/'${KOKORO_JOB_PATH}'/'${KOKORO_BUILD_NUMBER}'/">Kokoro build dashboard (internal only)</a></h2>' >> reports/kokoro_index.html
 echo '<h2><a href="https://sponge.corp.google.com/invocation?id='${KOKORO_BUILD_ID}'&searchFor=">Test result dashboard (internal only)</a></h2>' >> reports/kokoro_index.html
 echo '<h2><a href="test_report.html">HTML test report (Not available yet)</a></h2>' >> reports/kokoro_index.html
 echo '<h2><a href="test_log.txt">Test log (Not available yet)</a></h2>' >> reports/kokoro_index.html
diff --git a/tools/internal_ci/helper_scripts/prepare_build_interop_rc b/tools/internal_ci/helper_scripts/prepare_build_interop_rc
index 859ce62..db978c8 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_interop_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_interop_rc
@@ -26,6 +26,7 @@
 # Set up gRPC-Go and gRPC-Java to test
 git clone --recursive https://github.com/grpc/grpc-go ./../grpc-go
 git clone --recursive https://github.com/grpc/grpc-java ./../grpc-java
+git clone --recursive https://github.com/grpc/grpc-node ./../grpc-node
 
 # Download json file.
 mkdir ~/service_account
diff --git a/tools/internal_ci/helper_scripts/prepare_build_linux_rc b/tools/internal_ci/helper_scripts/prepare_build_linux_rc
index 2ade8da..ea2a17f 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_linux_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_linux_rc
@@ -32,11 +32,4 @@
 # Download Docker images from DockerHub
 export DOCKERHUB_ORGANIZATION=grpctesting
 
-# If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests
-if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ] && [ -n "$RUN_TESTS_FLAGS" ]; then
-  sudo apt-get install -y jq
-  ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref)
-  export RUN_TESTS_FLAGS="$RUN_TESTS_FLAGS --filter_pr_tests --base_branch origin/$ghprbTargetBranch"	
-fi
-
 git submodule update --init
diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc
index f467ac0..bb046de 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc
@@ -30,6 +30,7 @@
 # Set up gRPC-Go and gRPC-Java to test
 git clone --recursive https://github.com/grpc/grpc-go ./../grpc-go
 git clone --recursive https://github.com/grpc/grpc-java ./../grpc-java
+git clone --recursive https://github.com/grpc/grpc-node ./../grpc-node
 
 # Set up Docker for Mac
 docker-machine create -d virtualbox --virtualbox-share-folder "/Users/kbuilder/workspace:" default
diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc
index b6cc43e..bd8c8eb 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc
@@ -41,6 +41,7 @@
 
 # If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests
 if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ] && [ -n "$RUN_TESTS_FLAGS" ]; then
+  brew update
   brew install jq
   ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref)
   export RUN_TESTS_FLAGS="$RUN_TESTS_FLAGS --filter_pr_tests --base_branch origin/$ghprbTargetBranch"
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.cfg b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
deleted file mode 100644
index ec738fc..0000000
--- a/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2017 gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# 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"
-    regex: "github/grpc/reports/**"
-  }
-}
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.sh b/tools/internal_ci/linux/grpc_interop_badserver_python.sh
deleted file mode 100755
index c2bd4e7..0000000
--- a/tools/internal_ci/linux/grpc_interop_badserver_python.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2017 gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -ex
-
-export LANG=en_US.UTF-8
-
-# Enter the gRPC repo root
-cd $(dirname $0)/../../..
-
-source tools/internal_ci/helper_scripts/prepare_build_linux_rc
-source tools/internal_ci/helper_scripts/prepare_build_interop_rc
-
-tools/run_tests/run_interop_tests.py -l python --use_docker --http2_server_interop
-
diff --git a/tools/internal_ci/linux/grpc_interop_matrix.sh b/tools/internal_ci/linux/grpc_interop_matrix.sh
index e199d48..4c24c43 100755
--- a/tools/internal_ci/linux/grpc_interop_matrix.sh
+++ b/tools/internal_ci/linux/grpc_interop_matrix.sh
@@ -22,4 +22,4 @@
 
 source tools/internal_ci/helper_scripts/prepare_build_linux_rc
 
-tools/interop_matrix/run_interop_matrix_tests.py --language=all --release=all --report_file=sponge_log.xml $@
+tools/interop_matrix/run_interop_matrix_tests.py --language=all --release=all --allow_flakes --report_file=sponge_log.xml --bq_result_table interop_results $@
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.cfg b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
index 2803616..13aec15 100644
--- a/tools/internal_ci/linux/grpc_interop_tocloud.cfg
+++ b/tools/internal_ci/linux/grpc_interop_tocloud.cfg
@@ -15,8 +15,7 @@
 # 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.
+build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
 timeout_mins: 60
 action {
   define_artifacts {
@@ -24,3 +23,8 @@
     regex: "github/grpc/reports/**"
   }
 }
+
+env_vars {
+  key: "RUN_TESTS_FLAGS"
+  value: "-l all -s all --use_docker --http2_interop --internal_ci -t -j 12 --bq_result_table interop_results"
+}
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.sh b/tools/internal_ci/linux/grpc_interop_tocloud.sh
deleted file mode 100755
index e3ba25a..0000000
--- a/tools/internal_ci/linux/grpc_interop_tocloud.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2017 gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -ex
-
-export LANG=en_US.UTF-8
-
-# Enter the gRPC repo root
-cd $(dirname $0)/../../..
-
-source tools/internal_ci/helper_scripts/prepare_build_linux_rc
-source tools/internal_ci/helper_scripts/prepare_build_interop_rc
-
-tools/run_tests/run_interop_tests.py -l all -s all --use_docker --http2_interop --internal_ci -t -j 12 $@
diff --git a/tools/internal_ci/linux/grpc_interop_toprod.cfg b/tools/internal_ci/linux/grpc_interop_toprod.cfg
index 903480a..8d025c4 100644
--- a/tools/internal_ci/linux/grpc_interop_toprod.cfg
+++ b/tools/internal_ci/linux/grpc_interop_toprod.cfg
@@ -15,8 +15,7 @@
 # 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_toprod.sh"
-# grpc_interop tests can take 6+ hours to complete.
+build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
 timeout_mins: 60
 action {
   define_artifacts {
@@ -25,3 +24,7 @@
   }
 }
 
+env_vars {
+  key: "RUN_TESTS_FLAGS"
+  value: "-l all --cloud_to_prod --cloud_to_prod_auth --prod_servers default gateway_v4 --use_docker --internal_ci -t -j 12 --bq_result_table interop_results"
+}
diff --git a/tools/internal_ci/linux/grpc_interop_toprod.sh b/tools/internal_ci/linux/grpc_interop_toprod.sh
deleted file mode 100755
index 97a7d5d..0000000
--- a/tools/internal_ci/linux/grpc_interop_toprod.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2017 gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -ex
-
-export LANG=en_US.UTF-8
-
-# Enter the gRPC repo root
-cd $(dirname $0)/../../..
-
-source tools/internal_ci/helper_scripts/prepare_build_linux_rc
-source tools/internal_ci/helper_scripts/prepare_build_interop_rc
-
-tools/run_tests/run_interop_tests.py \
-    -l all \
-    --cloud_to_prod \
-    --cloud_to_prod_auth \
-    --prod_servers default gateway_v4 \
-    --use_docker --internal_ci --allow_flakes -t -j 12 $@
-
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.sh b/tools/internal_ci/linux/grpc_run_interop_tests.sh
similarity index 88%
rename from tools/internal_ci/linux/grpc_interop_badserver_java.sh
rename to tools/internal_ci/linux/grpc_run_interop_tests.sh
index d25845c..1f4eda2 100755
--- a/tools/internal_ci/linux/grpc_interop_badserver_java.sh
+++ b/tools/internal_ci/linux/grpc_run_interop_tests.sh
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/bin/bash
 # Copyright 2017 gRPC authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,5 +23,4 @@
 source tools/internal_ci/helper_scripts/prepare_build_linux_rc
 source tools/internal_ci/helper_scripts/prepare_build_interop_rc
 
-tools/run_tests/run_interop_tests.py -l java --use_docker --http2_server_interop
-
+tools/run_tests/run_interop_tests.py $RUN_TESTS_FLAGS
diff --git a/tools/internal_ci/linux/grpc_run_tests_matrix.sh b/tools/internal_ci/linux/grpc_run_tests_matrix.sh
index bd1430b..1018708 100755
--- a/tools/internal_ci/linux/grpc_run_tests_matrix.sh
+++ b/tools/internal_ci/linux/grpc_run_tests_matrix.sh
@@ -20,6 +20,13 @@
 
 source tools/internal_ci/helper_scripts/prepare_build_linux_rc
 
+# If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests
+if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ] && [ -n "$RUN_TESTS_FLAGS" ]; then
+  sudo apt-get install -y jq
+  ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref)
+  export RUN_TESTS_FLAGS="$RUN_TESTS_FLAGS --filter_pr_tests --base_branch origin/$ghprbTargetBranch"
+fi
+
 tools/run_tests/run_tests_matrix.py $RUN_TESTS_FLAGS || FAILED="true"
 
 # Reveal leftover processes that might be left behind by the build
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg
similarity index 76%
rename from tools/internal_ci/linux/grpc_interop_badserver_java.cfg
rename to tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg
index dc21142..cb18e8e 100644
--- a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg
@@ -15,12 +15,16 @@
 # 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
+build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
+timeout_mins: 60
 action {
   define_artifacts {
-    regex: "**/report.xml"
+    regex: "**/sponge_log.xml"
     regex: "github/grpc/reports/**"
   }
 }
+
+env_vars {
+  key: "RUN_TESTS_FLAGS"
+  value: "-l all -s all --use_docker --http2_interop --internal_ci -t -j 12"
+}
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
similarity index 71%
copy from tools/internal_ci/linux/grpc_interop_badserver_java.cfg
copy to tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
index dc21142..e141d9f 100644
--- a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
@@ -15,12 +15,16 @@
 # 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
+build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
+timeout_mins: 60
 action {
   define_artifacts {
-    regex: "**/report.xml"
+    regex: "**/sponge_log.xml"
     regex: "github/grpc/reports/**"
   }
 }
+
+env_vars {
+  key: "RUN_TESTS_FLAGS"
+  value: "-l all --allow_flakes --cloud_to_prod --cloud_to_prod_auth --prod_servers default gateway_v4 --use_docker --internal_ci -t -j 12"
+}
diff --git a/tools/interop_matrix/README.md b/tools/interop_matrix/README.md
index c2f3543..a3717a5 100644
--- a/tools/interop_matrix/README.md
+++ b/tools/interop_matrix/README.md
@@ -5,32 +5,21 @@
 The setup builds gRPC docker images for each language/runtime and upload it to Google Container Registry (GCR). These images, encapsulating gRPC stack
 from specific releases/tag, are used to test version compatiblity between gRPC release versions.
 
-## Step-by-step instructions for adding a new release to compatibility test
+## Step-by-step instructions for adding a GCR image for a new release for compatibility test
 We have continuous nightly test setup to test gRPC backward compatibility between old clients and latest server.  When a gRPC developer creates a new gRPC release, s/he is also responsible to add the just-released gRPC client to the nightly test.  The steps are:
-- Add (or update) an entry in ./client_matrix.py file to reference the github tag for the release.
+- Add (or update) an entry in `./client_matrix.py` file to reference the github tag for the release.
 - Build new client docker image(s).  For example, for java release `v1.9.9`, do
   - `tools/interop_matrix/create_matrix_images.py --git_checkout --release=v1.9.9 --language=java`
 - Verify that the new docker image was built successfully and uploaded to GCR.  For example,
-  - `gcloud beta container images list-tags gcr.io/grpc-testing/grpc_interop_java_oracle8`
-  - should show an image entry with tag `v1.9.9`.
+  - `gcloud beta container images list --repository gcr.io/grpc-testing` shows image repos.
+  - `gcloud beta container images list-tags gcr.io/grpc-testing/grpc_interop_java_oracle8` should show an image entry with tag `v1.9.9`.
 - Verify the just-created docker client image would pass backward compatibility test (it should).  For example,
   - `gcloud docker -- pull gcr.io/grpc-testing/grpc_interop_java_oracle8:v1.9.9` followed by
-  - `docker_image=gcr.io/grpc-testing/grpc_interop_java_oracle8:v1.9.9 ./testcases/java__master`
+  - `docker_image=gcr.io/grpc-testing/grpc_interop_java_oracle8:v1.9.9 tools/interop_matrix/testcases/java__master`
 - git commit the change and merge it to upstream/master.
 - (Optional) clean up the tmp directory to where grpc source is cloned at `/export/hda3/tmp/grpc_matrix/`.
 For more details on each step, refer to sections below.
 
-## Instructions for creating GCR images
-- Edit  `./client_matrix.py` to include desired gRPC release.
-- Run `tools/interop_matrix/create_matrix_images.py`.  Useful options:
-  - `--git_checkout` enables git checkout grpc release branch/tag.
-  - `--release` specifies a git release tag.  Make sure it is a valid tag in the grpc github rep.
-  - `--language` specifies a language.
-  For example, To build all languages for all gRPC releases across all runtimes, do `tools/interop_matrix/create_matrix_images.py --git_checkout --release=all`.
-- Verify the newly created docker images are uploaded to GCR.  For example:
-  - `gcloud beta container images list --repository gcr.io/grpc-testing` shows image repos.
-  - `gcloud beta container images list-tags gcr.io/grpc-testing/grpc_interop_go1.7` show tags for a image repo.
-
 ## Instructions for adding new language/runtimes*
 - Create new `Dockerfile.template`, `build_interop.sh.template` for the language/runtime under `template/tools/dockerfile/`.
 - Run `tools/buildgen/generate_projects.sh` to create corresponding files under `tools/dockerfile/`.
@@ -47,7 +36,7 @@
 
 ## Instructions for running test cases against GCR images
 - Run `tools/interop_matrix/run_interop_matrix_tests.py`.  Useful options:
-  - `--release` specifies a git release tag.  Defaults to `--release=master`.  Make sure the GCR images with the tag have been created using `create_matrix_images.py` above.
+  - `--release` specifies a git release tag.  Defaults to `--release=all`.  Make sure the GCR images with the tag have been created using `create_matrix_images.py` above.
   - `--language` specifies a language.  Defaults to `--language=all`.
   For example, To test all languages for all gRPC releases across all runtimes, do `tools/interop_matrix/run_interop_matrix_test.py --release=all`.
 - The output for all the test cases is recorded in a junit style xml file (default to 'report.xml').
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
index 4d1b5f0..23c5ae0 100644
--- a/tools/interop_matrix/client_matrix.py
+++ b/tools/interop_matrix/client_matrix.py
@@ -38,12 +38,16 @@
         'v1.2.5',
         'v1.3.9',
         'v1.4.2',
+        'v1.6.6',
     ],
     'go': [
         'v1.0.5',
         'v1.2.1',
         'v1.3.0',
         'v1.4.2',
+        'v1.5.2',
+        'v1.6.0',
+        'v1.7.0',
     ],
     'java': [
         'v1.0.3',
@@ -52,5 +56,7 @@
         'v1.3.1',
         'v1.4.0',
         'v1.5.0',
+        'v1.6.1',
+        'v1.7.0',
     ],
 }
diff --git a/tools/interop_matrix/create_matrix_images.py b/tools/interop_matrix/create_matrix_images.py
index 119cbd2..67355e7 100755
--- a/tools/interop_matrix/create_matrix_images.py
+++ b/tools/interop_matrix/create_matrix_images.py
@@ -174,7 +174,7 @@
   # If we not using current tree or the sibling for grpc stack, do checkout.
   if args.git_checkout:
     stack_base = checkout_grpc_stack(lang, release)
-    var ={'go': 'GRPC_GO_ROOT', 'java': 'GRPC_JAVA_ROOT'}.get(lang, 'GRPC_ROOT')
+    var ={'go': 'GRPC_GO_ROOT', 'java': 'GRPC_JAVA_ROOT', 'node': 'GRPC_NODE_ROOT'}.get(lang, 'GRPC_ROOT')
     env[var] = stack_base
 
   for runtime in client_matrix.LANG_RUNTIME_MATRIX[lang]:
diff --git a/tools/interop_matrix/create_testcases.sh b/tools/interop_matrix/create_testcases.sh
index d06fb34..3d34b2e 100755
--- a/tools/interop_matrix/create_testcases.sh
+++ b/tools/interop_matrix/create_testcases.sh
@@ -31,9 +31,12 @@
 
 echo "Create '$LANG' test cases for gRPC release '${RELEASE:=master}'"
 
+echo $client_lang
 # Invoke run_interop_test in manual mode.
+# TODO(adelez): Add cloud_gateways when we figure out how to skip them if not 
+# running in GCE.
 ${GRPC_ROOT}/tools/run_tests/run_interop_tests.py -l $LANG --use_docker \
-  --cloud_to_prod --manual_run
+  --cloud_to_prod --prod_servers default gateway_v4 --manual_run
 
 # Clean up
 function cleanup {
@@ -52,11 +55,18 @@
   [ -e "$CMDS_SH" ] && rm $CMDS_SH
 }
 trap cleanup EXIT
+# TODO(adelez): add test auth tests but do not run if not testing on GCE.
 # Running the testcases as sanity unless we are asked to skip.
 [ -z "$SKIP_TEST" ] && (echo "Running test cases: $CMDS_SH"; sh $CMDS_SH)
 
+# Convert c++ to cxx. 
+if [$LANG == "c++" ]; then
+client_lang="cxx"
+else
+client_lang=$LANG
+fi
 mkdir -p $TESTCASES_DIR
-testcase=$TESTCASES_DIR/${LANG}__$RELEASE
+testcase=$TESTCASES_DIR/${client_lang}__$RELEASE
 if [ -e $testcase ]; then
   echo "Updating: $testcase"
   diff $testcase $CMDS_SH || true
diff --git a/tools/interop_matrix/run_interop_matrix_tests.py b/tools/interop_matrix/run_interop_matrix_tests.py
index 4315c82..d037e13 100755
--- a/tools/interop_matrix/run_interop_matrix_tests.py
+++ b/tools/interop_matrix/run_interop_matrix_tests.py
@@ -36,6 +36,7 @@
 import dockerjob
 import jobset
 import report_utils
+import upload_test_results
 
 _LANGUAGES = client_matrix.LANG_RUNTIME_MATRIX.keys()
 # All gRPC release tags, flattened, deduped and sorted.
@@ -48,9 +49,8 @@
 argp.add_argument('--gcr_path',
                   default='gcr.io/grpc-testing',
                   help='Path of docker images in Google Container Registry')
-
 argp.add_argument('--release',
-                  default='master',
+                  default='all',
                   choices=['all', 'master'] + _RELEASES,
                   help='Release tags to test.  When testing all '
                   'releases defined in client_matrix.py, use "all".')
@@ -69,6 +69,18 @@
                   default='report.xml',
                   help='The result file to create.')
 
+argp.add_argument('--allow_flakes',
+                  default=False,
+                  action='store_const',
+                  const=True,
+                  help=('Allow flaky tests to show as passing (re-runs failed '
+                        'tests up to five times)'))
+argp.add_argument('--bq_result_table',
+                  default='',
+                  type=str,
+                  nargs='?',
+                  help='Upload test results to a specified BQ table.')
+
 args = argp.parse_args()
 
 
@@ -94,14 +106,15 @@
   for runtime in client_matrix.LANG_RUNTIME_MATRIX[lang]:
     image_path = '%s/grpc_interop_%s' % (args.gcr_path, runtime)
     output = subprocess.check_output(['gcloud', 'beta', 'container', 'images',
-                                        'list-tags', '--format=json', image_path])
+                                      'list-tags', '--format=json', image_path])
     docker_image_list = json.loads(output)
     # All images should have a single tag or no tag.
+    # TODO(adelez): Remove tagless images.
     tags = [i['tags'][0] for i in docker_image_list if i['tags']]
     jobset.message('START', 'Found images for %s: %s' % (image_path, tags),
                    do_newline=True)
     skipped = len(docker_image_list) - len(tags)
-    jobset.message('START', 'Skipped images (no-tag/unknown-tag): %d' % skipped,
+    jobset.message('SKIPPED', 'Skipped images (no-tag/unknown-tag): %d' % skipped,
                    do_newline=True)
     # Filter tags based on the releases.
     images[runtime] = [(tag,'%s:%s' % (image_path,tag)) for tag in tags if
@@ -110,7 +123,7 @@
 
 # caches test cases (list of JobSpec) loaded from file.  Keyed by lang and runtime.
 _loaded_testcases = {}
-def find_test_cases(lang, release):
+def find_test_cases(lang, release, suite_name):
   """Returns the list of test cases from testcase files per lang/release."""
   file_tmpl = os.path.join(os.path.dirname(__file__), 'testcases/%s__%s')
   if not os.path.exists(file_tmpl % (lang, release)):
@@ -127,10 +140,15 @@
         if line.startswith('docker run'):
           m = re.search('--test_case=(.*)"', line)
           shortname = m.group(1) if m else 'unknown_test'
+          m = re.search('--server_host_override=(.*).sandbox.googleapis.com', 
+                        line)
+          server = m.group(1) if m else 'unknown_server'
           spec = jobset.JobSpec(cmdline=line,
-                                shortname=shortname,
+                                shortname='%s:%s:%s:%s' % (suite_name, lang, 
+                                                           server, shortname),
                                 timeout_seconds=_TEST_TIMEOUT,
-                                shell=True)
+                                shell=True,
+                                flake_retries=5 if args.allow_flakes else 0)
           job_spec_list.append(spec)
       jobset.message('START',
                      'Loaded %s tests from %s' % (len(job_spec_list), testcases),
@@ -148,19 +166,25 @@
 
   images is a list of (<release-tag>, <image-full-path>) tuple.
   """
+  total_num_failures = 0
   for image_tuple in images:
     release, image = image_tuple
     jobset.message('START', 'Testing %s' % image, do_newline=True)
     # Download the docker image before running each test case.
     subprocess.check_call(['gcloud', 'docker', '--', 'pull', image])
     _docker_images_cleanup.append(image)
-    job_spec_list = find_test_cases(lang,release)
+    suite_name = '%s__%s_%s' % (lang, runtime, release)
+    job_spec_list = find_test_cases(lang, release, suite_name)
     num_failures, resultset = jobset.run(job_spec_list,
                                          newline_on_success=True,
                                          add_env={'docker_image':image},
                                          maxjobs=args.jobs)
+    if args.bq_result_table and resultset:
+      upload_test_results.upload_interop_results_to_bq(
+          resultset, args.bq_result_table, args)
     if num_failures:
       jobset.message('FAILED', 'Some tests failed', do_newline=True)
+      total_num_failures += num_failures
     else:
       jobset.message('SUCCESS', 'All tests passed', do_newline=True)
 
@@ -168,8 +192,11 @@
         _xml_report_tree,
         resultset,
         'grpc_interop_matrix',
-        '%s__%s %s'%(lang,runtime,release),
+        suite_name,
         str(uuid.uuid4()))
+  
+  return total_num_failures
+
 
 _docker_images_cleanup = []
 def cleanup():
@@ -180,9 +207,14 @@
 atexit.register(cleanup)
 
 languages = args.language if args.language != ['all'] else _LANGUAGES
+total_num_failures = 0
 for lang in languages:
   docker_images = find_all_images_for_lang(lang)
   for runtime in sorted(docker_images.keys()):
-    run_tests_for_lang(lang, runtime, docker_images[runtime])
+    total_num_failures += run_tests_for_lang(lang, runtime, docker_images[runtime])
 
 report_utils.create_xml_report_file(_xml_report_tree, args.report_file)
+
+if total_num_failures:
+  sys.exit(1)
+sys.exit(0)
diff --git a/tools/interop_matrix/testcases/cxx__master b/tools/interop_matrix/testcases/cxx__master
index ccd2859..e0fed53 100755
--- a/tools/interop_matrix/testcases/cxx__master
+++ b/tools/interop_matrix/testcases/cxx__master
@@ -1,5 +1,5 @@
 #!/bin/bash
-echo "Testing ${docker_image:=grpc_interop_cxx:1423f288-ac00-4f3a-9885-771258eecae3}"
+echo "Testing ${docker_image:=grpc_interop_cxx:78de6f80-524d-4bc9-bfb2-f00c24ceafed}"
 docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary"
 docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary"
 docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
@@ -9,3 +9,12 @@
 docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin"
 docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response"
 docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "bins/opt/interop_client --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server"
diff --git a/tools/interop_matrix/testcases/go__master b/tools/interop_matrix/testcases/go__master
index 2624c7f..33b25d6 100755
--- a/tools/interop_matrix/testcases/go__master
+++ b/tools/interop_matrix/testcases/go__master
@@ -1,5 +1,5 @@
 #!/bin/bash
-echo "Testing ${docker_image:=grpc_interop_go:41fffd01-a6c8-41b6-8136-c0aaa1ec2437}"
+echo "Testing ${docker_image:=grpc_interop_go:dd8fbf3a-4964-4387-9997-5dadeea09835}"
 docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary"
 docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary"
 docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
@@ -9,3 +9,12 @@
 docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin"
 docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response"
 docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server"
diff --git a/tools/interop_matrix/testcases/java__master b/tools/interop_matrix/testcases/java__master
index cf43164..dbd8727 100755
--- a/tools/interop_matrix/testcases/java__master
+++ b/tools/interop_matrix/testcases/java__master
@@ -1,5 +1,5 @@
 #!/bin/bash
-echo "Testing ${docker_image:=grpc_interop_java:ea528843-be34-4ff3-a136-e4609424e061}"
+echo "Testing ${docker_image:=grpc_interop_java:a764b50c-1788-4387-9b9e-5cfa93927006}"
 docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary"
 docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary"
 docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
@@ -9,3 +9,12 @@
 docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin"
 docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response"
 docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response"
+docker run -i --rm=true -w /var/local/git/grpc/../grpc-java --net=host $docker_image bash -c "./run-test-client.sh --server_host=216.239.32.254 --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server"
diff --git a/tools/profiling/microbenchmarks/bm_json.py b/tools/profiling/microbenchmarks/bm_json.py
index f6082fe..eb450ee 100644
--- a/tools/profiling/microbenchmarks/bm_json.py
+++ b/tools/profiling/microbenchmarks/bm_json.py
@@ -76,7 +76,7 @@
     'dyn': ['end_of_stream', 'request_size'],
   },
   'BM_HpackParserParseHeader': {
-    'tpl': ['fixture'],
+    'tpl': ['fixture', 'on_header'],
     'dyn': [],
   },
   'BM_CallCreateDestroy': {
@@ -157,6 +157,9 @@
     rest = s[0]
     dyn_args = s[1:]
   name = rest
+  print (name)
+  print (dyn_args, _BM_SPECS[name]['dyn'])
+  print (tpl_args, _BM_SPECS[name]['tpl'])
   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'])
diff --git a/tools/run_tests/dockerize/build_interop_image.sh b/tools/run_tests/dockerize/build_interop_image.sh
index 9d8ad53..09e0629 100755
--- a/tools/run_tests/dockerize/build_interop_image.sh
+++ b/tools/run_tests/dockerize/build_interop_image.sh
@@ -48,6 +48,14 @@
   echo "WARNING: grpc-go not found, it won't be mounted to the docker container."
 fi
 
+echo "GRPC_NODE_ROOT: ${GRPC_NODE_ROOT:=$(cd ../grpc-node && pwd)}"
+if [ -n "$GRPC_NODE_ROOT" ]
+then
+  MOUNT_ARGS+=" -v $GRPC_NODE_ROOT:/var/local/jenkins/grpc-node:ro"
+else
+  echo "WARNING: grpc-node not found, it won't be mounted to the docker container."
+fi
+
 mkdir -p /tmp/ccache
 
 # Mount service account dir if available.
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index babdfeb..46f4cb6 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -136,23 +136,6 @@
   }, 
   {
     "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"
     ], 
@@ -1239,6 +1222,23 @@
   {
     "deps": [
       "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
+    "name": "grpc_ssl_credentials_test", 
+    "src": [
+      "test/core/security/ssl_credentials_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
       "grpc"
     ], 
     "headers": [], 
@@ -2464,23 +2464,6 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
-    "name": "transport_pid_controller_test", 
-    "src": [
-      "test/core/transport/pid_controller_test.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
     "name": "transport_security_test", 
     "src": [
       "test/core/tsi/transport_security_test.c"
@@ -2615,6 +2598,25 @@
   }, 
   {
     "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "bdp_estimator_test", 
+    "src": [
+      "test/core/transport/bdp_estimator_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
@@ -3495,6 +3497,28 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
+      "grpc++_test", 
+      "grpc_test_util"
+    ], 
+    "headers": [
+      "test/core/end2end/end2end_tests.h"
+    ], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "h2_ssl_cert_test", 
+    "src": [
+      "test/core/end2end/end2end_tests.h", 
+      "test/core/end2end/h2_ssl_cert_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
       "grpc++_test_util", 
       "grpc_test_util"
     ], 
@@ -3550,6 +3574,28 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
+      "grpc++_core_stats", 
+      "grpc++_test_config", 
+      "grpc++_test_util", 
+      "grpc_test_util", 
+      "qps"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "inproc_sync_unary_ping_pong_test", 
+    "src": [
+      "test/cpp/qps/inproc_sync_unary_ping_pong_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
       "grpc++_test_config", 
       "grpc++_test_util", 
       "grpc_test_util", 
@@ -4230,6 +4276,44 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c++", 
+    "name": "transport_pid_controller_test", 
+    "src": [
+      "test/core/transport/pid_controller_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "vector_test", 
+    "src": [
+      "test/core/support/vector_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "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"
@@ -4885,24 +4969,6 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
-    "name": "large_metadata_bad_client_test", 
-    "src": [
-      "test/core/bad_client/tests/large_metadata.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "bad_client_test", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
     "name": "server_registered_method_bad_client_test", 
     "src": [
       "test/core/bad_client/tests/server_registered_method.c"
@@ -5298,24 +5364,6 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "src": [
-      "test/core/end2end/fixtures/h2_ssl_cert.c"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "end2end_tests", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
     "name": "h2_ssl_proxy_test", 
     "src": [
       "test/core/end2end/fixtures/h2_ssl_proxy.c"
@@ -7479,7 +7527,9 @@
       "third_party/cares/cares/config-win32.h", 
       "third_party/cares/cares/setup_once.h", 
       "third_party/cares/config_darwin/ares_config.h", 
-      "third_party/cares/config_linux/ares_config.h"
+      "third_party/cares/config_freebsd/ares_config.h", 
+      "third_party/cares/config_linux/ares_config.h", 
+      "third_party/cares/config_openbsd/ares_config.h"
     ], 
     "is_filegroup": false, 
     "language": "c", 
@@ -7856,6 +7906,7 @@
       "src/core/lib/support/atomic_with_atm.h", 
       "src/core/lib/support/atomic_with_std.h", 
       "src/core/lib/support/env.h", 
+      "src/core/lib/support/manual_constructor.h", 
       "src/core/lib/support/memory.h", 
       "src/core/lib/support/mpscq.h", 
       "src/core/lib/support/murmur_hash.h", 
@@ -7903,6 +7954,7 @@
       "src/core/lib/support/atomic_with_atm.h", 
       "src/core/lib/support/atomic_with_std.h", 
       "src/core/lib/support/env.h", 
+      "src/core/lib/support/manual_constructor.h", 
       "src/core/lib/support/memory.h", 
       "src/core/lib/support/mpscq.h", 
       "src/core/lib/support/murmur_hash.h", 
@@ -8239,6 +8291,7 @@
       "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/support/vector.h", 
       "src/core/lib/surface/alarm_internal.h", 
       "src/core/lib/surface/api_trace.h", 
       "src/core/lib/surface/call.h", 
@@ -8374,6 +8427,7 @@
       "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/support/vector.h", 
       "src/core/lib/surface/alarm_internal.h", 
       "src/core/lib/surface/api_trace.h", 
       "src/core/lib/surface/call.h", 
@@ -8928,7 +8982,7 @@
       "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.cc", 
       "test/core/util/debugger_macros.h", 
       "test/core/util/grpc_profiler.c", 
       "test/core/util/grpc_profiler.h", 
@@ -8995,6 +9049,7 @@
       "src/core/ext/transport/chttp2/transport/bin_decoder.h", 
       "src/core/ext/transport/chttp2/transport/bin_encoder.h", 
       "src/core/ext/transport/chttp2/transport/chttp2_transport.h", 
+      "src/core/ext/transport/chttp2/transport/flow_control.h", 
       "src/core/ext/transport/chttp2/transport/frame.h", 
       "src/core/ext/transport/chttp2/transport/frame_data.h", 
       "src/core/ext/transport/chttp2/transport/frame_goaway.h", 
@@ -9024,6 +9079,7 @@
       "src/core/ext/transport/chttp2/transport/chttp2_transport.cc", 
       "src/core/ext/transport/chttp2/transport/chttp2_transport.h", 
       "src/core/ext/transport/chttp2/transport/flow_control.cc", 
+      "src/core/ext/transport/chttp2/transport/flow_control.h", 
       "src/core/ext/transport/chttp2/transport/frame.h", 
       "src/core/ext/transport/chttp2/transport/frame_data.cc", 
       "src/core/ext/transport/chttp2/transport/frame_data.h", 
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 8341842..3b1b658 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -3,6 +3,7 @@
 [
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -21,10 +22,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -43,10 +46,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -65,10 +70,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -87,10 +94,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -109,10 +118,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -131,10 +142,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -155,32 +168,12 @@
       "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": "bdp_estimator_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ]
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -199,10 +192,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -221,10 +216,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -243,10 +240,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -265,10 +264,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -287,10 +288,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -309,10 +312,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -331,10 +336,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -353,10 +360,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -375,10 +384,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -397,10 +408,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -419,10 +432,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -441,10 +456,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -463,10 +480,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -487,10 +506,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -509,10 +530,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -533,10 +556,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -555,10 +580,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -577,10 +604,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -601,10 +630,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -623,10 +654,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux"
     ], 
@@ -641,10 +674,12 @@
     "name": "ev_epollsig_linux_test", 
     "platforms": [
       "linux"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -663,10 +698,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -683,10 +720,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -705,10 +744,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -727,10 +768,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -747,10 +790,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -767,10 +812,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -789,10 +836,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -811,10 +860,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -833,10 +884,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -855,10 +908,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -877,10 +932,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -899,10 +956,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -921,10 +980,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -943,10 +1004,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -965,10 +1028,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -987,10 +1052,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1009,10 +1076,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1031,10 +1100,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1053,10 +1124,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1075,10 +1148,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1097,10 +1172,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1119,10 +1196,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1141,10 +1220,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1163,10 +1244,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1185,10 +1268,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1207,10 +1292,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1229,10 +1316,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1251,10 +1340,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1273,10 +1364,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1295,10 +1388,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1319,10 +1414,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1341,10 +1438,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1363,10 +1462,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1383,10 +1484,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1405,10 +1508,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1427,10 +1532,36 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "grpc_ssl_credentials_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux"
     ], 
@@ -1445,10 +1576,12 @@
     "name": "handshake_client", 
     "platforms": [
       "linux"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux"
     ], 
@@ -1463,10 +1596,12 @@
     "name": "handshake_server", 
     "platforms": [
       "linux"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1485,10 +1620,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1507,10 +1644,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1529,10 +1668,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1551,10 +1692,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1571,10 +1714,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux"
     ], 
@@ -1587,10 +1732,12 @@
     "name": "httpscli_test", 
     "platforms": [
       "linux"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1609,10 +1756,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1631,10 +1780,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1653,10 +1804,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1675,10 +1828,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1697,10 +1852,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1719,10 +1876,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1741,10 +1900,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1761,10 +1922,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1783,10 +1946,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1805,10 +1970,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1827,10 +1994,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1849,10 +2018,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1871,10 +2042,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1893,10 +2066,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1917,10 +2092,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1939,10 +2116,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -1961,10 +2140,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux"
     ], 
@@ -1979,10 +2160,12 @@
     "name": "pollset_set_test", 
     "platforms": [
       "linux"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2001,10 +2184,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2023,10 +2208,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2045,10 +2232,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2067,10 +2256,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2091,10 +2282,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2115,10 +2308,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2137,10 +2332,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2159,10 +2356,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2181,10 +2380,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2203,10 +2404,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2225,10 +2428,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2247,10 +2452,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2269,10 +2476,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2291,10 +2500,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2313,10 +2524,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2333,10 +2546,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2355,10 +2570,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2377,10 +2594,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2399,10 +2618,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2421,10 +2642,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2445,10 +2668,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2467,10 +2692,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2489,10 +2716,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2513,10 +2742,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2535,10 +2766,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2557,10 +2790,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2581,10 +2816,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2605,10 +2842,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2627,10 +2866,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2649,32 +2890,12 @@
       "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": "transport_pid_controller_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ]
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2691,10 +2912,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2713,10 +2936,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2735,10 +2960,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2757,10 +2984,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2779,10 +3008,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2801,10 +3032,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2823,12 +3056,38 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "bdp_estimator_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2845,12 +3104,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2867,12 +3128,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2889,12 +3152,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2911,12 +3176,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2933,12 +3200,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2955,12 +3224,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--benchmark_min_time=4"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2977,12 +3248,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -2999,12 +3272,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3026,12 +3301,14 @@
       "mac", 
       "posix"
     ], 
-    "timeout_seconds": 1200
+    "timeout_seconds": 1200, 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3053,12 +3330,14 @@
       "mac", 
       "posix"
     ], 
-    "timeout_seconds": 1200
+    "timeout_seconds": 1200, 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3080,12 +3359,14 @@
       "mac", 
       "posix"
     ], 
-    "timeout_seconds": 1200
+    "timeout_seconds": 1200, 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3107,12 +3388,14 @@
       "mac", 
       "posix"
     ], 
-    "timeout_seconds": 1200
+    "timeout_seconds": 1200, 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3129,12 +3412,14 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [
       "--benchmark_min_time=0"
     ], 
+    "benchmark": true, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3151,10 +3436,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3173,10 +3460,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3195,10 +3484,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3217,10 +3508,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3237,10 +3530,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3252,7 +3547,8 @@
     "exclude_iomgrs": [], 
     "excluded_poll_engines": [
       "poll", 
-      "poll-cv"
+      "poll-cv", 
+      "epollex"
     ], 
     "flaky": false, 
     "gtest": true, 
@@ -3263,10 +3559,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3285,10 +3583,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3307,10 +3607,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3329,10 +3631,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3351,10 +3655,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3373,10 +3679,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3395,10 +3703,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3417,10 +3727,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3439,10 +3751,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3461,10 +3775,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3483,10 +3799,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3505,12 +3823,14 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--generated_file_path=gens/src/proto/grpc/testing/"
     ], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3529,10 +3849,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3551,10 +3873,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3573,10 +3897,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3599,10 +3925,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3614,7 +3942,8 @@
     "exclude_iomgrs": [], 
     "excluded_poll_engines": [
       "poll", 
-      "poll-cv"
+      "poll-cv", 
+      "epollex"
     ], 
     "flaky": false, 
     "gtest": false, 
@@ -3625,10 +3954,36 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
+    "name": "h2_ssl_cert_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3647,10 +4002,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3669,10 +4026,34 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "inproc_sync_unary_ping_pong_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3689,10 +4070,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3711,10 +4094,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3733,10 +4118,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3755,10 +4142,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3777,10 +4166,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3799,10 +4190,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3819,10 +4212,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3841,10 +4236,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3861,10 +4258,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3883,10 +4282,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3905,10 +4306,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3927,10 +4330,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3947,10 +4352,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3969,10 +4376,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -3991,10 +4400,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4002,7 +4413,9 @@
       "windows"
     ], 
     "cpu_cost": 1.0, 
-    "exclude_configs": [], 
+    "exclude_configs": [
+      "tsan"
+    ], 
     "exclude_iomgrs": [], 
     "flaky": false, 
     "gtest": true, 
@@ -4013,10 +4426,13 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "timeout_seconds": 1200, 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4035,10 +4451,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": false
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4055,10 +4473,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4077,10 +4497,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4100,10 +4522,60 @@
       "posix", 
       "windows"
     ], 
-    "timeout_seconds": 1200
+    "timeout_seconds": 1200, 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "transport_pid_controller_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
+    "name": "vector_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4120,10 +4592,12 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4142,10 +4616,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4166,10 +4642,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4190,10 +4668,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4214,10 +4694,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4238,10 +4720,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4262,34 +4746,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [
-      "uv"
-    ], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c", 
-    "name": "large_metadata_bad_client_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ]
-  }, 
-  {
-    "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4310,10 +4772,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4334,10 +4798,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4358,10 +4824,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4382,10 +4850,12 @@
       "mac", 
       "posix", 
       "windows"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4402,13 +4872,15 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--test_bin_name=resolver_component_test_unsecure", 
       "--running_under_bazel=false"
     ], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4425,13 +4897,15 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [
       "--test_bin_name=resolver_component_test", 
       "--running_under_bazel=false"
     ], 
+    "benchmark": false, 
     "ci_platforms": [
       "linux", 
       "mac", 
@@ -4448,7 +4922,8 @@
       "linux", 
       "mac", 
       "posix"
-    ]
+    ], 
+    "uses_polling": true
   }, 
   {
     "args": [
@@ -26400,1344 +26875,6 @@
     "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": [
-      "bad_hostname"
-    ], 
-    "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": [
-      "bad_ping"
-    ], 
-    "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": [
-      "binary_metadata"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "call_creds"
-    ], 
-    "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": [
-      "cancel_after_accept"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_client_done"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_invoke"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_after_round_trip"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_before_invoke"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_in_a_vacuum"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "cancel_with_status"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
-    ], 
-    "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": [
-      "connectivity"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [
-      "uv"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "default_host"
-    ], 
-    "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": [
-      "disappearing_server"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": true, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "filter_call_init_fails"
-    ], 
-    "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": [
-      "filter_causes_close"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "filter_latency"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "high_initial_seqno"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "hpack_size"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "idempotent_request"
-    ], 
-    "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": [
-      "invoke_large_request"
-    ], 
-    "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": [
-      "keepalive_timeout"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "large_metadata"
-    ], 
-    "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": [
-      "load_reporting_hook"
-    ], 
-    "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": [
-      "max_concurrent_streams"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "max_connection_age"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "max_connection_idle"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [
-      "uv"
-    ], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "max_message_length"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "negative_deadline"
-    ], 
-    "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": [
-      "network_status_change"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "no_logging"
-    ], 
-    "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": [
-      "no_op"
-    ], 
-    "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": [
-      "payload"
-    ], 
-    "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": [
-      "ping"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "ping_pong_streaming"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "registered_call"
-    ], 
-    "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": [
-      "request_with_flags"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "request_with_payload"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "resource_quota_server"
-    ], 
-    "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": [
-      "server_finishes_request"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_calls"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "shutdown_finishes_tags"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_cacheable_request"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "simple_delayed_request"
-    ], 
-    "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": [
-      "simple_metadata"
-    ], 
-    "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": [
-      "simple_request"
-    ], 
-    "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": [
-      "stream_compression_compressed_payload"
-    ], 
-    "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": [
-      "stream_compression_payload"
-    ], 
-    "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": [
-      "stream_compression_ping_pong_streaming"
-    ], 
-    "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": [
-      "streaming_error_response"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "trailing_metadata"
-    ], 
-    "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": [
-      "workaround_cronet_compression"
-    ], 
-    "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": [
-      "write_buffering"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "write_buffering_at_end"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_cert_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "authority_not_supported"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
       "posix"
     ], 
     "cpu_cost": 1.0, 
@@ -31092,52 +30229,6 @@
   }, 
   {
     "args": [
-      "write_buffering"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "inproc_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "write_buffering_at_end"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "inproc_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
       "authority_not_supported"
     ], 
     "ci_platforms": [
@@ -49475,55 +48566,10 @@
   }, 
   {
     "args": [
-      "write_buffering"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "inproc_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "write_buffering_at_end"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 0.1, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "inproc_nosec_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_1channel_100rpcs_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49549,6 +48595,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_1channel_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49572,8 +48619,35 @@
   {
     "args": [
       "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 16, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 1, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 50, \"req_size\": 300}}, \"client_channels\": 300, \"threads_per_cq\": 0, \"load_params\": {\"poisson\": {\"offered_load\": 37500}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "auto_timeout_scaling": false, 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp", 
+    "timeout_seconds": 120
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49599,6 +48673,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49624,6 +48699,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49649,6 +48725,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49674,6 +48751,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49699,6 +48777,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49724,6 +48803,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 2}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49749,6 +48829,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49774,6 +48855,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49799,6 +48881,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49824,6 +48907,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49851,6 +48935,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49876,6 +48961,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49903,6 +48989,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49928,6 +49015,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49953,6 +49041,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -49978,6 +49067,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50003,6 +49093,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50028,6 +49119,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50053,6 +49145,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50078,6 +49171,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50103,6 +49197,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50128,6 +49223,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50153,6 +49249,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50178,6 +49275,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50203,6 +49301,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50228,6 +49327,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50253,6 +49353,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50278,6 +49379,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50303,6 +49405,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50328,6 +49431,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50353,6 +49457,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50378,6 +49483,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50403,6 +49509,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50428,6 +49535,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50453,6 +49561,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50478,6 +49587,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50503,6 +49613,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50528,6 +49639,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50553,6 +49665,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50578,6 +49691,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 2}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50603,6 +49717,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50628,6 +49743,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50653,6 +49769,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50678,6 +49795,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50705,6 +49823,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50730,6 +49849,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50757,6 +49877,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50782,6 +49903,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50807,6 +49929,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50832,6 +49955,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50857,6 +49981,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50882,6 +50007,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50907,6 +50033,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50932,6 +50059,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50957,6 +50085,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -50982,6 +50111,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51007,6 +50137,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51032,6 +50163,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51057,6 +50189,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51082,6 +50215,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51107,6 +50241,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51132,6 +50267,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51157,6 +50293,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51182,6 +50319,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51207,6 +50345,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51232,6 +50371,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51257,6 +50397,7 @@
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51279,6 +50420,7 @@
   }, 
   {
     "args": [
+      "--run_inproc", 
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_1channel_100rpcs_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
@@ -51289,6 +50431,712 @@
     "cpu_cost": "capacity", 
     "defaults": "boringssl", 
     "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_unary_1channel_100rpcs_1MB", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_1channel_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_streaming_from_client_1channel_1MB", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_generic_async_streaming_ping_pong_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_generic_async_streaming_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_generic_async_streaming_qps_unconstrained_1mps_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_generic_async_streaming_qps_unconstrained_10mps_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 2}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_unary_ping_pong_insecure_1MB", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1024, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_sync_unary_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_unary_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1024, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_sync_streaming_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1024, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1024, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_streaming_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1024, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1024, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--run_inproc", 
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "qps_json_driver", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "qps_json_driver:inproc_cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_1channel_100rpcs_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "auto_timeout_scaling": false, 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
@@ -51313,13 +51161,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_1channel_100rpcs_1MB_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_1channel_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51351,13 +51200,53 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_1channel_1MB_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 16, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 1, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 50, \"req_size\": 300}}, \"client_channels\": 300, \"threads_per_cq\": 0, \"load_params\": {\"poisson\": {\"offered_load\": 37500}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "auto_timeout_scaling": false, 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp_low_thread_count", 
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51389,13 +51278,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51427,13 +51317,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51465,13 +51356,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_1mps_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51503,13 +51395,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_10mps_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51541,13 +51434,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_1channel_1MBmsg_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51579,13 +51473,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_64KBmsg_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 2}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51617,13 +51512,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51655,13 +51551,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51693,13 +51590,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51731,13 +51629,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51771,13 +51670,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51809,13 +51709,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51849,13 +51750,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51887,13 +51789,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_secure_1MB_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51925,13 +51828,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -51963,13 +51867,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52001,13 +51906,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52039,13 +51945,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52077,13 +51984,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52115,13 +52023,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52153,13 +52062,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_1mps_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52191,13 +52101,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_10mps_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52229,13 +52140,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52267,13 +52179,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52305,13 +52218,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_1mps_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52343,13 +52257,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_10mps_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52381,13 +52296,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_client_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52419,13 +52335,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_client_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52457,13 +52374,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52495,13 +52413,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52533,13 +52452,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_server_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52571,13 +52491,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_server_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52609,13 +52530,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_ping_pong_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52647,13 +52569,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_qps_unconstrained_secure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52685,13 +52608,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52723,13 +52647,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52761,13 +52686,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_1mps_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52799,13 +52725,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_10mps_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52837,13 +52764,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 65536, \"req_size\": 65536}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52875,13 +52803,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 2}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52913,13 +52842,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52951,13 +52881,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"security_params\": null, \"threads_per_cq\": 2, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 2, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -52989,13 +52920,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"server_type\": \"ASYNC_GENERIC_SERVER\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"security_params\": null, \"threads_per_cq\": 0}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53027,13 +52959,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53067,13 +53000,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 8388608, \"req_size\": 128}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53105,13 +53039,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_servers\": 1, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53145,13 +53080,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53183,13 +53119,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_insecure_1MB_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53221,13 +53158,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53259,13 +53197,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53297,13 +53236,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53335,13 +53275,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53373,13 +53314,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53411,13 +53353,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53449,13 +53392,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53487,13 +53431,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53525,13 +53470,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53563,13 +53509,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 1, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53601,13 +53548,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"messages_per_stream\": 10, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53639,13 +53587,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53677,13 +53626,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_client_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53715,13 +53665,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53753,13 +53704,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53791,13 +53743,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53829,13 +53782,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_server_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"SYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53867,13 +53821,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 0, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"latency\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"threads_per_cq\": 0, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53905,13 +53860,14 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_ping_pong_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
       "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"security_params\": null, \"threads_per_cq\": 3, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"security_params\": null, \"channel_args\": [{\"str_value\": \"throughput\", \"name\": \"grpc.optimization_target\"}, {\"int_value\": 1, \"name\": \"grpc.minimal_stack\"}], \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING_FROM_SERVER\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 3, \"load_params\": {\"closed_loop\": {}}, \"client_type\": \"ASYNC_CLIENT\", \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
+    "auto_timeout_scaling": false, 
     "boringssl": true, 
     "ci_platforms": [
       "linux"
@@ -53943,7 +53899,7 @@
       "linux"
     ], 
     "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure_low_thread_count", 
-    "timeout_seconds": 120
+    "timeout_seconds": 600
   }, 
   {
     "args": [
diff --git a/tools/run_tests/performance/massage_qps_stats.py b/tools/run_tests/performance/massage_qps_stats.py
index ebbfe6c..48c5758 100644
--- a/tools/run_tests/performance/massage_qps_stats.py
+++ b/tools/run_tests/performance/massage_qps_stats.py
@@ -101,6 +101,10 @@
     stats["core_combiner_locks_scheduled_items"] = massage_qps_stats_helpers.counter(core_stats, "combiner_locks_scheduled_items")
     stats["core_combiner_locks_scheduled_final_items"] = massage_qps_stats_helpers.counter(core_stats, "combiner_locks_scheduled_final_items")
     stats["core_combiner_locks_offloaded"] = massage_qps_stats_helpers.counter(core_stats, "combiner_locks_offloaded")
+    stats["core_call_combiner_locks_initiated"] = massage_qps_stats_helpers.counter(core_stats, "call_combiner_locks_initiated")
+    stats["core_call_combiner_locks_scheduled_items"] = massage_qps_stats_helpers.counter(core_stats, "call_combiner_locks_scheduled_items")
+    stats["core_call_combiner_set_notify_on_cancel"] = massage_qps_stats_helpers.counter(core_stats, "call_combiner_set_notify_on_cancel")
+    stats["core_call_combiner_cancelled"] = massage_qps_stats_helpers.counter(core_stats, "call_combiner_cancelled")
     stats["core_executor_scheduled_short_items"] = massage_qps_stats_helpers.counter(core_stats, "executor_scheduled_short_items")
     stats["core_executor_scheduled_long_items"] = massage_qps_stats_helpers.counter(core_stats, "executor_scheduled_long_items")
     stats["core_executor_scheduled_to_self"] = massage_qps_stats_helpers.counter(core_stats, "executor_scheduled_to_self")
@@ -109,6 +113,9 @@
     stats["core_executor_push_retries"] = massage_qps_stats_helpers.counter(core_stats, "executor_push_retries")
     stats["core_server_requested_calls"] = massage_qps_stats_helpers.counter(core_stats, "server_requested_calls")
     stats["core_server_slowpath_requests_queued"] = massage_qps_stats_helpers.counter(core_stats, "server_slowpath_requests_queued")
+    stats["core_cq_ev_queue_trylock_failures"] = massage_qps_stats_helpers.counter(core_stats, "cq_ev_queue_trylock_failures")
+    stats["core_cq_ev_queue_trylock_successes"] = massage_qps_stats_helpers.counter(core_stats, "cq_ev_queue_trylock_successes")
+    stats["core_cq_ev_queue_transient_pop_failures"] = massage_qps_stats_helpers.counter(core_stats, "cq_ev_queue_transient_pop_failures")
     h = massage_qps_stats_helpers.histogram(core_stats, "call_initial_size")
     stats["core_call_initial_size"] = ",".join("%f" % x for x in h.buckets)
     stats["core_call_initial_size_bkts"] = ",".join("%f" % x for x in h.boundaries)
diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py
index 8f01eb4..ddaffa4 100644
--- a/tools/run_tests/performance/scenario_config.py
+++ b/tools/run_tests/performance/scenario_config.py
@@ -22,6 +22,7 @@
 
 SMOKETEST='smoketest'
 SCALABLE='scalable'
+INPROC='inproc'
 SWEEP='sweep'
 DEFAULT_CATEGORIES=[SCALABLE, SMOKETEST]
 
@@ -82,6 +83,16 @@
         r['simple_params'] = sizes
     return r
 
+def _load_params(offered_load):
+    r = {}
+    if offered_load is None:
+        r['closed_loop'] = {}
+    else:
+        load = {}
+        load['offered_load'] = offered_load
+        r['poisson'] = load
+    return r
+
 def _add_channel_arg(config, key, value):
   if 'channel_args' in config:
     channel_args = config['channel_args']
@@ -115,7 +126,8 @@
                         resource_quota_size=None,
                         messages_per_stream=None,
                         excluded_poll_engines=[],
-                        minimal_stack=False):
+                        minimal_stack=False,
+                        offered_load=None):
   """Creates a basic ping pong scenario."""
   scenario = {
     'name': name,
@@ -129,9 +141,6 @@
       'async_client_threads': 1,
       'threads_per_cq': client_threads_per_cq,
       'rpc_type': rpc_type,
-      'load_params': {
-        'closed_loop': {}
-      },
       'histogram_params': HISTOGRAM_PARAMS,
       'channel_args': [],
     },
@@ -171,12 +180,16 @@
     scenario['client_config']['outstanding_rpcs_per_channel'] = deep
     scenario['client_config']['client_channels'] = wide
     scenario['client_config']['async_client_threads'] = 0
+    if offered_load is not None:
+        optimization_target = 'latency'
   else:
     scenario['client_config']['outstanding_rpcs_per_channel'] = 1
     scenario['client_config']['client_channels'] = 1
     scenario['client_config']['async_client_threads'] = 1
     optimization_target = 'latency'
 
+  scenario['client_config']['load_params'] = _load_params(offered_load)
+
   optimization_channel_arg = {
     'name': 'grpc.optimization_target',
     'str_value': optimization_target
@@ -224,7 +237,7 @@
       unconstrained_client='async', outstanding=100, channels=1,
       num_clients=1,
       secure=False,
-      categories=[SMOKETEST] + [SCALABLE])
+      categories=[SMOKETEST] + [INPROC] + [SCALABLE])
 
     yield _ping_pong_scenario(
       'cpp_protobuf_async_streaming_from_client_1channel_1MB', rpc_type='STREAMING_FROM_CLIENT',
@@ -233,11 +246,20 @@
       unconstrained_client='async', outstanding=1, channels=1,
       num_clients=1,
       secure=False,
-      categories=[SMOKETEST] + [SCALABLE])
+      categories=[SMOKETEST] + [INPROC] + [SCALABLE])
+
+    yield _ping_pong_scenario(
+       'cpp_protobuf_async_unary_75Kqps_600channel_60Krpcs_300Breq_50Bresp',
+       rpc_type='UNARY', client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
+       req_size=300, resp_size=50,
+       unconstrained_client='async', outstanding=30000, channels=300,
+       offered_load=37500, secure=False,
+       async_server_threads=16, server_threads_per_cq=1,
+       categories=[SMOKETEST] + [SCALABLE])
 
     for secure in [True, False]:
       secstr = 'secure' if secure else 'insecure'
-      smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE]
+      smoketest_categories = ([SMOKETEST] if secure else [INPROC]) + [SCALABLE]
 
       yield _ping_pong_scenario(
           'cpp_generic_async_streaming_ping_pong_%s' % secstr,
@@ -809,7 +831,7 @@
 
   def worker_cmdline(self):
     if self.php7_protobuf_c:
-        return ['tools/run_tests/performance/run_worker_php.sh --use_protobuf_c_extension']
+        return ['tools/run_tests/performance/run_worker_php.sh', '--use_protobuf_c_extension']
     return ['tools/run_tests/performance/run_worker_php.sh']
 
   def worker_port_offset(self):
@@ -821,7 +843,7 @@
     php7_extension_mode='php7_protobuf_php_extension'
     if self.php7_protobuf_c:
         php7_extension_mode='php7_protobuf_c_extension'
-    
+
     yield _ping_pong_scenario(
         '%s_to_cpp_protobuf_sync_unary_ping_pong' % php7_extension_mode,
         rpc_type='UNARY', client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
diff --git a/tools/run_tests/performance/scenario_result_schema.json b/tools/run_tests/performance/scenario_result_schema.json
index 169221d..b00c2ee 100644
--- a/tools/run_tests/performance/scenario_result_schema.json
+++ b/tools/run_tests/performance/scenario_result_schema.json
@@ -517,6 +517,26 @@
       }, 
       {
         "mode": "NULLABLE", 
+        "name": "core_call_combiner_locks_initiated", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_call_combiner_locks_scheduled_items", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_call_combiner_set_notify_on_cancel", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_call_combiner_cancelled", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
         "name": "core_executor_scheduled_short_items", 
         "type": "INTEGER"
       }, 
@@ -557,6 +577,21 @@
       }, 
       {
         "mode": "NULLABLE", 
+        "name": "core_cq_ev_queue_trylock_failures", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_cq_ev_queue_trylock_successes", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_cq_ev_queue_transient_pop_failures", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
         "name": "core_call_initial_size", 
         "type": "STRING"
       }, 
@@ -1314,6 +1349,26 @@
       }, 
       {
         "mode": "NULLABLE", 
+        "name": "core_call_combiner_locks_initiated", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_call_combiner_locks_scheduled_items", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_call_combiner_set_notify_on_cancel", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_call_combiner_cancelled", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
         "name": "core_executor_scheduled_short_items", 
         "type": "INTEGER"
       }, 
@@ -1354,6 +1409,21 @@
       }, 
       {
         "mode": "NULLABLE", 
+        "name": "core_cq_ev_queue_trylock_failures", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_cq_ev_queue_trylock_successes", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
+        "name": "core_cq_ev_queue_transient_pop_failures", 
+        "type": "INTEGER"
+      }, 
+      {
+        "mode": "NULLABLE", 
         "name": "core_call_initial_size", 
         "type": "STRING"
       }, 
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 393aef8..56d6e4e 100644
--- a/tools/run_tests/python_utils/filter_pull_request_tests.py
+++ b/tools/run_tests/python_utils/filter_pull_request_tests.py
@@ -78,7 +78,7 @@
   '^src/python/': [_PYTHON_TEST_SUITE],
   '^src/ruby/': [_RUBY_TEST_SUITE],
   '^templates/': [],
-  '^test/core/': [_CORE_TEST_SUITE],
+  '^test/core/': [_CORE_TEST_SUITE, _CPP_TEST_SUITE],
   '^test/cpp/': [_CPP_TEST_SUITE],
   '^test/distrib/cpp/': [_CPP_TEST_SUITE],
   '^test/distrib/csharp/': [_CSHARP_TEST_SUITE],
diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py
index d523095..85eef44 100755
--- a/tools/run_tests/python_utils/jobset.py
+++ b/tools/run_tests/python_utils/jobset.py
@@ -302,6 +302,7 @@
           self._retries += 1
           self.result.num_failures += 1
           self.result.retries = self._timeout_retries + self._retries
+          # NOTE: job is restarted regardless of jobset's max_time setting
           self.start()
         else:
           self._state = _FAILURE
@@ -344,6 +345,7 @@
         if self._spec.kill_handler:
           self._spec.kill_handler(self)
         self._process.terminate()
+        # NOTE: job is restarted regardless of jobset's max_time setting
         self.start()
       else:
         message('TIMEOUT', '%s [pid=%d, time=%.1fsec]' % (self._spec.shortname, self._process.pid, elapsed), stdout(), do_newline=True)
@@ -412,7 +414,7 @@
       if current_cpu_cost + spec.cpu_cost <= self._maxjobs:
         if len(self._running) < self._maxjobs_cpu_agnostic:
           break
-      self.reap()
+      self.reap(spec.shortname, spec.cpu_cost)
     if self.cancelled(): return False
     job = Job(spec,
               self._newline_on_success,
@@ -424,7 +426,7 @@
       self.resultset[job.GetSpec().shortname] = []
     return True
 
-  def reap(self):
+  def reap(self, waiting_for=None, waiting_for_cost=None):
     """Collect the dead jobs."""
     while self._running:
       dead = set()
@@ -452,8 +454,12 @@
           sofar = now - self._start_time
           remaining = sofar / self._completed * (self._remaining + len(self._running))
           rstr = 'ETA %.1f sec; %s' % (remaining, rstr)
-        message('WAITING', '%s%d jobs running, %d complete, %d failed' % (
-            rstr, len(self._running), self._completed, self._failures))
+        if waiting_for is not None:
+          wstr = ' next: %s @ %.2f cpu' % (waiting_for, waiting_for_cost)
+        else:
+          wstr = ''
+        message('WAITING', '%s%d jobs running, %d complete, %d failed (load %.2f)%s' % (
+            rstr, len(self._running), self._completed, self._failures, self.cpu_cost(), wstr))
       if platform_string() == 'windows':
         time.sleep(0.1)
       else:
diff --git a/tools/run_tests/python_utils/upload_test_results.py b/tools/run_tests/python_utils/upload_test_results.py
index 15e8277..ea97bc0 100644
--- a/tools/run_tests/python_utils/upload_test_results.py
+++ b/tools/run_tests/python_utils/upload_test_results.py
@@ -51,6 +51,19 @@
   ('cpu_measured', 'FLOAT', 'Actual CPU usage of test'),
   ('return_code', 'INTEGER', 'Exit code of test'),
 ]
+_INTEROP_RESULTS_SCHEMA = [
+  ('job_name', 'STRING', 'Name of Jenkins/Kokoro job'),
+  ('build_id', 'INTEGER', 'Build ID of Jenkins/Kokoro job'),
+  ('build_url', 'STRING', 'URL of Jenkins/Kokoro job'),
+  ('test_name', 'STRING', 'Unique test name combining client, server, and test_name'),
+  ('suite', 'STRING', 'Test suite: cloud_to_cloud, cloud_to_prod, or cloud_to_prod_auth'),
+  ('client', 'STRING', 'Client language'),
+  ('server', 'STRING', 'Server host name'),
+  ('test_case', 'STRING', 'Name of test case'),
+  ('result', 'STRING', 'Test result: PASSED, TIMEOUT, FAILED, or SKIPPED'),
+  ('timestamp', 'TIMESTAMP', 'Timestamp of test run'),
+  ('elapsed_time', 'FLOAT', 'How long test took to run'),
+]
 
 
 def _get_build_metadata(test_results):
@@ -114,3 +127,41 @@
           else:
             print('Error uploading result to bigquery, all attempts failed.')
             sys.exit(1)
+
+
+def upload_interop_results_to_bq(resultset, bq_table, args):
+  """Upload interop test results to a BQ table.
+
+  Args:
+      resultset: dictionary generated by jobset.run
+      bq_table: string name of table to create/upload results to in BQ
+      args: args in run_interop_tests.py, generated by argparse
+  """
+  bq = big_query_utils.create_big_query()
+  big_query_utils.create_partitioned_table(bq, _PROJECT_ID, _DATASET_ID, bq_table, _INTEROP_RESULTS_SCHEMA, _DESCRIPTION,
+                                           partition_type=_PARTITION_TYPE, expiration_ms= _EXPIRATION_MS)
+
+  for shortname, results in six.iteritems(resultset):
+    for result in results:
+      test_results = {}
+      _get_build_metadata(test_results)
+      test_results['elapsed_time'] = '%.2f' % result.elapsed_time
+      test_results['result'] = result.state
+      test_results['test_name'] = shortname
+      test_results['suite'] = shortname.split(':')[0]
+      test_results['client'] = shortname.split(':')[1]
+      test_results['server'] = shortname.split(':')[2]
+      test_results['test_case'] = shortname.split(':')[3]
+      test_results['timestamp'] = time.strftime('%Y-%m-%d %H:%M:%S')
+      row = big_query_utils.make_row(str(uuid.uuid4()), test_results)
+      # TODO(jtattermusch): rows are inserted one by one, very inefficient
+      max_retries = 3
+      for attempt in range(max_retries):
+        if big_query_utils.insert_rows(bq, _PROJECT_ID, _DATASET_ID, bq_table, [row]):
+          break
+        else:
+          if attempt < max_retries - 1:
+            print('Error uploading result to bigquery, will retry.')
+          else:
+            print('Error uploading result to bigquery, all attempts failed.')
+            sys.exit(1)
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 1537641..b20d6ce 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -35,6 +35,11 @@
 import python_utils.dockerjob as dockerjob
 import python_utils.jobset as jobset
 import python_utils.report_utils as report_utils
+# It's ok to not import because this is only necessary to upload results to BQ.
+try:
+  from python_utils.upload_test_results import upload_interop_results_to_bq
+except ImportError as e:
+  print(e)
 
 # Docker doesn't clean up after itself, so we do it on exit.
 atexit.register(lambda: subprocess.call(['stty', 'echo']))
@@ -308,20 +313,20 @@
 class NodeLanguage:
 
   def __init__(self):
-    self.client_cwd = None
-    self.server_cwd = None
+    self.client_cwd = '../grpc-node'
+    self.server_cwd = '../grpc-node'
     self.safename = str(self)
 
   def client_cmd(self, args):
-    return ['tools/run_tests/interop/with_nvm.sh',
-            'node', 'src/node/interop/interop_client.js'] + args
+    return ['packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh',
+            'node', 'test/interop/interop_client.js'] + args
 
   def cloud_to_prod_env(self):
     return {}
 
   def server_cmd(self, args):
-    return ['tools/run_tests/interop/with_nvm.sh',
-            'node', 'src/node/interop/interop_server.js'] + args
+    return ['packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh',
+            'node', 'test/interop/interop_server.js'] + args
 
   def global_env(self):
     return {}
@@ -672,10 +677,10 @@
           cmdline=cmdline,
           cwd=cwd,
           environ=environ,
-          shortname='%s:%s:%s:%s' % (suite_name, server_host_name, language,
+          shortname='%s:%s:%s:%s' % (suite_name, language, server_host_name,
                                      test_case),
           timeout_seconds=_TEST_TIMEOUT,
-          flake_retries=5 if args.allow_flakes else 0,
+          flake_retries=4 if args.allow_flakes else 0,
           timeout_retries=2 if args.allow_flakes else 0,
           kill_handler=_job_kill_handler)
   if docker_image:
@@ -741,7 +746,7 @@
           shortname='cloud_to_cloud:%s:%s_server:%s' % (language, server_name,
                                                         test_case),
           timeout_seconds=_TEST_TIMEOUT,
-          flake_retries=5 if args.allow_flakes else 0,
+          flake_retries=4 if args.allow_flakes else 0,
           timeout_retries=2 if args.allow_flakes else 0,
           kill_handler=_job_kill_handler)
   if docker_image:
@@ -956,6 +961,11 @@
                   const=True,
                   help=('Put reports into subdirectories to improve '
                         'presentation of results by Internal CI.'))
+argp.add_argument('--bq_result_table',
+                  default='',
+                  type=str,
+                  nargs='?',
+                  help='Upload test results to a specified BQ table.')
 args = argp.parse_args()
 
 servers = set(s for s in itertools.chain.from_iterable(_SERVERS
@@ -1205,6 +1215,8 @@
   num_failures, resultset = jobset.run(jobs, newline_on_success=True,
                                        maxjobs=args.jobs,
                                        skip_jobs=args.manual_run)
+  if args.bq_result_table and resultset:
+    upload_interop_results_to_bq(resultset, args.bq_result_table, args)
   if num_failures:
     jobset.message('FAILED', 'Some tests failed', do_newline=True)
   else:
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 7c65067..c3d070a 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -63,8 +63,7 @@
 }
 
 _POLLING_STRATEGIES = {
-  'linux': ['epollsig', 'epoll1', 'poll', 'poll-cv'],
-# TODO(ctiller, sreecha): enable epollex, epoll-thread-pool
+  'linux': ['epollex', 'epollsig', 'epoll1', 'poll', 'poll-cv'],
   'mac': ['poll'],
 }
 
@@ -122,7 +121,7 @@
   # so far on windows.
   if jobset.platform_string() == 'windows':
     return 64
-  return 128
+  return 1024
 
 # SimpleConfig: just compile with CONFIG=config, and run the binary to test
 class Config(object):
@@ -149,18 +148,16 @@
     for k, v in environ.items():
       actual_environ[k] = v
     if not flaky and shortname and shortname in flaky_tests:
-      print('Setting %s to flaky' % shortname)
       flaky = True
     if shortname in shortname_to_cpu:
-      print('Update CPU cost for %s: %f -> %f' % (shortname, cpu_cost, shortname_to_cpu[shortname]))
       cpu_cost = shortname_to_cpu[shortname]
     return jobset.JobSpec(cmdline=self.tool_prefix + cmdline,
                           shortname=shortname,
                           environ=actual_environ,
                           cpu_cost=cpu_cost,
                           timeout_seconds=(self.timeout_multiplier * timeout_seconds if timeout_seconds else None),
-                          flake_retries=5 if flaky or args.allow_flakes else 0,
-                          timeout_retries=3 if flaky or args.allow_flakes else 0)
+                          flake_retries=4 if flaky or args.allow_flakes else 0,
+                          timeout_retries=1 if flaky or args.allow_flakes else 0)
 
 
 def get_c_tests(travis, test_lang) :
@@ -284,9 +281,10 @@
       if self._use_cmake and target.get('boringssl', False):
         # cmake doesn't build boringssl tests
         continue
+      auto_timeout_scaling = target.get('auto_timeout_scaling', True)
       polling_strategies = (_POLLING_STRATEGIES.get(self.platform, ['all'])
                             if target.get('uses_polling', True)
-                            else ['all'])
+                            else ['none'])
       if self.args.iomgr_platform == 'uv':
         polling_strategies = ['all']
       for polling_strategy in polling_strategies:
@@ -299,7 +297,8 @@
           env['GRPC_DNS_RESOLVER'] = resolver
         shortname_ext = '' if polling_strategy=='all' else ' GRPC_POLL_STRATEGY=%s' % polling_strategy
         timeout_scaling = 1
-        if polling_strategy == 'poll-cv':
+
+        if auto_timeout_scaling and polling_strategy == 'poll-cv':
           timeout_scaling *= 5
 
         if polling_strategy in target.get('excluded_poll_engines', []):
@@ -307,12 +306,12 @@
 
         # 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'):
+        if auto_timeout_scaling and ('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']:
@@ -330,11 +329,29 @@
         if cpu_cost == 'capacity':
           cpu_cost = multiprocessing.cpu_count()
         if os.path.isfile(binary):
-          if 'gtest' in target and target['gtest']:
-            # here we parse the output of --gtest_list_tests to build up a
-            # complete list of the tests contained in a binary
-            # for each test, we then add a job to run, filtering for just that
-            # test
+          list_test_command = None
+          filter_test_command = None
+
+          # these are the flag defined by gtest and benchmark framework to list
+          # and filter test runs. We use them to split each individual test
+          # into its own JobSpec, and thus into its own process.
+          if 'benchmark' in target and target['benchmark']:
+            with open(os.devnull, 'w') as fnull:
+              tests = subprocess.check_output([binary, '--benchmark_list_tests'],
+                                              stderr=fnull)
+            for line in tests.split('\n'):
+              test = line.strip()
+              if not test: continue
+              cmdline = [binary, '--benchmark_filter=%s$' % test] + target['args']
+              out.append(self.config.job_spec(cmdline,
+                                              shortname='%s %s' % (' '.join(cmdline), shortname_ext),
+                                              cpu_cost=cpu_cost,
+                                              timeout_seconds=_DEFAULT_TIMEOUT_SECONDS * timeout_scaling,
+                                              environ=env))
+          elif 'gtest' in target and target['gtest']:
+            # here we parse the output of --gtest_list_tests to build up a complete
+            # list of the tests contained in a binary for each test, we then
+            # add a job to run, filtering for just that test.
             with open(os.devnull, 'w') as fnull:
               tests = subprocess.check_output([binary, '--gtest_list_tests'],
                                               stderr=fnull)
@@ -353,7 +370,7 @@
                 out.append(self.config.job_spec(cmdline,
                                                 shortname='%s %s' % (' '.join(cmdline), shortname_ext),
                                                 cpu_cost=cpu_cost,
-                                                timeout_seconds=_DEFAULT_TIMEOUT_SECONDS * timeout_scaling,
+                                                timeout_seconds=target.get('timeout_seconds', _DEFAULT_TIMEOUT_SECONDS) * timeout_scaling,
                                                 environ=env))
           else:
             cmdline = [binary] + target['args']
@@ -1493,7 +1510,7 @@
   return environ
 
 build_steps = list(set(
-                   jobset.JobSpec(cmdline, environ=build_step_environ(build_config), flake_retries=5)
+                   jobset.JobSpec(cmdline, environ=build_step_environ(build_config), flake_retries=2)
                    for l in languages
                    for cmdline in l.pre_build_steps()))
 if make_targets:
diff --git a/tools/run_tests/sanity/check_sources_and_headers.py b/tools/run_tests/sanity/check_sources_and_headers.py
index c27a0b7..cae175c 100755
--- a/tools/run_tests/sanity/check_sources_and_headers.py
+++ b/tools/run_tests/sanity/check_sources_and_headers.py
@@ -36,6 +36,7 @@
   assert False, 'no target %s' % name
 
 def target_has_header(target, name):
+  if name.startswith('absl/'): return True
   # print target['name'], name
   if name in target['headers']:
     return True
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index 97324f0..2aee000 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -35,6 +35,7 @@
  cacf7f1d4e3d44d871b605da3b647f07d718623f third_party/zlib (v1.2.11)
  3be1924221e1326df520f8498d704a5c4c8d0cce third_party/cares/cares (cares-1_13_0)
  73594cde8c9a52a102c4341c244c833aa61b9c06 third_party/bloaty
+ cc4bed2d74f7c8717e31f9579214ab52a9c9c610 third_party/abseil-cpp
 EOF
 
 diff -u $submodules $want_submodules
diff --git a/tools/run_tests/sanity/check_test_filtering.py b/tools/run_tests/sanity/check_test_filtering.py
index 3ebb938..a523f08 100755
--- a/tools/run_tests/sanity/check_test_filtering.py
+++ b/tools/run_tests/sanity/check_test_filtering.py
@@ -81,7 +81,8 @@
     self.test_filtering(['src/core/foo.bar'], [_LIST_OF_LANGUAGE_LABELS])
     # Testing individual languages
     self.test_filtering(['test/core/foo.bar'], [label for label in _LIST_OF_LANGUAGE_LABELS if label not in
-                                                filter_pull_request_tests._CORE_TEST_SUITE.labels])
+                                                filter_pull_request_tests._CORE_TEST_SUITE.labels +
+                                                filter_pull_request_tests._CPP_TEST_SUITE.labels])
     self.test_filtering(['src/cpp/foo.bar'], [label for label in _LIST_OF_LANGUAGE_LABELS if label not in
                                               filter_pull_request_tests._CPP_TEST_SUITE.labels])
     self.test_filtering(['src/csharp/foo.bar'], [label for label in _LIST_OF_LANGUAGE_LABELS if label not in