Merge pull request #14798 from ZhouyihaiDing/macOS_pecl

PHP: fix maxOS distrib test pecl installation error
diff --git a/BUILD b/BUILD
index d59d2ad..c12337e 100644
--- a/BUILD
+++ b/BUILD
@@ -307,8 +307,12 @@
     language = "c++",
     deps = [
         "grpc_base",
+        "grpc_deadline_filter",
         "grpc_http_filters",
+        "grpc_message_size_filter",
+        "grpc_server_load_reporting",
         "grpc_transport_chttp2_client_secure",
+        "grpc_transport_chttp2_server_secure",
         "grpc_transport_cronet_client_secure",
     ],
 )
@@ -1708,6 +1712,9 @@
         "src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc",
         "src/core/tsi/alts/handshaker/alts_tsi_utils.cc",
         "src/core/tsi/fake_transport_security.cc",
+        "src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc",
+        "src/core/tsi/ssl/session_cache/ssl_session_cache.cc",
+        "src/core/tsi/ssl/session_cache/ssl_session_openssl.cc",
         "src/core/tsi/ssl_transport_security.cc",
         "src/core/tsi/transport_security_grpc.cc",
     ],
@@ -1719,6 +1726,8 @@
         "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h",
         "src/core/tsi/alts/handshaker/alts_tsi_utils.h",
         "src/core/tsi/fake_transport_security.h",
+        "src/core/tsi/ssl/session_cache/ssl_session.h",
+        "src/core/tsi/ssl/session_cache/ssl_session_cache.h",
         "src/core/tsi/ssl_transport_security.h",
         "src/core/tsi/ssl_types.h",
         "src/core/tsi/transport_security_grpc.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 56dcb46..ad8548e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -562,6 +562,7 @@
 add_dependencies(buildtests_cxx grpclb_api_test)
 add_dependencies(buildtests_cxx grpclb_end2end_test)
 add_dependencies(buildtests_cxx h2_ssl_cert_test)
+add_dependencies(buildtests_cxx h2_ssl_session_reuse_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)
@@ -1117,6 +1118,9 @@
   src/core/ext/filters/deadline/deadline_filter.cc
   src/core/tsi/alts_transport_security.cc
   src/core/tsi/fake_transport_security.cc
+  src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc
+  src/core/tsi/ssl/session_cache/ssl_session_cache.cc
+  src/core/tsi/ssl/session_cache/ssl_session_openssl.cc
   src/core/tsi/ssl_transport_security.cc
   src/core/tsi/transport_security_grpc.cc
   src/core/ext/transport/chttp2/server/chttp2_server.cc
@@ -1388,6 +1392,10 @@
   src/core/lib/transport/transport.cc
   src/core/lib/transport/transport_op_string.cc
   src/core/lib/debug/trace.cc
+  src/core/ext/filters/deadline/deadline_filter.cc
+  src/core/ext/filters/message_size/message_size_filter.cc
+  src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
+  src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
   src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc
   src/core/ext/transport/cronet/transport/cronet_api_dummy.cc
   src/core/ext/transport/cronet/transport/cronet_transport.cc
@@ -1440,7 +1448,6 @@
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
   src/core/ext/filters/client_channel/uri_parser.cc
-  src/core/ext/filters/deadline/deadline_filter.cc
   src/core/lib/http/httpcli_security_connector.cc
   src/core/lib/security/context/security_context.cc
   src/core/lib/security/credentials/alts/alts_credentials.cc
@@ -1508,10 +1515,13 @@
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/tsi/alts_transport_security.cc
   src/core/tsi/fake_transport_security.cc
+  src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc
+  src/core/tsi/ssl/session_cache/ssl_session_cache.cc
+  src/core/tsi/ssl/session_cache/ssl_session_openssl.cc
   src/core/tsi/ssl_transport_security.cc
   src/core/tsi/transport_security_grpc.cc
-  src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
-  src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
+  src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc
+  src/core/ext/transport/chttp2/server/chttp2_server.cc
   src/core/plugin_registry/grpc_cronet_plugin_registry.cc
 )
 
@@ -1569,9 +1579,20 @@
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
+  include/grpc/byte_buffer.h
+  include/grpc/byte_buffer_reader.h
+  include/grpc/compression.h
+  include/grpc/fork.h
+  include/grpc/grpc.h
+  include/grpc/grpc_posix.h
+  include/grpc/grpc_security_constants.h
+  include/grpc/load_reporting.h
+  include/grpc/slice.h
+  include/grpc/slice_buffer.h
+  include/grpc/status.h
+  include/grpc/support/workaround_list.h
   include/grpc/grpc_cronet.h
   include/grpc/grpc_security.h
-  include/grpc/grpc_security_constants.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
   get_filename_component(_path ${_path} PATH)
@@ -11559,6 +11580,43 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(h2_ssl_session_reuse_test
+  test/core/end2end/h2_ssl_session_reuse_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(h2_ssl_session_reuse_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  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_session_reuse_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
diff --git a/Makefile b/Makefile
index 5088971..134c524 100644
--- a/Makefile
+++ b/Makefile
@@ -1164,6 +1164,7 @@
 grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test
 grpclb_end2end_test: $(BINDIR)/$(CONFIG)/grpclb_end2end_test
 h2_ssl_cert_test: $(BINDIR)/$(CONFIG)/h2_ssl_cert_test
+h2_ssl_session_reuse_test: $(BINDIR)/$(CONFIG)/h2_ssl_session_reuse_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
@@ -1643,6 +1644,7 @@
   $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/grpclb_end2end_test \
   $(BINDIR)/$(CONFIG)/h2_ssl_cert_test \
+  $(BINDIR)/$(CONFIG)/h2_ssl_session_reuse_test \
   $(BINDIR)/$(CONFIG)/health_service_end2end_test \
   $(BINDIR)/$(CONFIG)/http2_client \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
@@ -1810,6 +1812,7 @@
   $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/grpclb_end2end_test \
   $(BINDIR)/$(CONFIG)/h2_ssl_cert_test \
+  $(BINDIR)/$(CONFIG)/h2_ssl_session_reuse_test \
   $(BINDIR)/$(CONFIG)/health_service_end2end_test \
   $(BINDIR)/$(CONFIG)/http2_client \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
@@ -2260,6 +2263,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/grpclb_end2end_test || ( echo test grpclb_end2end_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 h2_ssl_session_reuse_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl_session_reuse_test || ( echo test h2_ssl_session_reuse_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 inlined_vector_test"
@@ -3442,6 +3447,9 @@
     src/core/ext/filters/deadline/deadline_filter.cc \
     src/core/tsi/alts_transport_security.cc \
     src/core/tsi/fake_transport_security.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_cache.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_openssl.cc \
     src/core/tsi/ssl_transport_security.cc \
     src/core/tsi/transport_security_grpc.cc \
     src/core/ext/transport/chttp2/server/chttp2_server.cc \
@@ -3715,6 +3723,10 @@
     src/core/lib/transport/transport.cc \
     src/core/lib/transport/transport_op_string.cc \
     src/core/lib/debug/trace.cc \
+    src/core/ext/filters/deadline/deadline_filter.cc \
+    src/core/ext/filters/message_size/message_size_filter.cc \
+    src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
+    src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
     src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc \
     src/core/ext/transport/cronet/transport/cronet_api_dummy.cc \
     src/core/ext/transport/cronet/transport/cronet_transport.cc \
@@ -3767,7 +3779,6 @@
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
     src/core/ext/filters/client_channel/uri_parser.cc \
-    src/core/ext/filters/deadline/deadline_filter.cc \
     src/core/lib/http/httpcli_security_connector.cc \
     src/core/lib/security/context/security_context.cc \
     src/core/lib/security/credentials/alts/alts_credentials.cc \
@@ -3835,10 +3846,13 @@
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/tsi/alts_transport_security.cc \
     src/core/tsi/fake_transport_security.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_cache.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_openssl.cc \
     src/core/tsi/ssl_transport_security.cc \
     src/core/tsi/transport_security_grpc.cc \
-    src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
-    src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
+    src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc \
+    src/core/ext/transport/chttp2/server/chttp2_server.cc \
     src/core/plugin_registry/grpc_cronet_plugin_registry.cc \
 
 PUBLIC_HEADERS_C += \
@@ -3863,9 +3877,20 @@
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
+    include/grpc/byte_buffer.h \
+    include/grpc/byte_buffer_reader.h \
+    include/grpc/compression.h \
+    include/grpc/fork.h \
+    include/grpc/grpc.h \
+    include/grpc/grpc_posix.h \
+    include/grpc/grpc_security_constants.h \
+    include/grpc/load_reporting.h \
+    include/grpc/slice.h \
+    include/grpc/slice_buffer.h \
+    include/grpc/status.h \
+    include/grpc/support/workaround_list.h \
     include/grpc/grpc_cronet.h \
     include/grpc/grpc_security.h \
-    include/grpc/grpc_security_constants.h \
 
 LIBGRPC_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CRONET_SRC))))
 
@@ -17513,6 +17538,49 @@
 endif
 
 
+H2_SSL_SESSION_REUSE_TEST_SRC = \
+    test/core/end2end/h2_ssl_session_reuse_test.cc \
+
+H2_SSL_SESSION_REUSE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_SSL_SESSION_REUSE_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_ssl_session_reuse_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_session_reuse_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_ssl_session_reuse_test: $(PROTOBUF_DEP) $(H2_SSL_SESSION_REUSE_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_SESSION_REUSE_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_session_reuse_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/h2_ssl_session_reuse_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_session_reuse_test: $(H2_SSL_SESSION_REUSE_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(H2_SSL_SESSION_REUSE_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 HEALTH_SERVICE_END2END_TEST_SRC = \
     test/cpp/end2end/health_service_end2end_test.cc \
 
@@ -23588,6 +23656,9 @@
 src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc: $(OPENSSL_DEP)
 src/core/tsi/alts_transport_security.cc: $(OPENSSL_DEP)
 src/core/tsi/fake_transport_security.cc: $(OPENSSL_DEP)
+src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc: $(OPENSSL_DEP)
+src/core/tsi/ssl/session_cache/ssl_session_cache.cc: $(OPENSSL_DEP)
+src/core/tsi/ssl/session_cache/ssl_session_openssl.cc: $(OPENSSL_DEP)
 src/core/tsi/ssl_transport_security.cc: $(OPENSSL_DEP)
 src/core/tsi/transport_security.cc: $(OPENSSL_DEP)
 src/core/tsi/transport_security_adapter.cc: $(OPENSSL_DEP)
diff --git a/bazel/cc_grpc_library.bzl b/bazel/cc_grpc_library.bzl
index 94781ed..5216a7a 100644
--- a/bazel/cc_grpc_library.bzl
+++ b/bazel/cc_grpc_library.bzl
@@ -2,7 +2,7 @@
 
 load("//:bazel/generate_cc.bzl", "generate_cc")
 
-def cc_grpc_library(name, srcs, deps, proto_only, well_known_protos, generate_mock, use_external = False, **kwargs):
+def cc_grpc_library(name, srcs, deps, proto_only, well_known_protos, generate_mocks = False, use_external = False, **kwargs):
   """Generates C++ grpc classes from a .proto file.
 
   Assumes the generated classes will be used in cc_api_version = 2.
@@ -16,7 +16,7 @@
         protos
       use_external: When True the grpc deps are prefixed with //external. This
         allows grpc to be used as a dependency in other bazel projects.
-      generate_mock: When true GMOCk code for client stub is generated.
+      generate_mocks: When True, Google Mock code for client stub is generated.
       **kwargs: rest of arguments, e.g., compatible_with and visibility.
   """
   if len(srcs) > 1:
@@ -54,7 +54,7 @@
         srcs = [proto_target],
         plugin = plugin,
         well_known_protos = well_known_protos,
-        generate_mock = generate_mock,
+        generate_mocks = generate_mocks,
         **kwargs
     )
 
diff --git a/bazel/generate_cc.bzl b/bazel/generate_cc.bzl
index f88ee2f..e610123 100644
--- a/bazel/generate_cc.bzl
+++ b/bazel/generate_cc.bzl
@@ -14,7 +14,7 @@
   if ctx.executable.plugin:
     outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.h" for proto in protos]
     outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.cc" for proto in protos]
-    if ctx.attr.generate_mock:
+    if ctx.attr.generate_mocks:
       outs += [proto.path[label_len:-len(".proto")] + "_mock.grpc.pb.h" for proto in protos]
   else:
     outs += [proto.path[label_len:-len(".proto")] + ".pb.h" for proto in protos]
@@ -26,7 +26,7 @@
   if ctx.executable.plugin:
     arguments += ["--plugin=protoc-gen-PLUGIN=" + ctx.executable.plugin.path]
     flags = list(ctx.attr.flags)
-    if ctx.attr.generate_mock:
+    if ctx.attr.generate_mocks:
       flags.append("generate_mock_code=true")
     arguments += ["--PLUGIN_out=" + ",".join(flags) + ":" + dir_out]
     additional_input = [ctx.executable.plugin]
@@ -76,7 +76,7 @@
         "well_known_protos" : attr.label(
             mandatory = False,
         ),
-        "generate_mock" : attr.bool(
+        "generate_mocks" : attr.bool(
             default = False,
             mandatory = False,
         ),
diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl
index 571b29c..08dc3de 100644
--- a/bazel/grpc_build_system.bzl
+++ b/bazel/grpc_build_system.bzl
@@ -97,7 +97,7 @@
 load("//:bazel/cc_grpc_library.bzl", "cc_grpc_library")
 
 def grpc_proto_library(name, srcs = [], deps = [], well_known_protos = False,
-                       has_services = True, use_external = False, generate_mock = False):
+                       has_services = True, use_external = False, generate_mocks = False):
   cc_grpc_library(
     name = name,
     srcs = srcs,
@@ -105,7 +105,7 @@
     well_known_protos = well_known_protos,
     proto_only = not has_services,
     use_external = use_external,
-    generate_mock = generate_mock,
+    generate_mocks = generate_mocks,
   )
 
 def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++"):
diff --git a/build.yaml b/build.yaml
index 0dd3d36..71fd59c 100644
--- a/build.yaml
+++ b/build.yaml
@@ -1041,12 +1041,17 @@
   headers:
   - src/core/tsi/alts_transport_security.h
   - src/core/tsi/fake_transport_security.h
+  - src/core/tsi/ssl/session_cache/ssl_session.h
+  - src/core/tsi/ssl/session_cache/ssl_session_cache.h
   - src/core/tsi/ssl_transport_security.h
   - src/core/tsi/ssl_types.h
   - src/core/tsi/transport_security_grpc.h
   src:
   - src/core/tsi/alts_transport_security.cc
   - src/core/tsi/fake_transport_security.cc
+  - src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc
+  - src/core/tsi/ssl/session_cache/ssl_session_cache.cc
+  - src/core/tsi/ssl/session_cache/ssl_session_openssl.cc
   - src/core/tsi/ssl_transport_security.cc
   - src/core/tsi/transport_security_grpc.cc
   deps:
@@ -1391,9 +1396,13 @@
   dll: true
   filegroups:
   - grpc_base
+  - grpc_base_headers
+  - grpc_deadline_filter
+  - grpc_message_size_filter
+  - grpc_server_load_reporting
   - grpc_transport_cronet_client_secure
   - grpc_transport_chttp2_client_secure
-  - grpc_server_load_reporting
+  - grpc_transport_chttp2_server_secure
   generate_plugin_registry: true
   platforms:
   - linux
@@ -4561,6 +4570,22 @@
   - gpr
   uses:
   - grpc++_test
+- name: h2_ssl_session_reuse_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - test/core/end2end/end2end_tests.h
+  src:
+  - test/core/end2end/h2_ssl_session_reuse_test.cc
+  deps:
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
+  uses:
+  - grpc++_test
 - name: health_service_end2end_test
   gtest: true
   build: test
diff --git a/config.m4 b/config.m4
index 3a81f9d..43fac8b 100644
--- a/config.m4
+++ b/config.m4
@@ -345,6 +345,9 @@
     src/core/ext/filters/deadline/deadline_filter.cc \
     src/core/tsi/alts_transport_security.cc \
     src/core/tsi/fake_transport_security.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_cache.cc \
+    src/core/tsi/ssl/session_cache/ssl_session_openssl.cc \
     src/core/tsi/ssl_transport_security.cc \
     src/core/tsi/transport_security_grpc.cc \
     src/core/ext/transport/chttp2/server/chttp2_server.cc \
@@ -702,6 +705,7 @@
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/frame_protector)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/handshaker)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/zero_copy_frame_protector)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/ssl/session_cache)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/asn1)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/base64)
diff --git a/config.w32 b/config.w32
index 76be896..eb05298 100644
--- a/config.w32
+++ b/config.w32
@@ -322,6 +322,9 @@
     "src\\core\\ext\\filters\\deadline\\deadline_filter.cc " +
     "src\\core\\tsi\\alts_transport_security.cc " +
     "src\\core\\tsi\\fake_transport_security.cc " +
+    "src\\core\\tsi\\ssl\\session_cache\\ssl_session_boringssl.cc " +
+    "src\\core\\tsi\\ssl\\session_cache\\ssl_session_cache.cc " +
+    "src\\core\\tsi\\ssl\\session_cache\\ssl_session_openssl.cc " +
     "src\\core\\tsi\\ssl_transport_security.cc " +
     "src\\core\\tsi\\transport_security_grpc.cc " +
     "src\\core\\ext\\transport\\chttp2\\server\\chttp2_server.cc " +
@@ -716,6 +719,8 @@
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\frame_protector");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\handshaker");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\zero_copy_frame_protector");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\ssl");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\ssl\\session_cache");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext\\grpc");
diff --git a/doc/unit_testing.md b/doc/unit_testing.md
index 0aa9be9..ca56481 100644
--- a/doc/unit_testing.md
+++ b/doc/unit_testing.md
@@ -56,7 +56,7 @@
 
 
 1.  Setting flag(generate_mock_code=true) on grpc plugin for protoc, or
-1.  Setting an attribute(generate_mock) in your bazel rule.
+1.  Setting an attribute(generate_mocks) in your bazel rule.
 
 Protoc plugin flag:
 
@@ -70,7 +70,7 @@
 grpc_proto_library(
   name = "echo_proto",
   srcs = ["echo.proto"],
-  generate_mock = True, 
+  generate_mocks = True,
 )
 ```
 
diff --git a/examples/cpp/route_guide/route_guide_server.cc b/examples/cpp/route_guide/route_guide_server.cc
index 24a4184..5867c16 100644
--- a/examples/cpp/route_guide/route_guide_server.cc
+++ b/examples/cpp/route_guide/route_guide_server.cc
@@ -51,6 +51,7 @@
   return num * 3.1415926 /180;
 }
 
+// The formula is based on http://mathforum.org/library/drmath/view/51879.html
 float GetDistance(const Point& start, const Point& end) {
   const float kCoordFactor = 10000000.0;
   float lat_1 = start.latitude() / kCoordFactor;
diff --git a/examples/csharp/route_guide/RouteGuide/RouteGuideUtil.cs b/examples/csharp/route_guide/RouteGuide/RouteGuideUtil.cs
index 66c4a94..f9af190 100644
--- a/examples/csharp/route_guide/RouteGuide/RouteGuideUtil.cs
+++ b/examples/csharp/route_guide/RouteGuide/RouteGuideUtil.cs
@@ -52,26 +52,23 @@
 
         /// <summary>
         /// Calculate the distance between two points using the "haversine" formula.
-        /// This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
+        /// The formula is based on http://mathforum.org/library/drmath/view/51879.html
         /// </summary>
         /// <param name="start">the starting point</param>
         /// <param name="end">the end point</param>
         /// <returns>the distance between the points in meters</returns>
         public static double GetDistance(this Point start, Point end)
         {
-            double lat1 = start.GetLatitude();
-            double lat2 = end.GetLatitude();
-            double lon1 = start.GetLongitude();
-            double lon2 = end.GetLongitude();
-            int r = 6371000; // metres
-            double phi1 = ToRadians(lat1);
-            double phi2 = ToRadians(lat2);
-            double deltaPhi = ToRadians(lat2 - lat1);
-            double deltaLambda = ToRadians(lon2 - lon1);
+            int r = 6371000;  // earth radius in metres
+            double lat1 = ToRadians(start.GetLatitude());
+            double lat2 = ToRadians(end.GetLatitude());
+            double lon1 = ToRadians(start.GetLongitude());
+            double lon2 = ToRadians(end.GetLongitude());
+            double deltalat = lat2 - lat1;
+            double deltalon = lon2 - lon1;
 
-            double a = Math.Sin(deltaPhi / 2) * Math.Sin(deltaPhi / 2) + Math.Cos(phi1) * Math.Cos(phi2) * Math.Sin(deltaLambda / 2) * Math.Sin(deltaLambda / 2);
+            double a = Math.Sin(deltalat / 2) * Math.Sin(deltalat / 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Sin(deltalon / 2) * Math.Sin(deltalon / 2);
             double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
-
             return r * c;
         }
 
diff --git a/examples/node/dynamic_codegen/route_guide/route_guide_server.js b/examples/node/dynamic_codegen/route_guide/route_guide_server.js
index ab537ff..f9028e8 100644
--- a/examples/node/dynamic_codegen/route_guide/route_guide_server.js
+++ b/examples/node/dynamic_codegen/route_guide/route_guide_server.js
@@ -103,7 +103,7 @@
 
 /**
  * Calculate the distance between two points using the "haversine" formula.
- * This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
+ * The formula is based on http://mathforum.org/library/drmath/view/51879.html.
  * @param start The starting point
  * @param end The end point
  * @return The distance between the points in meters
@@ -112,21 +112,18 @@
   function toRadians(num) {
     return num * Math.PI / 180;
   }
-  var lat1 = start.latitude / COORD_FACTOR;
-  var lat2 = end.latitude / COORD_FACTOR;
-  var lon1 = start.longitude / COORD_FACTOR;
-  var lon2 = end.longitude / COORD_FACTOR;
-  var R = 6371000; // metres
-  var φ1 = toRadians(lat1);
-  var φ2 = toRadians(lat2);
-  var Δφ = toRadians(lat2-lat1);
-  var Δλ = toRadians(lon2-lon1);
+  var R = 6371000;  // earth radius in metres
+  var lat1 = toRadians(start.latitude / COORD_FACTOR);
+  var lat2 = toRadians(end.latitude / COORD_FACTOR);
+  var lon1 = toRadians(start.longitude / COORD_FACTOR);
+  var lon2 = toRadians(end.longitude / COORD_FACTOR);
 
-  var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
-      Math.cos(φ1) * Math.cos(φ2) *
-      Math.sin(Δλ/2) * Math.sin(Δλ/2);
+  var deltalat = lat2-lat1;
+  var deltalon = lon2-lon1;
+  var a = Math.sin(deltalat/2) * Math.sin(deltalat/2) +
+      Math.cos(lat1) * Math.cos(lat2) *
+      Math.sin(dlon/2) * Math.sin(dlon/2);
   var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
-
   return R * c;
 }
 
diff --git a/examples/node/static_codegen/route_guide/route_guide_server.js b/examples/node/static_codegen/route_guide/route_guide_server.js
index ef00bbb..eecac62 100644
--- a/examples/node/static_codegen/route_guide/route_guide_server.js
+++ b/examples/node/static_codegen/route_guide/route_guide_server.js
@@ -102,7 +102,7 @@
 
 /**
  * Calculate the distance between two points using the "haversine" formula.
- * This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
+ * The formula is based on http://mathforum.org/library/drmath/view/51879.html.
  * @param start The starting point
  * @param end The end point
  * @return The distance between the points in meters
@@ -111,21 +111,18 @@
   function toRadians(num) {
     return num * Math.PI / 180;
   }
-  var lat1 = start.getLatitude() / COORD_FACTOR;
-  var lat2 = end.getLatitude() / COORD_FACTOR;
-  var lon1 = start.getLongitude() / COORD_FACTOR;
-  var lon2 = end.getLongitude() / COORD_FACTOR;
-  var R = 6371000; // metres
-  var φ1 = toRadians(lat1);
-  var φ2 = toRadians(lat2);
-  var Δφ = toRadians(lat2-lat1);
-  var Δλ = toRadians(lon2-lon1);
+  var R = 6371000;  // earth radius in metres
+  var lat1 = toRadians(start.getLatitude() / COORD_FACTOR);
+  var lat2 = toRadians(end.getLatitude() / COORD_FACTOR);
+  var lon1 = toRadians(start.getLongitude() / COORD_FACTOR);
+  var lon2 = toRadians(end.getLongitude() / COORD_FACTOR);
 
-  var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
-      Math.cos(φ1) * Math.cos(φ2) *
-      Math.sin(Δλ/2) * Math.sin(Δλ/2);
+  var deltalat = lat2-lat1;
+  var deltalon = lon2-lon1;
+  var a = Math.sin(deltalat/2) * Math.sin(deltalat/2) +
+      Math.cos(lat1) * Math.cos(lat2) *
+      Math.sin(deltalon/2) * Math.sin(deltalon/2);
   var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
-
   return R * c;
 }
 
diff --git a/examples/python/route_guide/route_guide_server.py b/examples/python/route_guide/route_guide_server.py
index f10008f..1969fdd 100644
--- a/examples/python/route_guide/route_guide_server.py
+++ b/examples/python/route_guide/route_guide_server.py
@@ -46,6 +46,7 @@
     delta_lat_rad = math.radians(lat_2 - lat_1)
     delta_lon_rad = math.radians(lon_2 - lon_1)
 
+    # Formula is based on http://mathforum.org/library/drmath/view/51879.html
     a = (pow(math.sin(delta_lat_rad / 2), 2) +
          (math.cos(lat_rad_1) * math.cos(lat_rad_2) * pow(
              math.sin(delta_lon_rad / 2), 2)))
diff --git a/examples/ruby/route_guide/route_guide_server.rb b/examples/ruby/route_guide/route_guide_server.rb
index 8ea07a2..5eb268b 100755
--- a/examples/ruby/route_guide/route_guide_server.rb
+++ b/examples/ruby/route_guide/route_guide_server.rb
@@ -32,19 +32,18 @@
 RADIUS = 637_100
 
 # Determines the distance between two points.
+# The formula is based on http://mathforum.org/library/drmath/view/51879.html.
 def calculate_distance(point_a, point_b)
   to_radians = proc { |x| x * Math::PI / 180 }
-  lat_a = point_a.latitude / COORD_FACTOR
-  lat_b = point_b.latitude / COORD_FACTOR
-  long_a = point_a.longitude / COORD_FACTOR
-  long_b = point_b.longitude / COORD_FACTOR
-  φ1 = to_radians.call(lat_a)
-  φ2 = to_radians.call(lat_b)
-  Δφ = to_radians.call(lat_a - lat_b)
-  Δλ = to_radians.call(long_a - long_b)
-  a = Math.sin(Δφ / 2)**2 +
-      Math.cos(φ1) * Math.cos(φ2) +
-      Math.sin(Δλ / 2)**2
+  lat_a = to_radians.call(point_a.latitude / COORD_FACTOR)
+  lat_b = to_radians.call(point_b.latitude / COORD_FACTOR)
+  lon_a = to_radians.call(point_a.longitude / COORD_FACTOR)
+  lon_b = to_radians.call(point_b.longitude / COORD_FACTOR)
+  delta_lat = lat_a - lat_b
+  delta_lon = lon_a - lon_b
+  a = Math.sin(delta_lat / 2)**2 +
+      Math.cos(lat_a) * Math.cos(lat_b) +
+      Math.sin(delta_lon / 2)**2
   (2 * RADIUS *  Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))).to_i
 end
 
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index f42bd4f..f53e9db 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -332,6 +332,8 @@
                       'src/core/ext/filters/deadline/deadline_filter.h',
                       'src/core/tsi/alts_transport_security.h',
                       'src/core/tsi/fake_transport_security.h',
+                      'src/core/tsi/ssl/session_cache/ssl_session.h',
+                      'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
                       'src/core/tsi/ssl_transport_security.h',
                       'src/core/tsi/ssl_types.h',
                       'src/core/tsi/transport_security_grpc.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 634bff2..71f59b9 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -182,7 +182,6 @@
     ss.dependency 'BoringSSL', '~> 10.0'
     ss.dependency 'nanopb', '~> 0.3'
 
-    # To save you from scrolling, this is the last part of the podspec.
     ss.source_files = 'src/core/lib/gpr/arena.h',
                       'src/core/lib/gpr/env.h',
                       'src/core/lib/gpr/fork.h',
@@ -343,6 +342,8 @@
                       'src/core/ext/filters/deadline/deadline_filter.h',
                       'src/core/tsi/alts_transport_security.h',
                       'src/core/tsi/fake_transport_security.h',
+                      'src/core/tsi/ssl/session_cache/ssl_session.h',
+                      'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
                       'src/core/tsi/ssl_transport_security.h',
                       'src/core/tsi/ssl_types.h',
                       'src/core/tsi/transport_security_grpc.h',
@@ -760,6 +761,9 @@
                       'src/core/ext/filters/deadline/deadline_filter.cc',
                       'src/core/tsi/alts_transport_security.cc',
                       'src/core/tsi/fake_transport_security.cc',
+                      'src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc',
+                      'src/core/tsi/ssl/session_cache/ssl_session_cache.cc',
+                      'src/core/tsi/ssl/session_cache/ssl_session_openssl.cc',
                       'src/core/tsi/ssl_transport_security.cc',
                       'src/core/tsi/transport_security_grpc.cc',
                       'src/core/ext/transport/chttp2/server/chttp2_server.cc',
@@ -914,6 +918,8 @@
                               'src/core/ext/filters/deadline/deadline_filter.h',
                               'src/core/tsi/alts_transport_security.h',
                               'src/core/tsi/fake_transport_security.h',
+                              'src/core/tsi/ssl/session_cache/ssl_session.h',
+                              'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
                               'src/core/tsi/ssl_transport_security.h',
                               'src/core/tsi/ssl_types.h',
                               'src/core/tsi/transport_security_grpc.h',
@@ -1071,34 +1077,945 @@
 
   s.subspec 'Cronet-Interface' do |ss|
     ss.header_mappings_dir = 'include/grpc'
-    ss.source_files = 'include/grpc/grpc_cronet.h'
+    ss.source_files = 'include/grpc/support/alloc.h',
+                      'include/grpc/support/atm.h',
+                      'include/grpc/support/atm_gcc_atomic.h',
+                      'include/grpc/support/atm_gcc_sync.h',
+                      'include/grpc/support/atm_windows.h',
+                      'include/grpc/support/cpu.h',
+                      'include/grpc/support/log.h',
+                      'include/grpc/support/log_windows.h',
+                      'include/grpc/support/port_platform.h',
+                      'include/grpc/support/string_util.h',
+                      'include/grpc/support/sync.h',
+                      'include/grpc/support/sync_custom.h',
+                      'include/grpc/support/sync_generic.h',
+                      'include/grpc/support/sync_posix.h',
+                      'include/grpc/support/sync_windows.h',
+                      'include/grpc/support/thd_id.h',
+                      'include/grpc/support/time.h',
+                      'include/grpc/impl/codegen/atm.h',
+                      'include/grpc/impl/codegen/atm_gcc_atomic.h',
+                      'include/grpc/impl/codegen/atm_gcc_sync.h',
+                      'include/grpc/impl/codegen/atm_windows.h',
+                      'include/grpc/impl/codegen/fork.h',
+                      'include/grpc/impl/codegen/gpr_slice.h',
+                      'include/grpc/impl/codegen/gpr_types.h',
+                      'include/grpc/impl/codegen/port_platform.h',
+                      'include/grpc/impl/codegen/sync.h',
+                      'include/grpc/impl/codegen/sync_custom.h',
+                      'include/grpc/impl/codegen/sync_generic.h',
+                      'include/grpc/impl/codegen/sync_posix.h',
+                      'include/grpc/impl/codegen/sync_windows.h',
+                      'include/grpc/impl/codegen/byte_buffer.h',
+                      'include/grpc/impl/codegen/byte_buffer_reader.h',
+                      'include/grpc/impl/codegen/compression_types.h',
+                      'include/grpc/impl/codegen/connectivity_state.h',
+                      'include/grpc/impl/codegen/grpc_types.h',
+                      'include/grpc/impl/codegen/propagation_bits.h',
+                      'include/grpc/impl/codegen/slice.h',
+                      'include/grpc/impl/codegen/status.h',
+                      'include/grpc/impl/codegen/atm.h',
+                      'include/grpc/impl/codegen/atm_gcc_atomic.h',
+                      'include/grpc/impl/codegen/atm_gcc_sync.h',
+                      'include/grpc/impl/codegen/atm_windows.h',
+                      'include/grpc/impl/codegen/fork.h',
+                      'include/grpc/impl/codegen/gpr_slice.h',
+                      'include/grpc/impl/codegen/gpr_types.h',
+                      'include/grpc/impl/codegen/port_platform.h',
+                      'include/grpc/impl/codegen/sync.h',
+                      'include/grpc/impl/codegen/sync_custom.h',
+                      'include/grpc/impl/codegen/sync_generic.h',
+                      'include/grpc/impl/codegen/sync_posix.h',
+                      'include/grpc/impl/codegen/sync_windows.h',
+                      'include/grpc/byte_buffer.h',
+                      'include/grpc/byte_buffer_reader.h',
+                      'include/grpc/compression.h',
+                      'include/grpc/fork.h',
+                      'include/grpc/grpc.h',
+                      'include/grpc/grpc_posix.h',
+                      'include/grpc/grpc_security_constants.h',
+                      'include/grpc/load_reporting.h',
+                      'include/grpc/slice.h',
+                      'include/grpc/slice_buffer.h',
+                      'include/grpc/status.h',
+                      'include/grpc/support/workaround_list.h',
+                      'include/grpc/grpc_cronet.h',
+                      'include/grpc/grpc_security.h'
   end
 
   s.subspec 'Cronet-Implementation' do |ss|
     ss.header_mappings_dir = '.'
-
-    ss.dependency "#{s.name}/Interface", version
-    ss.dependency "#{s.name}/Implementation", version
+    ss.libraries = 'z'
     ss.dependency "#{s.name}/Cronet-Interface", version
+    ss.dependency 'BoringSSL', '~> 10.0'
+    ss.dependency 'nanopb', '~> 0.3'
 
-    ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc',
-                      'src/core/ext/transport/cronet/transport/cronet_transport.cc',
-                      'third_party/nanopb/pb_common.c',
-                      'third_party/nanopb/pb_decode.c',
-                      'third_party/nanopb/pb_encode.c',
+    ss.source_files = 'src/core/lib/gpr/arena.h',
+                      'src/core/lib/gpr/env.h',
+                      'src/core/lib/gpr/fork.h',
+                      'src/core/lib/gpr/host_port.h',
+                      'src/core/lib/gpr/mpscq.h',
+                      'src/core/lib/gpr/murmur_hash.h',
+                      'src/core/lib/gpr/spinlock.h',
+                      'src/core/lib/gpr/string.h',
+                      'src/core/lib/gpr/string_windows.h',
+                      'src/core/lib/gpr/time_precise.h',
+                      'src/core/lib/gpr/tls.h',
+                      'src/core/lib/gpr/tls_gcc.h',
+                      'src/core/lib/gpr/tls_msvc.h',
+                      'src/core/lib/gpr/tls_pthread.h',
+                      'src/core/lib/gpr/tmpfile.h',
+                      'src/core/lib/gpr/useful.h',
+                      'src/core/lib/gprpp/abstract.h',
+                      'src/core/lib/gprpp/atomic.h',
+                      'src/core/lib/gprpp/atomic_with_atm.h',
+                      'src/core/lib/gprpp/atomic_with_std.h',
+                      'src/core/lib/gprpp/manual_constructor.h',
+                      'src/core/lib/gprpp/memory.h',
+                      'src/core/lib/gprpp/thd.h',
+                      'src/core/lib/profiling/timers.h',
+                      'src/core/lib/gpr/alloc.cc',
+                      'src/core/lib/gpr/arena.cc',
+                      'src/core/lib/gpr/atm.cc',
+                      'src/core/lib/gpr/cpu_iphone.cc',
+                      'src/core/lib/gpr/cpu_linux.cc',
+                      'src/core/lib/gpr/cpu_posix.cc',
+                      'src/core/lib/gpr/cpu_windows.cc',
+                      'src/core/lib/gpr/env_linux.cc',
+                      'src/core/lib/gpr/env_posix.cc',
+                      'src/core/lib/gpr/env_windows.cc',
+                      'src/core/lib/gpr/fork.cc',
+                      'src/core/lib/gpr/host_port.cc',
+                      'src/core/lib/gpr/log.cc',
+                      'src/core/lib/gpr/log_android.cc',
+                      'src/core/lib/gpr/log_linux.cc',
+                      'src/core/lib/gpr/log_posix.cc',
+                      'src/core/lib/gpr/log_windows.cc',
+                      'src/core/lib/gpr/mpscq.cc',
+                      'src/core/lib/gpr/murmur_hash.cc',
+                      'src/core/lib/gpr/string.cc',
+                      'src/core/lib/gpr/string_posix.cc',
+                      'src/core/lib/gpr/string_util_windows.cc',
+                      'src/core/lib/gpr/string_windows.cc',
+                      'src/core/lib/gpr/sync.cc',
+                      'src/core/lib/gpr/sync_posix.cc',
+                      'src/core/lib/gpr/sync_windows.cc',
+                      'src/core/lib/gpr/time.cc',
+                      'src/core/lib/gpr/time_posix.cc',
+                      'src/core/lib/gpr/time_precise.cc',
+                      'src/core/lib/gpr/time_windows.cc',
+                      'src/core/lib/gpr/tls_pthread.cc',
+                      'src/core/lib/gpr/tmpfile_msys.cc',
+                      'src/core/lib/gpr/tmpfile_posix.cc',
+                      'src/core/lib/gpr/tmpfile_windows.cc',
+                      'src/core/lib/gpr/wrap_memcpy.cc',
+                      'src/core/lib/gprpp/thd_posix.cc',
+                      'src/core/lib/gprpp/thd_windows.cc',
+                      'src/core/lib/profiling/basic_timers.cc',
+                      'src/core/lib/profiling/stap_timers.cc',
+                      'src/core/lib/avl/avl.h',
+                      'src/core/lib/backoff/backoff.h',
+                      'src/core/lib/channel/channel_args.h',
+                      'src/core/lib/channel/channel_stack.h',
+                      'src/core/lib/channel/channel_stack_builder.h',
+                      'src/core/lib/channel/channel_trace.h',
+                      'src/core/lib/channel/channel_trace_registry.h',
+                      'src/core/lib/channel/connected_channel.h',
+                      'src/core/lib/channel/context.h',
+                      'src/core/lib/channel/handshaker.h',
+                      'src/core/lib/channel/handshaker_factory.h',
+                      'src/core/lib/channel/handshaker_registry.h',
+                      'src/core/lib/channel/status_util.h',
+                      'src/core/lib/compression/algorithm_metadata.h',
+                      'src/core/lib/compression/compression_internal.h',
+                      'src/core/lib/compression/message_compress.h',
+                      'src/core/lib/compression/stream_compression.h',
+                      'src/core/lib/compression/stream_compression_gzip.h',
+                      'src/core/lib/compression/stream_compression_identity.h',
+                      'src/core/lib/debug/stats.h',
+                      'src/core/lib/debug/stats_data.h',
+                      'src/core/lib/gprpp/debug_location.h',
+                      'src/core/lib/gprpp/inlined_vector.h',
+                      'src/core/lib/gprpp/orphanable.h',
+                      'src/core/lib/gprpp/ref_counted.h',
+                      'src/core/lib/gprpp/ref_counted_ptr.h',
+                      'src/core/lib/http/format_request.h',
+                      'src/core/lib/http/httpcli.h',
+                      'src/core/lib/http/parser.h',
+                      'src/core/lib/iomgr/block_annotate.h',
+                      'src/core/lib/iomgr/call_combiner.h',
+                      'src/core/lib/iomgr/closure.h',
+                      'src/core/lib/iomgr/combiner.h',
+                      'src/core/lib/iomgr/endpoint.h',
+                      'src/core/lib/iomgr/endpoint_pair.h',
+                      'src/core/lib/iomgr/error.h',
+                      'src/core/lib/iomgr/error_internal.h',
+                      'src/core/lib/iomgr/ev_epoll1_linux.h',
+                      'src/core/lib/iomgr/ev_epollex_linux.h',
+                      'src/core/lib/iomgr/ev_epollsig_linux.h',
+                      'src/core/lib/iomgr/ev_poll_posix.h',
+                      'src/core/lib/iomgr/ev_posix.h',
+                      'src/core/lib/iomgr/exec_ctx.h',
+                      'src/core/lib/iomgr/executor.h',
+                      'src/core/lib/iomgr/gethostname.h',
+                      'src/core/lib/iomgr/iocp_windows.h',
+                      'src/core/lib/iomgr/iomgr.h',
+                      'src/core/lib/iomgr/iomgr_custom.h',
+                      'src/core/lib/iomgr/iomgr_internal.h',
+                      'src/core/lib/iomgr/iomgr_posix.h',
+                      'src/core/lib/iomgr/is_epollexclusive_available.h',
+                      'src/core/lib/iomgr/load_file.h',
+                      'src/core/lib/iomgr/lockfree_event.h',
+                      'src/core/lib/iomgr/nameser.h',
+                      'src/core/lib/iomgr/network_status_tracker.h',
+                      'src/core/lib/iomgr/polling_entity.h',
+                      'src/core/lib/iomgr/pollset.h',
+                      'src/core/lib/iomgr/pollset_custom.h',
+                      'src/core/lib/iomgr/pollset_set.h',
+                      'src/core/lib/iomgr/pollset_set_custom.h',
+                      'src/core/lib/iomgr/pollset_set_windows.h',
+                      'src/core/lib/iomgr/pollset_windows.h',
+                      'src/core/lib/iomgr/port.h',
+                      'src/core/lib/iomgr/resolve_address.h',
+                      'src/core/lib/iomgr/resolve_address_custom.h',
+                      'src/core/lib/iomgr/resource_quota.h',
+                      'src/core/lib/iomgr/sockaddr.h',
+                      'src/core/lib/iomgr/sockaddr_custom.h',
+                      'src/core/lib/iomgr/sockaddr_posix.h',
+                      'src/core/lib/iomgr/sockaddr_utils.h',
+                      'src/core/lib/iomgr/sockaddr_windows.h',
+                      'src/core/lib/iomgr/socket_factory_posix.h',
+                      'src/core/lib/iomgr/socket_mutator.h',
+                      'src/core/lib/iomgr/socket_utils.h',
+                      'src/core/lib/iomgr/socket_utils_posix.h',
+                      'src/core/lib/iomgr/socket_windows.h',
+                      'src/core/lib/iomgr/sys_epoll_wrapper.h',
+                      'src/core/lib/iomgr/tcp_client.h',
+                      'src/core/lib/iomgr/tcp_client_posix.h',
+                      'src/core/lib/iomgr/tcp_custom.h',
+                      'src/core/lib/iomgr/tcp_posix.h',
+                      'src/core/lib/iomgr/tcp_server.h',
+                      'src/core/lib/iomgr/tcp_server_utils_posix.h',
+                      'src/core/lib/iomgr/tcp_windows.h',
+                      'src/core/lib/iomgr/time_averaged_stats.h',
+                      'src/core/lib/iomgr/timer.h',
+                      'src/core/lib/iomgr/timer_custom.h',
+                      'src/core/lib/iomgr/timer_heap.h',
+                      'src/core/lib/iomgr/timer_manager.h',
+                      'src/core/lib/iomgr/udp_server.h',
+                      'src/core/lib/iomgr/unix_sockets_posix.h',
+                      'src/core/lib/iomgr/wakeup_fd_cv.h',
+                      'src/core/lib/iomgr/wakeup_fd_pipe.h',
+                      'src/core/lib/iomgr/wakeup_fd_posix.h',
+                      'src/core/lib/json/json.h',
+                      'src/core/lib/json/json_common.h',
+                      'src/core/lib/json/json_reader.h',
+                      'src/core/lib/json/json_writer.h',
+                      'src/core/lib/slice/b64.h',
+                      'src/core/lib/slice/percent_encoding.h',
+                      'src/core/lib/slice/slice_hash_table.h',
+                      'src/core/lib/slice/slice_internal.h',
+                      'src/core/lib/slice/slice_string_helpers.h',
+                      'src/core/lib/slice/slice_weak_hash_table.h',
+                      'src/core/lib/surface/api_trace.h',
+                      'src/core/lib/surface/call.h',
+                      'src/core/lib/surface/call_test_only.h',
+                      'src/core/lib/surface/channel.h',
+                      'src/core/lib/surface/channel_init.h',
+                      'src/core/lib/surface/channel_stack_type.h',
+                      'src/core/lib/surface/completion_queue.h',
+                      'src/core/lib/surface/completion_queue_factory.h',
+                      'src/core/lib/surface/event_string.h',
+                      'src/core/lib/surface/init.h',
+                      'src/core/lib/surface/lame_client.h',
+                      'src/core/lib/surface/server.h',
+                      'src/core/lib/surface/validate_metadata.h',
+                      'src/core/lib/transport/bdp_estimator.h',
+                      'src/core/lib/transport/byte_stream.h',
+                      'src/core/lib/transport/connectivity_state.h',
+                      'src/core/lib/transport/error_utils.h',
+                      'src/core/lib/transport/http2_errors.h',
+                      'src/core/lib/transport/metadata.h',
+                      'src/core/lib/transport/metadata_batch.h',
+                      'src/core/lib/transport/pid_controller.h',
+                      'src/core/lib/transport/service_config.h',
+                      'src/core/lib/transport/static_metadata.h',
+                      'src/core/lib/transport/status_conversion.h',
+                      'src/core/lib/transport/status_metadata.h',
+                      'src/core/lib/transport/timeout_encoding.h',
+                      'src/core/lib/transport/transport.h',
+                      'src/core/lib/transport/transport_impl.h',
+                      'src/core/lib/debug/trace.h',
+                      'src/core/ext/filters/deadline/deadline_filter.h',
+                      'src/core/ext/filters/message_size/message_size_filter.h',
+                      'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
+                      'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
                       'src/core/ext/transport/cronet/transport/cronet_transport.h',
                       'third_party/objective_c/Cronet/bidirectional_stream_c.h',
+                      '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',
+                      'src/core/ext/transport/chttp2/transport/frame_ping.h',
+                      'src/core/ext/transport/chttp2/transport/frame_rst_stream.h',
+                      'src/core/ext/transport/chttp2/transport/frame_settings.h',
+                      'src/core/ext/transport/chttp2/transport/frame_window_update.h',
+                      'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
+                      'src/core/ext/transport/chttp2/transport/hpack_parser.h',
+                      'src/core/ext/transport/chttp2/transport/hpack_table.h',
+                      'src/core/ext/transport/chttp2/transport/http2_settings.h',
+                      'src/core/ext/transport/chttp2/transport/huffsyms.h',
+                      'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
+                      'src/core/ext/transport/chttp2/transport/internal.h',
+                      'src/core/ext/transport/chttp2/transport/stream_map.h',
+                      'src/core/ext/transport/chttp2/transport/varint.h',
+                      'src/core/ext/transport/chttp2/alpn/alpn.h',
+                      'src/core/ext/filters/http/client/http_client_filter.h',
+                      'src/core/ext/filters/http/message_compress/message_compress_filter.h',
+                      'src/core/ext/filters/http/server/http_server_filter.h',
+                      'src/core/ext/filters/client_channel/backup_poller.h',
+                      'src/core/ext/filters/client_channel/client_channel.h',
+                      'src/core/ext/filters/client_channel/client_channel_factory.h',
+                      'src/core/ext/filters/client_channel/connector.h',
+                      'src/core/ext/filters/client_channel/http_connect_handshaker.h',
+                      'src/core/ext/filters/client_channel/http_proxy.h',
+                      'src/core/ext/filters/client_channel/lb_policy.h',
+                      'src/core/ext/filters/client_channel/lb_policy_factory.h',
+                      'src/core/ext/filters/client_channel/lb_policy_registry.h',
+                      'src/core/ext/filters/client_channel/method_params.h',
+                      'src/core/ext/filters/client_channel/parse_address.h',
+                      'src/core/ext/filters/client_channel/proxy_mapper.h',
+                      'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
+                      'src/core/ext/filters/client_channel/resolver.h',
+                      'src/core/ext/filters/client_channel/resolver_factory.h',
+                      'src/core/ext/filters/client_channel/resolver_registry.h',
+                      'src/core/ext/filters/client_channel/retry_throttle.h',
+                      'src/core/ext/filters/client_channel/subchannel.h',
+                      'src/core/ext/filters/client_channel/subchannel_index.h',
+                      'src/core/ext/filters/client_channel/uri_parser.h',
+                      'src/core/lib/security/context/security_context.h',
+                      'src/core/lib/security/credentials/alts/alts_credentials.h',
+                      'src/core/lib/security/credentials/composite/composite_credentials.h',
+                      'src/core/lib/security/credentials/credentials.h',
+                      'src/core/lib/security/credentials/fake/fake_credentials.h',
+                      'src/core/lib/security/credentials/google_default/google_default_credentials.h',
+                      'src/core/lib/security/credentials/iam/iam_credentials.h',
+                      'src/core/lib/security/credentials/jwt/json_token.h',
+                      'src/core/lib/security/credentials/jwt/jwt_credentials.h',
+                      'src/core/lib/security/credentials/jwt/jwt_verifier.h',
+                      'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
+                      'src/core/lib/security/credentials/plugin/plugin_credentials.h',
+                      'src/core/lib/security/credentials/ssl/ssl_credentials.h',
+                      'src/core/lib/security/security_connector/alts_security_connector.h',
+                      'src/core/lib/security/security_connector/security_connector.h',
+                      'src/core/lib/security/transport/auth_filters.h',
+                      'src/core/lib/security/transport/secure_endpoint.h',
+                      'src/core/lib/security/transport/security_handshaker.h',
+                      'src/core/lib/security/transport/target_authority_table.h',
+                      'src/core/lib/security/transport/tsi_error.h',
+                      'src/core/lib/security/util/json_util.h',
+                      'src/core/tsi/alts/crypt/gsec.h',
+                      'src/core/tsi/alts/frame_protector/alts_counter.h',
+                      'src/core/tsi/alts/frame_protector/alts_crypter.h',
+                      'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
+                      'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
+                      'src/core/tsi/alts/frame_protector/frame_handler.h',
+                      'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
+                      'src/core/tsi/alts/handshaker/alts_tsi_event.h',
+                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
+                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
+                      'src/core/lib/security/credentials/alts/check_gcp_environment.h',
+                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
+                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
+                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
+                      'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
+                      'src/core/tsi/alts/handshaker/transport_security_common_api.h',
+                      'src/core/tsi/alts/handshaker/altscontext.pb.h',
+                      'src/core/tsi/alts/handshaker/handshaker.pb.h',
+                      'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
                       'third_party/nanopb/pb.h',
                       'third_party/nanopb/pb_common.h',
                       'third_party/nanopb/pb_decode.h',
-                      'third_party/nanopb/pb_encode.h'
+                      'third_party/nanopb/pb_encode.h',
+                      'src/core/tsi/transport_security.h',
+                      'src/core/tsi/transport_security_adapter.h',
+                      'src/core/tsi/transport_security_interface.h',
+                      'src/core/ext/transport/chttp2/client/chttp2_connector.h',
+                      'src/core/tsi/alts_transport_security.h',
+                      'src/core/tsi/fake_transport_security.h',
+                      'src/core/tsi/ssl/session_cache/ssl_session.h',
+                      'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
+                      'src/core/tsi/ssl_transport_security.h',
+                      'src/core/tsi/ssl_types.h',
+                      'src/core/tsi/transport_security_grpc.h',
+                      'src/core/ext/transport/chttp2/server/chttp2_server.h',
+                      'src/core/lib/surface/init.cc',
+                      'src/core/lib/avl/avl.cc',
+                      'src/core/lib/backoff/backoff.cc',
+                      'src/core/lib/channel/channel_args.cc',
+                      'src/core/lib/channel/channel_stack.cc',
+                      'src/core/lib/channel/channel_stack_builder.cc',
+                      'src/core/lib/channel/channel_trace.cc',
+                      'src/core/lib/channel/channel_trace_registry.cc',
+                      'src/core/lib/channel/connected_channel.cc',
+                      'src/core/lib/channel/handshaker.cc',
+                      'src/core/lib/channel/handshaker_factory.cc',
+                      'src/core/lib/channel/handshaker_registry.cc',
+                      'src/core/lib/channel/status_util.cc',
+                      'src/core/lib/compression/compression.cc',
+                      'src/core/lib/compression/compression_internal.cc',
+                      'src/core/lib/compression/message_compress.cc',
+                      'src/core/lib/compression/stream_compression.cc',
+                      'src/core/lib/compression/stream_compression_gzip.cc',
+                      'src/core/lib/compression/stream_compression_identity.cc',
+                      'src/core/lib/debug/stats.cc',
+                      'src/core/lib/debug/stats_data.cc',
+                      'src/core/lib/http/format_request.cc',
+                      'src/core/lib/http/httpcli.cc',
+                      'src/core/lib/http/parser.cc',
+                      'src/core/lib/iomgr/call_combiner.cc',
+                      'src/core/lib/iomgr/combiner.cc',
+                      'src/core/lib/iomgr/endpoint.cc',
+                      'src/core/lib/iomgr/endpoint_pair_posix.cc',
+                      'src/core/lib/iomgr/endpoint_pair_uv.cc',
+                      'src/core/lib/iomgr/endpoint_pair_windows.cc',
+                      'src/core/lib/iomgr/error.cc',
+                      'src/core/lib/iomgr/ev_epoll1_linux.cc',
+                      'src/core/lib/iomgr/ev_epollex_linux.cc',
+                      'src/core/lib/iomgr/ev_epollsig_linux.cc',
+                      'src/core/lib/iomgr/ev_poll_posix.cc',
+                      'src/core/lib/iomgr/ev_posix.cc',
+                      'src/core/lib/iomgr/ev_windows.cc',
+                      'src/core/lib/iomgr/exec_ctx.cc',
+                      'src/core/lib/iomgr/executor.cc',
+                      'src/core/lib/iomgr/fork_posix.cc',
+                      'src/core/lib/iomgr/fork_windows.cc',
+                      'src/core/lib/iomgr/gethostname_fallback.cc',
+                      'src/core/lib/iomgr/gethostname_host_name_max.cc',
+                      'src/core/lib/iomgr/gethostname_sysconf.cc',
+                      'src/core/lib/iomgr/iocp_windows.cc',
+                      'src/core/lib/iomgr/iomgr.cc',
+                      'src/core/lib/iomgr/iomgr_custom.cc',
+                      'src/core/lib/iomgr/iomgr_internal.cc',
+                      'src/core/lib/iomgr/iomgr_posix.cc',
+                      'src/core/lib/iomgr/iomgr_uv.cc',
+                      'src/core/lib/iomgr/iomgr_windows.cc',
+                      'src/core/lib/iomgr/is_epollexclusive_available.cc',
+                      'src/core/lib/iomgr/load_file.cc',
+                      'src/core/lib/iomgr/lockfree_event.cc',
+                      'src/core/lib/iomgr/network_status_tracker.cc',
+                      'src/core/lib/iomgr/polling_entity.cc',
+                      'src/core/lib/iomgr/pollset.cc',
+                      'src/core/lib/iomgr/pollset_custom.cc',
+                      'src/core/lib/iomgr/pollset_set.cc',
+                      'src/core/lib/iomgr/pollset_set_custom.cc',
+                      'src/core/lib/iomgr/pollset_set_windows.cc',
+                      'src/core/lib/iomgr/pollset_uv.cc',
+                      'src/core/lib/iomgr/pollset_windows.cc',
+                      'src/core/lib/iomgr/resolve_address.cc',
+                      'src/core/lib/iomgr/resolve_address_custom.cc',
+                      'src/core/lib/iomgr/resolve_address_posix.cc',
+                      'src/core/lib/iomgr/resolve_address_windows.cc',
+                      'src/core/lib/iomgr/resource_quota.cc',
+                      'src/core/lib/iomgr/sockaddr_utils.cc',
+                      'src/core/lib/iomgr/socket_factory_posix.cc',
+                      'src/core/lib/iomgr/socket_mutator.cc',
+                      'src/core/lib/iomgr/socket_utils_common_posix.cc',
+                      'src/core/lib/iomgr/socket_utils_linux.cc',
+                      'src/core/lib/iomgr/socket_utils_posix.cc',
+                      'src/core/lib/iomgr/socket_utils_uv.cc',
+                      'src/core/lib/iomgr/socket_utils_windows.cc',
+                      'src/core/lib/iomgr/socket_windows.cc',
+                      'src/core/lib/iomgr/tcp_client.cc',
+                      'src/core/lib/iomgr/tcp_client_custom.cc',
+                      'src/core/lib/iomgr/tcp_client_posix.cc',
+                      'src/core/lib/iomgr/tcp_client_windows.cc',
+                      'src/core/lib/iomgr/tcp_custom.cc',
+                      'src/core/lib/iomgr/tcp_posix.cc',
+                      'src/core/lib/iomgr/tcp_server.cc',
+                      'src/core/lib/iomgr/tcp_server_custom.cc',
+                      'src/core/lib/iomgr/tcp_server_posix.cc',
+                      'src/core/lib/iomgr/tcp_server_utils_posix_common.cc',
+                      'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc',
+                      'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc',
+                      'src/core/lib/iomgr/tcp_server_windows.cc',
+                      'src/core/lib/iomgr/tcp_uv.cc',
+                      'src/core/lib/iomgr/tcp_windows.cc',
+                      'src/core/lib/iomgr/time_averaged_stats.cc',
+                      'src/core/lib/iomgr/timer.cc',
+                      'src/core/lib/iomgr/timer_custom.cc',
+                      'src/core/lib/iomgr/timer_generic.cc',
+                      'src/core/lib/iomgr/timer_heap.cc',
+                      'src/core/lib/iomgr/timer_manager.cc',
+                      'src/core/lib/iomgr/timer_uv.cc',
+                      'src/core/lib/iomgr/udp_server.cc',
+                      'src/core/lib/iomgr/unix_sockets_posix.cc',
+                      'src/core/lib/iomgr/unix_sockets_posix_noop.cc',
+                      'src/core/lib/iomgr/wakeup_fd_cv.cc',
+                      'src/core/lib/iomgr/wakeup_fd_eventfd.cc',
+                      'src/core/lib/iomgr/wakeup_fd_nospecial.cc',
+                      'src/core/lib/iomgr/wakeup_fd_pipe.cc',
+                      'src/core/lib/iomgr/wakeup_fd_posix.cc',
+                      'src/core/lib/json/json.cc',
+                      'src/core/lib/json/json_reader.cc',
+                      'src/core/lib/json/json_string.cc',
+                      'src/core/lib/json/json_writer.cc',
+                      'src/core/lib/slice/b64.cc',
+                      'src/core/lib/slice/percent_encoding.cc',
+                      'src/core/lib/slice/slice.cc',
+                      'src/core/lib/slice/slice_buffer.cc',
+                      'src/core/lib/slice/slice_intern.cc',
+                      'src/core/lib/slice/slice_string_helpers.cc',
+                      'src/core/lib/surface/api_trace.cc',
+                      'src/core/lib/surface/byte_buffer.cc',
+                      'src/core/lib/surface/byte_buffer_reader.cc',
+                      'src/core/lib/surface/call.cc',
+                      'src/core/lib/surface/call_details.cc',
+                      'src/core/lib/surface/call_log_batch.cc',
+                      'src/core/lib/surface/channel.cc',
+                      'src/core/lib/surface/channel_init.cc',
+                      'src/core/lib/surface/channel_ping.cc',
+                      'src/core/lib/surface/channel_stack_type.cc',
+                      'src/core/lib/surface/completion_queue.cc',
+                      'src/core/lib/surface/completion_queue_factory.cc',
+                      'src/core/lib/surface/event_string.cc',
+                      'src/core/lib/surface/lame_client.cc',
+                      'src/core/lib/surface/metadata_array.cc',
+                      'src/core/lib/surface/server.cc',
+                      'src/core/lib/surface/validate_metadata.cc',
+                      'src/core/lib/surface/version.cc',
+                      'src/core/lib/transport/bdp_estimator.cc',
+                      'src/core/lib/transport/byte_stream.cc',
+                      'src/core/lib/transport/connectivity_state.cc',
+                      'src/core/lib/transport/error_utils.cc',
+                      'src/core/lib/transport/metadata.cc',
+                      'src/core/lib/transport/metadata_batch.cc',
+                      'src/core/lib/transport/pid_controller.cc',
+                      'src/core/lib/transport/service_config.cc',
+                      'src/core/lib/transport/static_metadata.cc',
+                      'src/core/lib/transport/status_conversion.cc',
+                      'src/core/lib/transport/status_metadata.cc',
+                      'src/core/lib/transport/timeout_encoding.cc',
+                      'src/core/lib/transport/transport.cc',
+                      'src/core/lib/transport/transport_op_string.cc',
+                      'src/core/lib/debug/trace.cc',
+                      'src/core/ext/filters/deadline/deadline_filter.cc',
+                      'src/core/ext/filters/message_size/message_size_filter.cc',
+                      'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
+                      'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
+                      'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc',
+                      'src/core/ext/transport/cronet/transport/cronet_transport.cc',
+                      'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
+                      'src/core/ext/transport/chttp2/transport/bin_decoder.cc',
+                      'src/core/ext/transport/chttp2/transport/bin_encoder.cc',
+                      'src/core/ext/transport/chttp2/transport/chttp2_plugin.cc',
+                      'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
+                      'src/core/ext/transport/chttp2/transport/flow_control.cc',
+                      'src/core/ext/transport/chttp2/transport/frame_data.cc',
+                      'src/core/ext/transport/chttp2/transport/frame_goaway.cc',
+                      'src/core/ext/transport/chttp2/transport/frame_ping.cc',
+                      'src/core/ext/transport/chttp2/transport/frame_rst_stream.cc',
+                      'src/core/ext/transport/chttp2/transport/frame_settings.cc',
+                      'src/core/ext/transport/chttp2/transport/frame_window_update.cc',
+                      'src/core/ext/transport/chttp2/transport/hpack_encoder.cc',
+                      'src/core/ext/transport/chttp2/transport/hpack_parser.cc',
+                      'src/core/ext/transport/chttp2/transport/hpack_table.cc',
+                      'src/core/ext/transport/chttp2/transport/http2_settings.cc',
+                      'src/core/ext/transport/chttp2/transport/huffsyms.cc',
+                      'src/core/ext/transport/chttp2/transport/incoming_metadata.cc',
+                      'src/core/ext/transport/chttp2/transport/parsing.cc',
+                      'src/core/ext/transport/chttp2/transport/stream_lists.cc',
+                      'src/core/ext/transport/chttp2/transport/stream_map.cc',
+                      'src/core/ext/transport/chttp2/transport/varint.cc',
+                      'src/core/ext/transport/chttp2/transport/writing.cc',
+                      'src/core/ext/transport/chttp2/alpn/alpn.cc',
+                      'src/core/ext/filters/http/client/http_client_filter.cc',
+                      'src/core/ext/filters/http/http_filters_plugin.cc',
+                      'src/core/ext/filters/http/message_compress/message_compress_filter.cc',
+                      'src/core/ext/filters/http/server/http_server_filter.cc',
+                      'src/core/ext/filters/client_channel/backup_poller.cc',
+                      'src/core/ext/filters/client_channel/channel_connectivity.cc',
+                      'src/core/ext/filters/client_channel/client_channel.cc',
+                      'src/core/ext/filters/client_channel/client_channel_factory.cc',
+                      'src/core/ext/filters/client_channel/client_channel_plugin.cc',
+                      'src/core/ext/filters/client_channel/connector.cc',
+                      'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
+                      'src/core/ext/filters/client_channel/http_proxy.cc',
+                      'src/core/ext/filters/client_channel/lb_policy.cc',
+                      'src/core/ext/filters/client_channel/lb_policy_factory.cc',
+                      'src/core/ext/filters/client_channel/lb_policy_registry.cc',
+                      'src/core/ext/filters/client_channel/method_params.cc',
+                      'src/core/ext/filters/client_channel/parse_address.cc',
+                      'src/core/ext/filters/client_channel/proxy_mapper.cc',
+                      'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
+                      'src/core/ext/filters/client_channel/resolver.cc',
+                      'src/core/ext/filters/client_channel/resolver_registry.cc',
+                      'src/core/ext/filters/client_channel/retry_throttle.cc',
+                      'src/core/ext/filters/client_channel/subchannel.cc',
+                      'src/core/ext/filters/client_channel/subchannel_index.cc',
+                      'src/core/ext/filters/client_channel/uri_parser.cc',
+                      'src/core/lib/http/httpcli_security_connector.cc',
+                      'src/core/lib/security/context/security_context.cc',
+                      'src/core/lib/security/credentials/alts/alts_credentials.cc',
+                      'src/core/lib/security/credentials/composite/composite_credentials.cc',
+                      'src/core/lib/security/credentials/credentials.cc',
+                      'src/core/lib/security/credentials/credentials_metadata.cc',
+                      'src/core/lib/security/credentials/fake/fake_credentials.cc',
+                      'src/core/lib/security/credentials/google_default/credentials_generic.cc',
+                      'src/core/lib/security/credentials/google_default/google_default_credentials.cc',
+                      'src/core/lib/security/credentials/iam/iam_credentials.cc',
+                      'src/core/lib/security/credentials/jwt/json_token.cc',
+                      'src/core/lib/security/credentials/jwt/jwt_credentials.cc',
+                      'src/core/lib/security/credentials/jwt/jwt_verifier.cc',
+                      'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc',
+                      'src/core/lib/security/credentials/plugin/plugin_credentials.cc',
+                      'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
+                      'src/core/lib/security/security_connector/alts_security_connector.cc',
+                      'src/core/lib/security/security_connector/security_connector.cc',
+                      'src/core/lib/security/transport/client_auth_filter.cc',
+                      'src/core/lib/security/transport/secure_endpoint.cc',
+                      'src/core/lib/security/transport/security_handshaker.cc',
+                      'src/core/lib/security/transport/server_auth_filter.cc',
+                      'src/core/lib/security/transport/target_authority_table.cc',
+                      'src/core/lib/security/transport/tsi_error.cc',
+                      'src/core/lib/security/util/json_util.cc',
+                      'src/core/lib/surface/init_secure.cc',
+                      'src/core/tsi/alts/crypt/aes_gcm.cc',
+                      'src/core/tsi/alts/crypt/gsec.cc',
+                      'src/core/tsi/alts/frame_protector/alts_counter.cc',
+                      'src/core/tsi/alts/frame_protector/alts_crypter.cc',
+                      'src/core/tsi/alts/frame_protector/alts_frame_protector.cc',
+                      'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc',
+                      'src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc',
+                      'src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc',
+                      'src/core/tsi/alts/frame_protector/frame_handler.cc',
+                      'src/core/tsi/alts/handshaker/alts_handshaker_client.cc',
+                      'src/core/tsi/alts/handshaker/alts_tsi_event.cc',
+                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc',
+                      'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc',
+                      'src/core/lib/security/credentials/alts/check_gcp_environment.cc',
+                      'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc',
+                      'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc',
+                      'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc',
+                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc',
+                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc',
+                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc',
+                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc',
+                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc',
+                      'src/core/tsi/alts/handshaker/alts_tsi_utils.cc',
+                      'src/core/tsi/alts/handshaker/transport_security_common_api.cc',
+                      'src/core/tsi/alts/handshaker/altscontext.pb.c',
+                      'src/core/tsi/alts/handshaker/handshaker.pb.c',
+                      'src/core/tsi/alts/handshaker/transport_security_common.pb.c',
+                      'third_party/nanopb/pb_common.c',
+                      'third_party/nanopb/pb_decode.c',
+                      'third_party/nanopb/pb_encode.c',
+                      'src/core/tsi/transport_security.cc',
+                      'src/core/tsi/transport_security_adapter.cc',
+                      'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
+                      'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+                      'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
+                      'src/core/tsi/alts_transport_security.cc',
+                      'src/core/tsi/fake_transport_security.cc',
+                      'src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc',
+                      'src/core/tsi/ssl/session_cache/ssl_session_cache.cc',
+                      'src/core/tsi/ssl/session_cache/ssl_session_openssl.cc',
+                      'src/core/tsi/ssl_transport_security.cc',
+                      'src/core/tsi/transport_security_grpc.cc',
+                      'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc',
+                      'src/core/ext/transport/chttp2/server/chttp2_server.cc',
+                      'src/core/plugin_registry/grpc_cronet_plugin_registry.cc'
+
+    ss.private_header_files = 'src/core/lib/gpr/arena.h',
+                              'src/core/lib/gpr/env.h',
+                              'src/core/lib/gpr/fork.h',
+                              'src/core/lib/gpr/host_port.h',
+                              'src/core/lib/gpr/mpscq.h',
+                              'src/core/lib/gpr/murmur_hash.h',
+                              'src/core/lib/gpr/spinlock.h',
+                              'src/core/lib/gpr/string.h',
+                              'src/core/lib/gpr/string_windows.h',
+                              'src/core/lib/gpr/time_precise.h',
+                              'src/core/lib/gpr/tls.h',
+                              'src/core/lib/gpr/tls_gcc.h',
+                              'src/core/lib/gpr/tls_msvc.h',
+                              'src/core/lib/gpr/tls_pthread.h',
+                              'src/core/lib/gpr/tmpfile.h',
+                              'src/core/lib/gpr/useful.h',
+                              'src/core/lib/gprpp/abstract.h',
+                              'src/core/lib/gprpp/atomic.h',
+                              'src/core/lib/gprpp/atomic_with_atm.h',
+                              'src/core/lib/gprpp/atomic_with_std.h',
+                              'src/core/lib/gprpp/manual_constructor.h',
+                              'src/core/lib/gprpp/memory.h',
+                              'src/core/lib/gprpp/thd.h',
+                              'src/core/lib/profiling/timers.h',
+                              'src/core/lib/avl/avl.h',
+                              'src/core/lib/backoff/backoff.h',
+                              'src/core/lib/channel/channel_args.h',
+                              'src/core/lib/channel/channel_stack.h',
+                              'src/core/lib/channel/channel_stack_builder.h',
+                              'src/core/lib/channel/channel_trace.h',
+                              'src/core/lib/channel/channel_trace_registry.h',
+                              'src/core/lib/channel/connected_channel.h',
+                              'src/core/lib/channel/context.h',
+                              'src/core/lib/channel/handshaker.h',
+                              'src/core/lib/channel/handshaker_factory.h',
+                              'src/core/lib/channel/handshaker_registry.h',
+                              'src/core/lib/channel/status_util.h',
+                              'src/core/lib/compression/algorithm_metadata.h',
+                              'src/core/lib/compression/compression_internal.h',
+                              'src/core/lib/compression/message_compress.h',
+                              'src/core/lib/compression/stream_compression.h',
+                              'src/core/lib/compression/stream_compression_gzip.h',
+                              'src/core/lib/compression/stream_compression_identity.h',
+                              'src/core/lib/debug/stats.h',
+                              'src/core/lib/debug/stats_data.h',
+                              'src/core/lib/gprpp/debug_location.h',
+                              'src/core/lib/gprpp/inlined_vector.h',
+                              'src/core/lib/gprpp/orphanable.h',
+                              'src/core/lib/gprpp/ref_counted.h',
+                              'src/core/lib/gprpp/ref_counted_ptr.h',
+                              'src/core/lib/http/format_request.h',
+                              'src/core/lib/http/httpcli.h',
+                              'src/core/lib/http/parser.h',
+                              'src/core/lib/iomgr/block_annotate.h',
+                              'src/core/lib/iomgr/call_combiner.h',
+                              'src/core/lib/iomgr/closure.h',
+                              'src/core/lib/iomgr/combiner.h',
+                              'src/core/lib/iomgr/endpoint.h',
+                              'src/core/lib/iomgr/endpoint_pair.h',
+                              'src/core/lib/iomgr/error.h',
+                              'src/core/lib/iomgr/error_internal.h',
+                              'src/core/lib/iomgr/ev_epoll1_linux.h',
+                              'src/core/lib/iomgr/ev_epollex_linux.h',
+                              'src/core/lib/iomgr/ev_epollsig_linux.h',
+                              'src/core/lib/iomgr/ev_poll_posix.h',
+                              'src/core/lib/iomgr/ev_posix.h',
+                              'src/core/lib/iomgr/exec_ctx.h',
+                              'src/core/lib/iomgr/executor.h',
+                              'src/core/lib/iomgr/gethostname.h',
+                              'src/core/lib/iomgr/iocp_windows.h',
+                              'src/core/lib/iomgr/iomgr.h',
+                              'src/core/lib/iomgr/iomgr_custom.h',
+                              'src/core/lib/iomgr/iomgr_internal.h',
+                              'src/core/lib/iomgr/iomgr_posix.h',
+                              'src/core/lib/iomgr/is_epollexclusive_available.h',
+                              'src/core/lib/iomgr/load_file.h',
+                              'src/core/lib/iomgr/lockfree_event.h',
+                              'src/core/lib/iomgr/nameser.h',
+                              'src/core/lib/iomgr/network_status_tracker.h',
+                              'src/core/lib/iomgr/polling_entity.h',
+                              'src/core/lib/iomgr/pollset.h',
+                              'src/core/lib/iomgr/pollset_custom.h',
+                              'src/core/lib/iomgr/pollset_set.h',
+                              'src/core/lib/iomgr/pollset_set_custom.h',
+                              'src/core/lib/iomgr/pollset_set_windows.h',
+                              'src/core/lib/iomgr/pollset_windows.h',
+                              'src/core/lib/iomgr/port.h',
+                              'src/core/lib/iomgr/resolve_address.h',
+                              'src/core/lib/iomgr/resolve_address_custom.h',
+                              'src/core/lib/iomgr/resource_quota.h',
+                              'src/core/lib/iomgr/sockaddr.h',
+                              'src/core/lib/iomgr/sockaddr_custom.h',
+                              'src/core/lib/iomgr/sockaddr_posix.h',
+                              'src/core/lib/iomgr/sockaddr_utils.h',
+                              'src/core/lib/iomgr/sockaddr_windows.h',
+                              'src/core/lib/iomgr/socket_factory_posix.h',
+                              'src/core/lib/iomgr/socket_mutator.h',
+                              'src/core/lib/iomgr/socket_utils.h',
+                              'src/core/lib/iomgr/socket_utils_posix.h',
+                              'src/core/lib/iomgr/socket_windows.h',
+                              'src/core/lib/iomgr/sys_epoll_wrapper.h',
+                              'src/core/lib/iomgr/tcp_client.h',
+                              'src/core/lib/iomgr/tcp_client_posix.h',
+                              'src/core/lib/iomgr/tcp_custom.h',
+                              'src/core/lib/iomgr/tcp_posix.h',
+                              'src/core/lib/iomgr/tcp_server.h',
+                              'src/core/lib/iomgr/tcp_server_utils_posix.h',
+                              'src/core/lib/iomgr/tcp_windows.h',
+                              'src/core/lib/iomgr/time_averaged_stats.h',
+                              'src/core/lib/iomgr/timer.h',
+                              'src/core/lib/iomgr/timer_custom.h',
+                              'src/core/lib/iomgr/timer_heap.h',
+                              'src/core/lib/iomgr/timer_manager.h',
+                              'src/core/lib/iomgr/udp_server.h',
+                              'src/core/lib/iomgr/unix_sockets_posix.h',
+                              'src/core/lib/iomgr/wakeup_fd_cv.h',
+                              'src/core/lib/iomgr/wakeup_fd_pipe.h',
+                              'src/core/lib/iomgr/wakeup_fd_posix.h',
+                              'src/core/lib/json/json.h',
+                              'src/core/lib/json/json_common.h',
+                              'src/core/lib/json/json_reader.h',
+                              'src/core/lib/json/json_writer.h',
+                              'src/core/lib/slice/b64.h',
+                              'src/core/lib/slice/percent_encoding.h',
+                              'src/core/lib/slice/slice_hash_table.h',
+                              'src/core/lib/slice/slice_internal.h',
+                              'src/core/lib/slice/slice_string_helpers.h',
+                              'src/core/lib/slice/slice_weak_hash_table.h',
+                              'src/core/lib/surface/api_trace.h',
+                              'src/core/lib/surface/call.h',
+                              'src/core/lib/surface/call_test_only.h',
+                              'src/core/lib/surface/channel.h',
+                              'src/core/lib/surface/channel_init.h',
+                              'src/core/lib/surface/channel_stack_type.h',
+                              'src/core/lib/surface/completion_queue.h',
+                              'src/core/lib/surface/completion_queue_factory.h',
+                              'src/core/lib/surface/event_string.h',
+                              'src/core/lib/surface/init.h',
+                              'src/core/lib/surface/lame_client.h',
+                              'src/core/lib/surface/server.h',
+                              'src/core/lib/surface/validate_metadata.h',
+                              'src/core/lib/transport/bdp_estimator.h',
+                              'src/core/lib/transport/byte_stream.h',
+                              'src/core/lib/transport/connectivity_state.h',
+                              'src/core/lib/transport/error_utils.h',
+                              'src/core/lib/transport/http2_errors.h',
+                              'src/core/lib/transport/metadata.h',
+                              'src/core/lib/transport/metadata_batch.h',
+                              'src/core/lib/transport/pid_controller.h',
+                              'src/core/lib/transport/service_config.h',
+                              'src/core/lib/transport/static_metadata.h',
+                              'src/core/lib/transport/status_conversion.h',
+                              'src/core/lib/transport/status_metadata.h',
+                              'src/core/lib/transport/timeout_encoding.h',
+                              'src/core/lib/transport/transport.h',
+                              'src/core/lib/transport/transport_impl.h',
+                              'src/core/lib/debug/trace.h',
+                              'src/core/ext/filters/deadline/deadline_filter.h',
+                              'src/core/ext/filters/message_size/message_size_filter.h',
+                              'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
+                              'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
+                              'src/core/ext/transport/cronet/transport/cronet_transport.h',
+                              'third_party/objective_c/Cronet/bidirectional_stream_c.h',
+                              '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',
+                              'src/core/ext/transport/chttp2/transport/frame_ping.h',
+                              'src/core/ext/transport/chttp2/transport/frame_rst_stream.h',
+                              'src/core/ext/transport/chttp2/transport/frame_settings.h',
+                              'src/core/ext/transport/chttp2/transport/frame_window_update.h',
+                              'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
+                              'src/core/ext/transport/chttp2/transport/hpack_parser.h',
+                              'src/core/ext/transport/chttp2/transport/hpack_table.h',
+                              'src/core/ext/transport/chttp2/transport/http2_settings.h',
+                              'src/core/ext/transport/chttp2/transport/huffsyms.h',
+                              'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
+                              'src/core/ext/transport/chttp2/transport/internal.h',
+                              'src/core/ext/transport/chttp2/transport/stream_map.h',
+                              'src/core/ext/transport/chttp2/transport/varint.h',
+                              'src/core/ext/transport/chttp2/alpn/alpn.h',
+                              'src/core/ext/filters/http/client/http_client_filter.h',
+                              'src/core/ext/filters/http/message_compress/message_compress_filter.h',
+                              'src/core/ext/filters/http/server/http_server_filter.h',
+                              'src/core/ext/filters/client_channel/backup_poller.h',
+                              'src/core/ext/filters/client_channel/client_channel.h',
+                              'src/core/ext/filters/client_channel/client_channel_factory.h',
+                              'src/core/ext/filters/client_channel/connector.h',
+                              'src/core/ext/filters/client_channel/http_connect_handshaker.h',
+                              'src/core/ext/filters/client_channel/http_proxy.h',
+                              'src/core/ext/filters/client_channel/lb_policy.h',
+                              'src/core/ext/filters/client_channel/lb_policy_factory.h',
+                              'src/core/ext/filters/client_channel/lb_policy_registry.h',
+                              'src/core/ext/filters/client_channel/method_params.h',
+                              'src/core/ext/filters/client_channel/parse_address.h',
+                              'src/core/ext/filters/client_channel/proxy_mapper.h',
+                              'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
+                              'src/core/ext/filters/client_channel/resolver.h',
+                              'src/core/ext/filters/client_channel/resolver_factory.h',
+                              'src/core/ext/filters/client_channel/resolver_registry.h',
+                              'src/core/ext/filters/client_channel/retry_throttle.h',
+                              'src/core/ext/filters/client_channel/subchannel.h',
+                              'src/core/ext/filters/client_channel/subchannel_index.h',
+                              'src/core/ext/filters/client_channel/uri_parser.h',
+                              'src/core/lib/security/context/security_context.h',
+                              'src/core/lib/security/credentials/alts/alts_credentials.h',
+                              'src/core/lib/security/credentials/composite/composite_credentials.h',
+                              'src/core/lib/security/credentials/credentials.h',
+                              'src/core/lib/security/credentials/fake/fake_credentials.h',
+                              'src/core/lib/security/credentials/google_default/google_default_credentials.h',
+                              'src/core/lib/security/credentials/iam/iam_credentials.h',
+                              'src/core/lib/security/credentials/jwt/json_token.h',
+                              'src/core/lib/security/credentials/jwt/jwt_credentials.h',
+                              'src/core/lib/security/credentials/jwt/jwt_verifier.h',
+                              'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
+                              'src/core/lib/security/credentials/plugin/plugin_credentials.h',
+                              'src/core/lib/security/credentials/ssl/ssl_credentials.h',
+                              'src/core/lib/security/security_connector/alts_security_connector.h',
+                              'src/core/lib/security/security_connector/security_connector.h',
+                              'src/core/lib/security/transport/auth_filters.h',
+                              'src/core/lib/security/transport/secure_endpoint.h',
+                              'src/core/lib/security/transport/security_handshaker.h',
+                              'src/core/lib/security/transport/target_authority_table.h',
+                              'src/core/lib/security/transport/tsi_error.h',
+                              'src/core/lib/security/util/json_util.h',
+                              'src/core/tsi/alts/crypt/gsec.h',
+                              'src/core/tsi/alts/frame_protector/alts_counter.h',
+                              'src/core/tsi/alts/frame_protector/alts_crypter.h',
+                              'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
+                              'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
+                              'src/core/tsi/alts/frame_protector/frame_handler.h',
+                              'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
+                              'src/core/tsi/alts/handshaker/alts_tsi_event.h',
+                              'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
+                              'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
+                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
+                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
+                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
+                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
+                              'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
+                              'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
+                              'src/core/lib/security/credentials/alts/check_gcp_environment.h',
+                              'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
+                              'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
+                              'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
+                              'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
+                              'src/core/tsi/alts/handshaker/transport_security_common_api.h',
+                              'src/core/tsi/alts/handshaker/altscontext.pb.h',
+                              'src/core/tsi/alts/handshaker/handshaker.pb.h',
+                              'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
+                              'third_party/nanopb/pb.h',
+                              'third_party/nanopb/pb_common.h',
+                              'third_party/nanopb/pb_decode.h',
+                              'third_party/nanopb/pb_encode.h',
+                              'src/core/tsi/transport_security.h',
+                              'src/core/tsi/transport_security_adapter.h',
+                              'src/core/tsi/transport_security_interface.h',
+                              'src/core/ext/transport/chttp2/client/chttp2_connector.h',
+                              'src/core/tsi/alts_transport_security.h',
+                              'src/core/tsi/fake_transport_security.h',
+                              'src/core/tsi/ssl/session_cache/ssl_session.h',
+                              'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
+                              'src/core/tsi/ssl_transport_security.h',
+                              'src/core/tsi/ssl_types.h',
+                              'src/core/tsi/transport_security_grpc.h',
+                              'src/core/ext/transport/chttp2/server/chttp2_server.h'
   end
 
-  s.subspec 'Tests' do |ss|
+  s.subspec 'Cronet-Tests' do |ss|
     ss.header_mappings_dir = '.'
 
-    ss.dependency "#{s.name}/Interface", version
-    ss.dependency "#{s.name}/Implementation", version
+    ss.dependency "#{s.name}/Cronet-Interface", version
+    ss.dependency "#{s.name}/Cronet-Implementation", version
 
     ss.source_files = 'test/core/util/test_config.cc',
                       'test/core/util/test_config.h',
diff --git a/grpc.def b/grpc.def
index 5ff3a1e..d64629f 100644
--- a/grpc.def
+++ b/grpc.def
@@ -85,6 +85,9 @@
     grpc_auth_context_add_property
     grpc_auth_context_add_cstring_property
     grpc_auth_context_set_peer_identity_property_name
+    grpc_ssl_session_cache_create_lru
+    grpc_ssl_session_cache_destroy
+    grpc_ssl_session_cache_create_channel_arg
     grpc_channel_credentials_release
     grpc_google_default_credentials_create
     grpc_set_ssl_roots_override_callback
diff --git a/grpc.gemspec b/grpc.gemspec
index 3b07dd6..6562f36 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -273,6 +273,8 @@
   s.files += %w( src/core/ext/filters/deadline/deadline_filter.h )
   s.files += %w( src/core/tsi/alts_transport_security.h )
   s.files += %w( src/core/tsi/fake_transport_security.h )
+  s.files += %w( src/core/tsi/ssl/session_cache/ssl_session.h )
+  s.files += %w( src/core/tsi/ssl/session_cache/ssl_session_cache.h )
   s.files += %w( src/core/tsi/ssl_transport_security.h )
   s.files += %w( src/core/tsi/ssl_types.h )
   s.files += %w( src/core/tsi/transport_security_grpc.h )
@@ -693,6 +695,9 @@
   s.files += %w( src/core/ext/filters/deadline/deadline_filter.cc )
   s.files += %w( src/core/tsi/alts_transport_security.cc )
   s.files += %w( src/core/tsi/fake_transport_security.cc )
+  s.files += %w( src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc )
+  s.files += %w( src/core/tsi/ssl/session_cache/ssl_session_cache.cc )
+  s.files += %w( src/core/tsi/ssl/session_cache/ssl_session_openssl.cc )
   s.files += %w( src/core/tsi/ssl_transport_security.cc )
   s.files += %w( src/core/tsi/transport_security_grpc.cc )
   s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.cc )
diff --git a/grpc.gyp b/grpc.gyp
index fc9a45d..957bb06 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -498,6 +498,9 @@
         'src/core/ext/filters/deadline/deadline_filter.cc',
         'src/core/tsi/alts_transport_security.cc',
         'src/core/tsi/fake_transport_security.cc',
+        'src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc',
+        'src/core/tsi/ssl/session_cache/ssl_session_cache.cc',
+        'src/core/tsi/ssl/session_cache/ssl_session_openssl.cc',
         'src/core/tsi/ssl_transport_security.cc',
         'src/core/tsi/transport_security_grpc.cc',
         'src/core/ext/transport/chttp2/server/chttp2_server.cc',
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index abc591f..7c069b3 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -100,6 +100,25 @@
 GRPCAPI int grpc_auth_context_set_peer_identity_property_name(
     grpc_auth_context* ctx, const char* name);
 
+/** --- SSL Session Cache. ---
+
+    A SSL session cache object represents a way to cache client sessions
+    between connections. Only ticket-based resumption is supported. */
+
+typedef struct grpc_ssl_session_cache grpc_ssl_session_cache;
+
+/** Create LRU cache for client-side SSL sessions with the given capacity.
+    If capacity is < 1, a default capacity is used instead. */
+GRPCAPI grpc_ssl_session_cache* grpc_ssl_session_cache_create_lru(
+    size_t capacity);
+
+/** Destroy SSL session cache. */
+GRPCAPI void grpc_ssl_session_cache_destroy(grpc_ssl_session_cache* cache);
+
+/** Create a channel arg with the given cache object. */
+GRPCAPI grpc_arg
+grpc_ssl_session_cache_create_channel_arg(grpc_ssl_session_cache* cache);
+
 /** --- grpc_channel_credentials object. ---
 
    A channel credentials object represents a way to authenticate a client on a
diff --git a/include/grpc/grpc_security_constants.h b/include/grpc/grpc_security_constants.h
index 60e167e..92580ea 100644
--- a/include/grpc/grpc_security_constants.h
+++ b/include/grpc/grpc_security_constants.h
@@ -29,6 +29,7 @@
 #define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
 #define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
 #define GRPC_X509_PEM_CERT_PROPERTY_NAME "x509_pem_cert"
+#define GRPC_SSL_SESSION_REUSED_PROPERTY "ssl_session_reused"
 
 /** Environment variable that points to the default SSL roots file. This file
    must be a PEM encoded file with all the roots such as the one that can be
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index b671ad6..03aaa9f 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -258,6 +258,10 @@
     secure channel is an SSL channel). If this parameter is specified and the
     underlying is not an SSL channel, it will just be ignored. */
 #define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG "grpc.ssl_target_name_override"
+/** If non-zero, a pointer to a session cache (a pointer of type
+    grpc_ssl_session_cache*). (use grpc_ssl_session_cache_arg_vtable() to fetch
+    an appropriate pointer arg vtable) */
+#define GRPC_SSL_SESSION_CACHE_ARG "grpc.ssl_session_cache"
 /** Maximum metadata size, in bytes. Note this limit applies to the max sum of
     all metadata key-value entries in a batch of headers. */
 #define GRPC_ARG_MAX_METADATA_SIZE "grpc.max_metadata_size"
diff --git a/include/grpcpp/impl/codegen/async_unary_call.h b/include/grpcpp/impl/codegen/async_unary_call.h
index 255f874..60ff8e2 100644
--- a/include/grpcpp/impl/codegen/async_unary_call.h
+++ b/include/grpcpp/impl/codegen/async_unary_call.h
@@ -126,9 +126,10 @@
     assert(started_);
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
-    meta_buf.set_output_tag(tag);
-    meta_buf.RecvInitialMetadata(context_);
-    call_.PerformOps(&meta_buf);
+    single_buf.set_output_tag(tag);
+    single_buf.RecvInitialMetadata(context_);
+    call_.PerformOps(&single_buf);
+    initial_metadata_read_ = true;
   }
 
   /// See \a ClientAysncResponseReaderInterface::Finish for semantics.
@@ -138,14 +139,20 @@
   ///     possible initial and trailing metadata sent from the server.
   void Finish(R* msg, Status* status, void* tag) override {
     assert(started_);
-    finish_buf.set_output_tag(tag);
-    if (!context_->initial_metadata_received_) {
-      finish_buf.RecvInitialMetadata(context_);
+    if (initial_metadata_read_) {
+      finish_buf.set_output_tag(tag);
+      finish_buf.RecvMessage(msg);
+      finish_buf.AllowNoMessage();
+      finish_buf.ClientRecvStatus(context_, status);
+      call_.PerformOps(&finish_buf);
+    } else {
+      single_buf.set_output_tag(tag);
+      single_buf.RecvInitialMetadata(context_);
+      single_buf.RecvMessage(msg);
+      single_buf.AllowNoMessage();
+      single_buf.ClientRecvStatus(context_, status);
+      call_.PerformOps(&single_buf);
     }
-    finish_buf.RecvMessage(msg);
-    finish_buf.AllowNoMessage();
-    finish_buf.ClientRecvStatus(context_, status);
-    call_.PerformOps(&finish_buf);
   }
 
  private:
@@ -153,6 +160,7 @@
   ClientContext* const context_;
   ::grpc::internal::Call call_;
   bool started_;
+  bool initial_metadata_read_ = false;
 
   template <class W>
   ClientAsyncResponseReader(::grpc::internal::Call call, ClientContext* context,
@@ -160,30 +168,29 @@
       : context_(context), call_(call), started_(start) {
     // Bind the metadata at time of StartCallInternal but set up the rest here
     // TODO(ctiller): don't assert
-    GPR_CODEGEN_ASSERT(init_buf.SendMessage(request).ok());
-    init_buf.ClientSendClose();
+    GPR_CODEGEN_ASSERT(single_buf.SendMessage(request).ok());
+    single_buf.ClientSendClose();
     if (start) StartCallInternal();
   }
 
   void StartCallInternal() {
-    init_buf.SendInitialMetadata(context_->send_initial_metadata_,
-                                 context_->initial_metadata_flags());
-    call_.PerformOps(&init_buf);
+    single_buf.SendInitialMetadata(context_->send_initial_metadata_,
+                                   context_->initial_metadata_flags());
   }
 
   // disable operator new
   static void* operator new(std::size_t size);
   static void* operator new(std::size_t size, void* p) { return p; }
 
-  ::grpc::internal::SneakyCallOpSet<::grpc::internal::CallOpSendInitialMetadata,
-                                    ::grpc::internal::CallOpSendMessage,
-                                    ::grpc::internal::CallOpClientSendClose>
-      init_buf;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
-      meta_buf;
-  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpClientSendClose,
+                              ::grpc::internal::CallOpRecvInitialMetadata,
                               ::grpc::internal::CallOpRecvMessage<R>,
                               ::grpc::internal::CallOpClientRecvStatus>
+      single_buf;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>,
+                              ::grpc::internal::CallOpClientRecvStatus>
       finish_buf;
 };
 
diff --git a/include/grpcpp/impl/codegen/call.h b/include/grpcpp/impl/codegen/call.h
index 3b0fd60..28cc4a9 100644
--- a/include/grpcpp/impl/codegen/call.h
+++ b/include/grpcpp/impl/codegen/call.h
@@ -656,21 +656,6 @@
   grpc_call* call_;
 };
 
-/// A CallOpSet that does not post completions to the completion queue.
-///
-/// Allows hiding some completions that the C core must generate from
-/// C++ users.
-template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>,
-          class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>,
-          class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>>
-class SneakyCallOpSet : public CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> {
- public:
-  bool FinalizeResult(void** tag, bool* status) override {
-    typedef CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> Base;
-    return Base::FinalizeResult(tag, status) && false;
-  }
-};
-
 /// Straightforward wrapping of the C call object
 class Call final {
  public:
diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h
index e88e796..81c3907 100644
--- a/include/grpcpp/server.h
+++ b/include/grpcpp/server.h
@@ -162,8 +162,8 @@
   friend class ServerInitializer;
 
   class SyncRequest;
-  class AsyncRequest;
-  class ShutdownRequest;
+  class UnimplementedAsyncRequest;
+  class UnimplementedAsyncResponse;
 
   /// SyncRequestThreadManager is an implementation of ThreadManager. This class
   /// is responsible for polling for incoming RPCs and calling the RPC handlers.
@@ -171,10 +171,6 @@
   /// interface)
   class SyncRequestThreadManager;
 
-  class UnimplementedAsyncRequestContext;
-  class UnimplementedAsyncRequest;
-  class UnimplementedAsyncResponse;
-
   /// Register a generic service. This call does not take ownership of the
   /// service. The service must exist for the lifetime of the Server instance.
   void RegisterAsyncGenericService(AsyncGenericService* service) override;
diff --git a/package.xml b/package.xml
index 0b3fc3a..892f9c2 100644
--- a/package.xml
+++ b/package.xml
@@ -280,6 +280,8 @@
     <file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/alts_transport_security.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/ssl/session_cache/ssl_session.h" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/ssl/session_cache/ssl_session_cache.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/ssl_types.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security_grpc.h" role="src" />
@@ -700,6 +702,9 @@
     <file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/alts_transport_security.cc" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/fake_transport_security.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/ssl/session_cache/ssl_session_cache.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/tsi/ssl/session_cache/ssl_session_openssl.cc" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.cc" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security_grpc.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.cc" role="src" />
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index bf3911e..67dd3a1 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -303,11 +303,16 @@
   chand->lb_policy->SetReresolutionClosureLocked(&args->closure);
 }
 
+// TODO(roth): The logic in this function is very hard to follow.  We
+// should refactor this so that it's easier to understand, perhaps as
+// part of changing the resolver API to more clearly differentiate
+// between transient failures and shutdown.
 static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
   channel_data* chand = static_cast<channel_data*>(arg);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p: got resolver result: error=%s", chand,
-            grpc_error_string(error));
+    gpr_log(GPR_DEBUG,
+            "chand=%p: got resolver result: resolver_result=%p error=%s", chand,
+            chand->resolver_result, grpc_error_string(error));
   }
   // Extract the following fields from the resolver result, if non-nullptr.
   bool lb_policy_updated = false;
@@ -423,8 +428,6 @@
         }
       }
     }
-    grpc_channel_args_destroy(chand->resolver_result);
-    chand->resolver_result = nullptr;
   }
   if (grpc_client_channel_trace.enabled()) {
     gpr_log(GPR_DEBUG,
@@ -497,6 +500,8 @@
                                    "Channel disconnected", &error, 1));
     GRPC_CLOSURE_LIST_SCHED(&chand->waiting_for_resolver_result_closures);
     GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "resolver");
+    grpc_channel_args_destroy(chand->resolver_result);
+    chand->resolver_result = nullptr;
   } else {  // Not shutting down.
     grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
     grpc_error* state_error =
@@ -515,11 +520,16 @@
         chand->exit_idle_when_lb_policy_arrives = false;
       }
       watch_lb_policy_locked(chand, chand->lb_policy.get(), state);
+    } else if (chand->resolver_result == nullptr) {
+      // Transient failure.
+      GRPC_CLOSURE_LIST_SCHED(&chand->waiting_for_resolver_result_closures);
     }
     if (!lb_policy_updated) {
       set_channel_connectivity_state_locked(
           chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
     }
+    grpc_channel_args_destroy(chand->resolver_result);
+    chand->resolver_result = nullptr;
     chand->resolver->NextLocked(&chand->resolver_result,
                                 &chand->on_resolver_result_changed);
     GRPC_ERROR_UNREF(state_error);
@@ -2753,7 +2763,45 @@
               chand, calld);
     }
     async_pick_done_locked(elem, GRPC_ERROR_REF(error));
-  } else if (chand->lb_policy != nullptr) {
+  } else if (chand->resolver == nullptr) {
+    // Shutting down.
+    if (grpc_client_channel_trace.enabled()) {
+      gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver disconnected", chand,
+              calld);
+    }
+    async_pick_done_locked(
+        elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
+  } else if (chand->lb_policy == nullptr) {
+    // Transient resolver failure.
+    // If call has wait_for_ready=true, try again; otherwise, fail.
+    uint32_t send_initial_metadata_flags =
+        calld->seen_send_initial_metadata
+            ? calld->send_initial_metadata_flags
+            : calld->pending_batches[0]
+                  .batch->payload->send_initial_metadata
+                  .send_initial_metadata_flags;
+    if (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) {
+      if (grpc_client_channel_trace.enabled()) {
+        gpr_log(GPR_DEBUG,
+                "chand=%p calld=%p: resolver returned but no LB policy; "
+                "wait_for_ready=true; trying again",
+                chand, calld);
+      }
+      pick_after_resolver_result_start_locked(elem);
+    } else {
+      if (grpc_client_channel_trace.enabled()) {
+        gpr_log(GPR_DEBUG,
+                "chand=%p calld=%p: resolver returned but no LB policy; "
+                "wait_for_ready=false; failing",
+                chand, calld);
+      }
+      async_pick_done_locked(
+          elem,
+          grpc_error_set_int(
+              GRPC_ERROR_CREATE_FROM_STATIC_STRING("Name resolution failure"),
+              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
+    }
+  } else {
     if (grpc_client_channel_trace.enabled()) {
       gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver returned, doing pick",
               chand, calld);
@@ -2767,30 +2815,6 @@
       async_pick_done_locked(elem, GRPC_ERROR_NONE);
     }
   }
-  // TODO(roth): It should be impossible for chand->lb_policy to be nullptr
-  // 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 != nullptr) {
-    // No LB policy, so try again.
-    if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
-              "chand=%p calld=%p: resolver returned but no LB policy, "
-              "trying again",
-              chand, calld);
-    }
-    pick_after_resolver_result_start_locked(elem);
-  } else {
-    if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver disconnected", chand,
-              calld);
-    }
-    async_pick_done_locked(
-        elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
-  }
 }
 
 static void pick_after_resolver_result_start_locked(grpc_call_element* elem) {
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 47e1dee..e805593 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
@@ -423,13 +423,13 @@
    * server->ip_address.bytes. */
   const grpc_grpclb_ip_address* ip = &server->ip_address;
   if (ip->size == 4) {
-    addr->len = sizeof(grpc_sockaddr_in);
+    addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
     grpc_sockaddr_in* addr4 = reinterpret_cast<grpc_sockaddr_in*>(&addr->addr);
     addr4->sin_family = GRPC_AF_INET;
     memcpy(&addr4->sin_addr, ip->bytes, ip->size);
     addr4->sin_port = netorder_port;
   } else if (ip->size == 16) {
-    addr->len = sizeof(grpc_sockaddr_in6);
+    addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
     grpc_sockaddr_in6* addr6 = (grpc_sockaddr_in6*)&addr->addr;
     addr6->sin6_family = GRPC_AF_INET6;
     memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
diff --git a/src/core/ext/filters/client_channel/lb_policy_factory.cc b/src/core/ext/filters/client_channel/lb_policy_factory.cc
index 80646a1..7c8cba5 100644
--- a/src/core/ext/filters/client_channel/lb_policy_factory.cc
+++ b/src/core/ext/filters/client_channel/lb_policy_factory.cc
@@ -66,7 +66,7 @@
   if (user_data != nullptr) GPR_ASSERT(addresses->user_data_vtable != nullptr);
   grpc_lb_address* target = &addresses->addresses[index];
   memcpy(target->address.addr, address, address_len);
-  target->address.len = address_len;
+  target->address.len = static_cast<socklen_t>(address_len);
   target->is_balancer = is_balancer;
   target->balancer_name = gpr_strdup(balancer_name);
   target->user_data = user_data;
diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc
index 92ea259..b390011 100644
--- a/src/core/ext/filters/client_channel/parse_address.cc
+++ b/src/core/ext/filters/client_channel/parse_address.cc
@@ -50,7 +50,7 @@
   if (path_len == maxlen) return false;
   un->sun_family = AF_UNIX;
   strcpy(un->sun_path, uri->path);
-  resolved_addr->len = sizeof(*un);
+  resolved_addr->len = static_cast<socklen_t>(sizeof(*un));
   return true;
 }
 
@@ -72,7 +72,7 @@
   if (!gpr_split_host_port(hostport, &host, &port)) return false;
   // Parse IP address.
   memset(addr, 0, sizeof(*addr));
-  addr->len = sizeof(grpc_sockaddr_in);
+  addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
   grpc_sockaddr_in* in = reinterpret_cast<grpc_sockaddr_in*>(addr->addr);
   in->sin_family = GRPC_AF_INET;
   if (grpc_inet_pton(GRPC_AF_INET, host, &in->sin_addr) == 0) {
@@ -118,7 +118,7 @@
   if (!gpr_split_host_port(hostport, &host, &port)) return false;
   // Parse IP address.
   memset(addr, 0, sizeof(*addr));
-  addr->len = sizeof(grpc_sockaddr_in6);
+  addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
   grpc_sockaddr_in6* in6 = reinterpret_cast<grpc_sockaddr_in6*>(addr->addr);
   in6->sin6_family = GRPC_AF_INET6;
   // Handle the RFC6874 syntax for IPv6 zone identifiers.
diff --git a/src/core/ext/filters/client_channel/resolver.h b/src/core/ext/filters/client_channel/resolver.h
index 1685a6c..cdb5a20 100644
--- a/src/core/ext/filters/client_channel/resolver.h
+++ b/src/core/ext/filters/client_channel/resolver.h
@@ -53,8 +53,12 @@
   /// Requests a callback when a new result becomes available.
   /// When the new result is available, sets \a *result to the new result
   /// and schedules \a on_complete for execution.
+  /// Upon transient failure, sets \a *result to nullptr and schedules
+  /// \a on_complete with no error.
   /// If resolution is fatally broken, sets \a *result to nullptr and
   /// schedules \a on_complete with an error.
+  /// TODO(roth): When we have time, improve the way this API represents
+  /// transient failure vs. shutdown.
   ///
   /// Note that the client channel will almost always have a request
   /// to \a NextLocked() pending.  When it gets the callback, it will
diff --git a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
index 4d8958f..99a33f2 100644
--- a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
+++ b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
@@ -82,6 +82,8 @@
   grpc_closure* next_completion_ = nullptr;
   // target result address for next completion
   grpc_channel_args** target_result_ = nullptr;
+  // if true, return failure
+  bool return_failure_ = false;
 };
 
 FakeResolver::FakeResolver(const ResolverArgs& args) : Resolver(args.combiner) {
@@ -121,12 +123,16 @@
 }
 
 void FakeResolver::MaybeFinishNextLocked() {
-  if (next_completion_ != nullptr && next_results_ != nullptr) {
-    *target_result_ = grpc_channel_args_union(next_results_, channel_args_);
+  if (next_completion_ != nullptr &&
+      (next_results_ != nullptr || return_failure_)) {
+    *target_result_ =
+        return_failure_ ? nullptr
+                        : grpc_channel_args_union(next_results_, channel_args_);
     grpc_channel_args_destroy(next_results_);
     next_results_ = nullptr;
     GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
     next_completion_ = nullptr;
+    return_failure_ = false;
   }
 }
 
@@ -197,6 +203,26 @@
       GRPC_ERROR_NONE);
 }
 
+void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
+                                                     grpc_error* error) {
+  SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
+  FakeResolver* resolver = closure_arg->generator->resolver_;
+  resolver->return_failure_ = true;
+  resolver->MaybeFinishNextLocked();
+  Delete(closure_arg);
+}
+
+void FakeResolverResponseGenerator::SetFailure() {
+  GPR_ASSERT(resolver_ != nullptr);
+  SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
+  closure_arg->generator = this;
+  GRPC_CLOSURE_SCHED(
+      GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
+                        closure_arg,
+                        grpc_combiner_scheduler(resolver_->combiner())),
+      GRPC_ERROR_NONE);
+}
+
 namespace {
 
 static void* response_generator_arg_copy(void* p) {
diff --git a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
index 858f358..e5175f9 100644
--- a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
+++ b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
@@ -56,6 +56,10 @@
   // resolver will return the last value set via \a SetResponse().
   void SetReresolutionResponse(grpc_channel_args* response);
 
+  // Tells the resolver to return a transient failure (signalled by
+  // returning a null result with no error).
+  void SetFailure();
+
   // Returns a channel arg containing \a generator.
   static grpc_arg MakeChannelArg(FakeResolverResponseGenerator* generator);
 
@@ -68,6 +72,7 @@
 
   static void SetResponseLocked(void* arg, grpc_error* error);
   static void SetReresolutionResponseLocked(void* arg, grpc_error* error);
+  static void SetFailureLocked(void* arg, grpc_error* error);
 
   FakeResolver* resolver_ = nullptr;  // Do not own.
 };
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index a4d616d..ab69cec 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -68,7 +68,7 @@
 
 #define DEFAULT_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */
 #define DEFAULT_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */
-#define DEFAULT_MAX_PINGS_BETWEEN_DATA 0                      /* unlimited */
+#define DEFAULT_MAX_PINGS_BETWEEN_DATA 2
 #define DEFAULT_MAX_PING_STRIKES 2
 
 static int g_default_client_keepalive_time_ms =
@@ -2630,7 +2630,7 @@
   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(arg);
   GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
   grpc_timer_init(&t->keepalive_watchdog_timer,
-                  grpc_core::ExecCtx::Get()->Now() + t->keepalive_time,
+                  grpc_core::ExecCtx::Get()->Now() + t->keepalive_timeout,
                   &t->keepalive_watchdog_fired_locked);
 }
 
diff --git a/src/core/ext/transport/chttp2/transport/parsing.cc b/src/core/ext/transport/chttp2/transport/parsing.cc
index 988380b..a10c9ad 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.cc
+++ b/src/core/ext/transport/chttp2/transport/parsing.cc
@@ -373,8 +373,6 @@
     /* t->parser = grpc_chttp2_data_parser_parse;*/
     t->parser = grpc_chttp2_data_parser_parse;
     t->parser_data = &s->data_parser;
-    t->ping_state.pings_before_data_required =
-        t->ping_policy.max_pings_without_data;
     t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST;
     return GRPC_ERROR_NONE;
   } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, nullptr)) {
@@ -547,8 +545,6 @@
         (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
   }
 
-  t->ping_state.pings_before_data_required =
-      t->ping_policy.max_pings_without_data;
   t->ping_state.last_ping_sent_time = GRPC_MILLIS_INF_PAST;
 
   /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc
index 7471d88..6f32397 100644
--- a/src/core/ext/transport/chttp2/transport/writing.cc
+++ b/src/core/ext/transport/chttp2/transport/writing.cc
@@ -224,7 +224,7 @@
       grpc_slice_buffer_add(
           &t_->outbuf, grpc_chttp2_window_update_create(0, transport_announce,
                                                         &throwaway_stats));
-      ResetPingRecvClock();
+      ResetPingClock();
     }
   }
 
@@ -269,11 +269,13 @@
     return s;
   }
 
-  void ResetPingRecvClock() {
+  void ResetPingClock() {
     if (!t_->is_client) {
       t_->ping_recv_state.last_ping_recv_time = GRPC_MILLIS_INF_PAST;
       t_->ping_recv_state.ping_strikes = 0;
     }
+    t_->ping_state.pings_before_data_required =
+        t_->ping_policy.max_pings_without_data;
   }
 
   void IncInitialMetadataWrites() { ++initial_metadata_writes_; }
@@ -435,7 +437,7 @@
       };
       grpc_chttp2_encode_header(&t_->hpack_compressor, nullptr, 0,
                                 s_->send_initial_metadata, &hopt, &t_->outbuf);
-      write_context_->ResetPingRecvClock();
+      write_context_->ResetPingClock();
       write_context_->IncInitialMetadataWrites();
     }
 
@@ -455,7 +457,7 @@
     grpc_slice_buffer_add(
         &t_->outbuf, grpc_chttp2_window_update_create(s_->id, stream_announce,
                                                       &s_->stats.outgoing));
-    write_context_->ResetPingRecvClock();
+    write_context_->ResetPingClock();
     write_context_->IncWindowUpdateWrites();
   }
 
@@ -489,7 +491,7 @@
         data_send_context.CompressMoreBytes();
       }
     }
-    write_context_->ResetPingRecvClock();
+    write_context_->ResetPingClock();
     if (data_send_context.is_last_frame()) {
       SentLastFrame();
     }
@@ -530,7 +532,7 @@
                                 s_->send_trailing_metadata, &hopt, &t_->outbuf);
     }
     write_context_->IncTrailingMetadataWrites();
-    write_context_->ResetPingRecvClock();
+    write_context_->ResetPingClock();
     SentLastFrame();
 
     write_context_->NoteScheduledResults();
diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc
index 67d5fd3..654300c 100644
--- a/src/core/lib/channel/channel_trace.cc
+++ b/src/core/lib/channel/channel_trace.cc
@@ -24,6 +24,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
diff --git a/src/core/lib/http/httpcli_security_connector.cc b/src/core/lib/http/httpcli_security_connector.cc
index 1809123..886357f 100644
--- a/src/core/lib/http/httpcli_security_connector.cc
+++ b/src/core/lib/http/httpcli_security_connector.cc
@@ -121,8 +121,11 @@
   if (secure_peer_name != nullptr) {
     c->secure_peer_name = gpr_strdup(secure_peer_name);
   }
-  result = tsi_create_ssl_client_handshaker_factory(
-      nullptr, pem_root_certs, nullptr, nullptr, 0, &c->handshaker_factory);
+  tsi_ssl_client_handshaker_options options;
+  memset(&options, 0, sizeof(options));
+  options.pem_root_certs = pem_root_certs;
+  result = tsi_create_ssl_client_handshaker_factory_with_options(
+      &options, &c->handshaker_factory);
   if (result != TSI_OK) {
     gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
             tsi_result_to_string(result));
diff --git a/src/core/lib/iomgr/resolve_address.h b/src/core/lib/iomgr/resolve_address.h
index 68cdefc..fe0d834 100644
--- a/src/core/lib/iomgr/resolve_address.h
+++ b/src/core/lib/iomgr/resolve_address.h
@@ -22,13 +22,28 @@
 #include <grpc/support/port_platform.h>
 
 #include <stddef.h>
+
+#include "src/core/lib/iomgr/port.h"
+
+#ifdef GRPC_UV
+#include <uv.h>
+#endif
+
+#ifdef GRPC_WINSOCK_SOCKET
+#include <ws2tcpip.h>
+#endif
+
+#ifdef GRPC_POSIX_SOCKET
+#include <sys/socket.h>
+#endif
+
 #include "src/core/lib/iomgr/pollset_set.h"
 
 #define GRPC_MAX_SOCKADDR_SIZE 128
 
 typedef struct {
   char addr[GRPC_MAX_SOCKADDR_SIZE];
-  size_t len;
+  socklen_t len;
 } grpc_resolved_address;
 
 typedef struct {
diff --git a/src/core/lib/iomgr/sockaddr_utils.cc b/src/core/lib/iomgr/sockaddr_utils.cc
index bc3550a..df25f77 100644
--- a/src/core/lib/iomgr/sockaddr_utils.cc
+++ b/src/core/lib/iomgr/sockaddr_utils.cc
@@ -58,7 +58,8 @@
         /* s6_addr32 would be nice, but it's non-standard. */
         memcpy(&addr4_out->sin_addr, &addr6->sin6_addr.s6_addr[12], 4);
         addr4_out->sin_port = addr6->sin6_port;
-        resolved_addr4_out->len = sizeof(grpc_sockaddr_in);
+        resolved_addr4_out->len =
+            static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
       }
       return 1;
     }
@@ -81,7 +82,7 @@
     memcpy(&addr6_out->sin6_addr.s6_addr[0], kV4MappedPrefix, 12);
     memcpy(&addr6_out->sin6_addr.s6_addr[12], &addr4->sin_addr, 4);
     addr6_out->sin6_port = addr4->sin_port;
-    resolved_addr6_out->len = sizeof(grpc_sockaddr_in6);
+    resolved_addr6_out->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
     return 1;
   }
   return 0;
@@ -135,7 +136,7 @@
   memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
   wild_out->sin_family = GRPC_AF_INET;
   wild_out->sin_port = grpc_htons(static_cast<uint16_t>(port));
-  resolved_wild_out->len = sizeof(grpc_sockaddr_in);
+  resolved_wild_out->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
 }
 
 void grpc_sockaddr_make_wildcard6(int port,
@@ -146,7 +147,7 @@
   memset(resolved_wild_out, 0, sizeof(*resolved_wild_out));
   wild_out->sin6_family = GRPC_AF_INET6;
   wild_out->sin6_port = grpc_htons(static_cast<uint16_t>(port));
-  resolved_wild_out->len = sizeof(grpc_sockaddr_in6);
+  resolved_wild_out->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
 }
 
 int grpc_sockaddr_to_string(char** out,
diff --git a/src/core/lib/iomgr/socket_utils_linux.cc b/src/core/lib/iomgr/socket_utils_linux.cc
index 1364cd3..f506329 100644
--- a/src/core/lib/iomgr/socket_utils_linux.cc
+++ b/src/core/lib/iomgr/socket_utils_linux.cc
@@ -38,7 +38,7 @@
   flags |= nonblock ? SOCK_NONBLOCK : 0;
   flags |= cloexec ? SOCK_CLOEXEC : 0;
   return accept4(sockfd, reinterpret_cast<grpc_sockaddr*>(resolved_addr->addr),
-                 reinterpret_cast<socklen_t*>(&resolved_addr->len), flags);
+                 &resolved_addr->len, flags);
 }
 
 #endif
diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc
index c21fb40..9f19b83 100644
--- a/src/core/lib/iomgr/tcp_client_posix.cc
+++ b/src/core/lib/iomgr/tcp_client_posix.cc
@@ -293,9 +293,8 @@
   int err;
   async_connect* ac;
   do {
-    GPR_ASSERT(addr->len < ~(socklen_t)0);
     err = connect(fd, reinterpret_cast<const grpc_sockaddr*>(addr->addr),
-                  static_cast<socklen_t>(addr->len));
+                  addr->len);
   } while (err < 0 && errno == EINTR);
   if (err >= 0) {
     char* addr_str = grpc_sockaddr_to_uri(addr);
diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc
index 1d9276a..4e1d90e 100644
--- a/src/core/lib/iomgr/tcp_server_posix.cc
+++ b/src/core/lib/iomgr/tcp_server_posix.cc
@@ -61,6 +61,11 @@
 static void init(void) {
 #ifndef GPR_MANYLINUX1
   int s = socket(AF_INET, SOCK_STREAM, 0);
+  if (s < 0) {
+    /* This might be an ipv6-only environment in which case 'socket(AF_INET,..)'
+       call would fail. Try creating IPv6 socket in that case */
+    s = socket(AF_INET6, SOCK_STREAM, 0);
+  }
   if (s >= 0) {
     has_so_reuseport = GRPC_LOG_IF_ERROR("check for SO_REUSEPORT",
                                          grpc_set_socket_reuse_port(s, 1));
@@ -214,7 +219,7 @@
     char* addr_str;
     char* name;
     memset(&addr, 0, sizeof(addr));
-    addr.len = sizeof(struct sockaddr_storage);
+    addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
     /* Note: If we ever decide to return this address to the user, remember to
        strip off the ::ffff:0.0.0.0/96 prefix first. */
     int fd = grpc_accept4(sp->fd, &addr, 1, 1);
@@ -413,11 +418,12 @@
      as some previously created listener. */
   if (requested_port == 0) {
     for (sp = s->head; sp; sp = sp->next) {
-      sockname_temp.len = sizeof(struct sockaddr_storage);
+      sockname_temp.len =
+          static_cast<socklen_t>(sizeof(struct sockaddr_storage));
       if (0 ==
           getsockname(sp->fd,
                       reinterpret_cast<grpc_sockaddr*>(&sockname_temp.addr),
-                      reinterpret_cast<socklen_t*>(&sockname_temp.len))) {
+                      &sockname_temp.len)) {
         int used_port = grpc_sockaddr_get_port(&sockname_temp);
         if (used_port > 0) {
           memcpy(&sockname_temp, addr, sizeof(grpc_resolved_address));
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
index 76d3d62..0734453 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
+++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
@@ -172,7 +172,7 @@
 
   GPR_ASSERT(addr->len < ~(socklen_t)0);
   if (bind(fd, reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr)),
-           static_cast<socklen_t>(addr->len)) < 0) {
+           addr->len) < 0) {
     err = GRPC_OS_ERROR(errno, "bind");
     goto error;
   }
@@ -182,10 +182,10 @@
     goto error;
   }
 
-  sockname_temp.len = sizeof(struct sockaddr_storage);
+  sockname_temp.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
 
   if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
-                  reinterpret_cast<socklen_t*>(&sockname_temp.len)) < 0) {
+                  &sockname_temp.len) < 0) {
     err = GRPC_OS_ERROR(errno, "getsockname");
     goto error;
   }
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc
index 29ff9ec..7fd86c5 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc
+++ b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc
@@ -68,14 +68,14 @@
   if (dsmode == GRPC_DSMODE_IPV4) {
     grpc_sockaddr_make_wildcard4(0, &wild);
   }
-  if (bind(fd, reinterpret_cast<const grpc_sockaddr*>(wild.addr),
-           static_cast<socklen_t>(wild.len)) != 0) {
+  if (bind(fd, reinterpret_cast<const grpc_sockaddr*>(wild.addr), wild.len) !=
+      0) {
     err = GRPC_OS_ERROR(errno, "bind");
     close(fd);
     return err;
   }
-  if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(wild.addr),
-                  reinterpret_cast<socklen_t*>(&wild.len)) != 0) {
+  if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(wild.addr), &wild.len) !=
+      0) {
     err = GRPC_OS_ERROR(errno, "getsockname");
     close(fd);
     return err;
@@ -119,9 +119,9 @@
     if (ifa_it->ifa_addr == nullptr) {
       continue;
     } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
-      addr.len = sizeof(grpc_sockaddr_in);
+      addr.len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
     } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
-      addr.len = sizeof(grpc_sockaddr_in6);
+      addr.len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
     } else {
       continue;
     }
diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc
index 15a242a..04716a2 100644
--- a/src/core/lib/iomgr/udp_server.cc
+++ b/src/core/lib/iomgr/udp_server.cc
@@ -347,7 +347,7 @@
              : bind(sockfd,
                     reinterpret_cast<grpc_sockaddr*>(
                         const_cast<char*>(addr->addr)),
-                    static_cast<socklen_t>(addr->len));
+                    addr->len);
 }
 
 /* Prepare a recently-created socket for listening. */
@@ -390,10 +390,10 @@
     goto error;
   }
 
-  sockname_temp.len = sizeof(struct sockaddr_storage);
+  sockname_temp.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
 
   if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
-                  reinterpret_cast<socklen_t*>(&sockname_temp.len)) < 0) {
+                  &sockname_temp.len) < 0) {
     goto error;
   }
 
@@ -575,10 +575,11 @@
      as some previously created listener. */
   if (grpc_sockaddr_get_port(addr) == 0) {
     for (size_t i = 0; i < s->listeners.size(); ++i) {
-      sockname_temp.len = sizeof(struct sockaddr_storage);
+      sockname_temp.len =
+          static_cast<socklen_t>(sizeof(struct sockaddr_storage));
       if (0 == getsockname(s->listeners[i].fd(),
                            reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
-                           reinterpret_cast<socklen_t*>(&sockname_temp.len))) {
+                           &sockname_temp.len)) {
         port = grpc_sockaddr_get_port(&sockname_temp);
         if (port > 0) {
           allocated_addr = static_cast<grpc_resolved_address*>(
diff --git a/src/core/lib/iomgr/unix_sockets_posix.cc b/src/core/lib/iomgr/unix_sockets_posix.cc
index 5d09b4a..22fcaf5 100644
--- a/src/core/lib/iomgr/unix_sockets_posix.cc
+++ b/src/core/lib/iomgr/unix_sockets_posix.cc
@@ -61,7 +61,8 @@
   un = reinterpret_cast<struct sockaddr_un*>((*addrs)->addrs->addr);
   un->sun_family = AF_UNIX;
   strncpy(un->sun_path, name, sizeof(un->sun_path));
-  (*addrs)->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
+  (*addrs)->addrs->len =
+      static_cast<socklen_t>(strlen(un->sun_path) + sizeof(un->sun_family) + 1);
   return GRPC_ERROR_NONE;
 }
 
diff --git a/src/core/lib/profiling/basic_timers.cc b/src/core/lib/profiling/basic_timers.cc
index 43384fd..652a498 100644
--- a/src/core/lib/profiling/basic_timers.cc
+++ b/src/core/lib/profiling/basic_timers.cc
@@ -26,11 +26,11 @@
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <string.h>
 
 #include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gprpp/thd.h"
 
 typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
 
@@ -68,7 +68,7 @@
 static gpr_timer_log_list g_in_progress_logs;
 static gpr_timer_log_list g_done_logs;
 static int g_shutdown;
-static grpc_core::Thread* g_writing_thread;
+static pthread_t g_writing_thread;
 static __thread int g_thread_id;
 static int g_next_thread_id;
 static int g_writing_enabled = 1;
@@ -149,7 +149,7 @@
   }
 }
 
-static void writing_thread(void* unused) {
+static void* writing_thread(void* unused) {
   gpr_timer_log* log;
   pthread_mutex_lock(&g_mu);
   for (;;) {
@@ -164,7 +164,7 @@
     }
     if (g_shutdown) {
       pthread_mutex_unlock(&g_mu);
-      return;
+      return NULL;
     }
   }
 }
@@ -182,8 +182,7 @@
   g_shutdown = 1;
   pthread_cond_signal(&g_cv);
   pthread_mutex_unlock(&g_mu);
-  g_writing_thread->Join();
-  grpc_core::Delete(g_writing_thread);
+  pthread_join(g_writing_thread, NULL);
 
   gpr_log(GPR_INFO, "flushing logs");
 
@@ -202,8 +201,12 @@
 }
 
 static void init_output() {
-  g_writing_thread = grpc_core::New<grpc_core::Thread>("timer_output_thread",
-                                                       writing_thread, nullptr);
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+  pthread_create(&g_writing_thread, &attr, &writing_thread, NULL);
+  pthread_attr_destroy(&attr);
+
   atexit(finish_writing);
 }
 
diff --git a/src/core/lib/profiling/timers.h b/src/core/lib/profiling/timers.h
index d0188b5..7ff7278 100644
--- a/src/core/lib/profiling/timers.h
+++ b/src/core/lib/profiling/timers.h
@@ -82,9 +82,12 @@
 };
 }  // namespace grpc
 
-#define GPR_TIMER_SCOPE(tag, important)                                        \
-  ::grpc::ProfileScope _profile_scope_##__LINE__((tag), (important), __FILE__, \
-                                                 __LINE__)
+#define GPR_TIMER_SCOPE_NAME_INTERNAL(prefix, line) prefix##line
+#define GPR_TIMER_SCOPE_NAME(prefix, line) \
+  GPR_TIMER_SCOPE_NAME_INTERNAL(prefix, line)
+#define GPR_TIMER_SCOPE(tag, important)                                 \
+  ::grpc::ProfileScope GPR_TIMER_SCOPE_NAME(_profile_scope_, __LINE__)( \
+      (tag), (important), __FILE__, __LINE__)
 
 #endif /* at least one profiler requested. */
 
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/src/core/lib/security/credentials/ssl/ssl_credentials.cc
index 252b25b..2b6377d 100644
--- a/src/core/lib/security/credentials/ssl/ssl_credentials.cc
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.cc
@@ -24,6 +24,7 @@
 
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/api_trace.h"
+#include "src/core/tsi/ssl_transport_security.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -56,16 +57,22 @@
   grpc_ssl_credentials* c = reinterpret_cast<grpc_ssl_credentials*>(creds);
   grpc_security_status status = GRPC_SECURITY_OK;
   const char* overridden_target_name = nullptr;
+  tsi_ssl_session_cache* ssl_session_cache = nullptr;
   for (size_t i = 0; args && i < args->num_args; i++) {
     grpc_arg* arg = &args->args[i];
     if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
         arg->type == GRPC_ARG_STRING) {
       overridden_target_name = arg->value.string;
-      break;
+    }
+    if (strcmp(arg->key, GRPC_SSL_SESSION_CACHE_ARG) == 0 &&
+        arg->type == GRPC_ARG_POINTER) {
+      ssl_session_cache =
+          static_cast<tsi_ssl_session_cache*>(arg->value.pointer.p);
     }
   }
   status = grpc_ssl_channel_security_connector_create(
-      creds, call_creds, &c->config, target, overridden_target_name, sc);
+      creds, call_creds, &c->config, target, overridden_target_name,
+      ssl_session_cache, sc);
   if (status != GRPC_SECURITY_OK) {
     return status;
   }
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index 3cc151b..cbe77d5 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -542,6 +542,46 @@
 
 /* --- Ssl implementation. --- */
 
+grpc_ssl_session_cache* grpc_ssl_session_cache_create_lru(size_t capacity) {
+  tsi_ssl_session_cache* cache = tsi_ssl_session_cache_create_lru(capacity);
+  return reinterpret_cast<grpc_ssl_session_cache*>(cache);
+}
+
+void grpc_ssl_session_cache_destroy(grpc_ssl_session_cache* cache) {
+  tsi_ssl_session_cache* tsi_cache =
+      reinterpret_cast<tsi_ssl_session_cache*>(cache);
+  tsi_ssl_session_cache_unref(tsi_cache);
+}
+
+static void* grpc_ssl_session_cache_arg_copy(void* p) {
+  tsi_ssl_session_cache* tsi_cache =
+      reinterpret_cast<tsi_ssl_session_cache*>(p);
+  // destroy call below will unref the pointer.
+  tsi_ssl_session_cache_ref(tsi_cache);
+  return p;
+}
+
+static void grpc_ssl_session_cache_arg_destroy(void* p) {
+  tsi_ssl_session_cache* tsi_cache =
+      reinterpret_cast<tsi_ssl_session_cache*>(p);
+  tsi_ssl_session_cache_unref(tsi_cache);
+}
+
+static int grpc_ssl_session_cache_arg_cmp(void* p, void* q) {
+  return GPR_ICMP(p, q);
+}
+
+grpc_arg grpc_ssl_session_cache_create_channel_arg(
+    grpc_ssl_session_cache* cache) {
+  static const grpc_arg_pointer_vtable vtable = {
+      grpc_ssl_session_cache_arg_copy,
+      grpc_ssl_session_cache_arg_destroy,
+      grpc_ssl_session_cache_arg_cmp,
+  };
+  return grpc_channel_arg_pointer_create(
+      const_cast<char*>(GRPC_SSL_SESSION_CACHE_ARG), cache, &vtable);
+}
+
 typedef struct {
   grpc_channel_security_connector base;
   tsi_ssl_client_handshaker_factory* client_handshaker_factory;
@@ -760,6 +800,9 @@
     } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) {
       grpc_auth_context_add_property(ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME,
                                      prop->value.data, prop->value.length);
+    } else if (strcmp(prop->name, TSI_SSL_SESSION_REUSED_PEER_PROPERTY) == 0) {
+      grpc_auth_context_add_property(ctx, GRPC_SSL_SESSION_REUSED_PROPERTY,
+                                     prop->value.data, prop->value.length);
     }
   }
   if (peer_identity_property_name != nullptr) {
@@ -983,28 +1026,30 @@
     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 = 0;
-  const char** alpn_protocol_strings =
-      fill_alpn_protocol_strings(&num_alpn_protocols);
+    const char* overridden_target_name,
+    tsi_ssl_session_cache* ssl_session_cache,
+    grpc_channel_security_connector** sc) {
   tsi_result result = TSI_OK;
   grpc_ssl_channel_security_connector* c;
-  const char* pem_root_certs;
   char* port;
   bool has_key_cert_pair;
+  tsi_ssl_client_handshaker_options options;
+  memset(&options, 0, sizeof(options));
+  options.alpn_protocols =
+      fill_alpn_protocol_strings(&options.num_alpn_protocols);
 
   if (config == nullptr || target_name == nullptr) {
     gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name.");
     goto error;
   }
   if (config->pem_root_certs == nullptr) {
-    pem_root_certs = grpc_get_default_ssl_roots();
-    if (pem_root_certs == nullptr) {
+    options.pem_root_certs = grpc_get_default_ssl_roots();
+    if (options.pem_root_certs == nullptr) {
       gpr_log(GPR_ERROR, "Could not get default pem root certs.");
       goto error;
     }
   } else {
-    pem_root_certs = config->pem_root_certs;
+    options.pem_root_certs = config->pem_root_certs;
   }
 
   c = static_cast<grpc_ssl_channel_security_connector*>(
@@ -1028,10 +1073,13 @@
   has_key_cert_pair = config->pem_key_cert_pair != nullptr &&
                       config->pem_key_cert_pair->private_key != nullptr &&
                       config->pem_key_cert_pair->cert_chain != nullptr;
-  result = tsi_create_ssl_client_handshaker_factory(
-      has_key_cert_pair ? config->pem_key_cert_pair : nullptr, pem_root_certs,
-      ssl_cipher_suites(), alpn_protocol_strings,
-      static_cast<uint16_t>(num_alpn_protocols), &c->client_handshaker_factory);
+  if (has_key_cert_pair) {
+    options.pem_key_cert_pair = config->pem_key_cert_pair;
+  }
+  options.cipher_suites = ssl_cipher_suites();
+  options.session_cache = ssl_session_cache;
+  result = tsi_create_ssl_client_handshaker_factory_with_options(
+      &options, &c->client_handshaker_factory);
   if (result != TSI_OK) {
     gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
             tsi_result_to_string(result));
@@ -1040,11 +1088,11 @@
     goto error;
   }
   *sc = &c->base;
-  gpr_free((void*)alpn_protocol_strings);
+  gpr_free((void*)options.alpn_protocols);
   return GRPC_SECURITY_OK;
 
 error:
-  gpr_free((void*)alpn_protocol_strings);
+  gpr_free((void*)options.alpn_protocols);
   return GRPC_SECURITY_ERROR;
 }
 
diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h
index 130c8ec..dc847d9 100644
--- a/src/core/lib/security/security_connector/security_connector.h
+++ b/src/core/lib/security/security_connector/security_connector.h
@@ -212,7 +212,9 @@
     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);
+    const char* overridden_target_name,
+    tsi_ssl_session_cache* ssl_session_cache,
+    grpc_channel_security_connector** sc);
 
 /* Gets the default ssl roots. Returns NULL if not found. */
 const char* grpc_get_default_ssl_roots(void);
diff --git a/src/core/plugin_registry/grpc_cronet_plugin_registry.cc b/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
index 49b9c7d..ab0f499 100644
--- a/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
+++ b/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
@@ -20,30 +20,34 @@
 
 #include <grpc/grpc.h>
 
+void grpc_deadline_filter_init(void);
+void grpc_deadline_filter_shutdown(void);
+void grpc_message_size_filter_init(void);
+void grpc_message_size_filter_shutdown(void);
+void grpc_server_load_reporting_plugin_init(void);
+void grpc_server_load_reporting_plugin_shutdown(void);
 void grpc_http_filters_init(void);
 void grpc_http_filters_shutdown(void);
 void grpc_chttp2_plugin_init(void);
 void grpc_chttp2_plugin_shutdown(void);
-void grpc_deadline_filter_init(void);
-void grpc_deadline_filter_shutdown(void);
 void grpc_client_channel_init(void);
 void grpc_client_channel_shutdown(void);
 void grpc_tsi_alts_init(void);
 void grpc_tsi_alts_shutdown(void);
-void grpc_server_load_reporting_plugin_init(void);
-void grpc_server_load_reporting_plugin_shutdown(void);
 
 void grpc_register_built_in_plugins(void) {
+  grpc_register_plugin(grpc_deadline_filter_init,
+                       grpc_deadline_filter_shutdown);
+  grpc_register_plugin(grpc_message_size_filter_init,
+                       grpc_message_size_filter_shutdown);
+  grpc_register_plugin(grpc_server_load_reporting_plugin_init,
+                       grpc_server_load_reporting_plugin_shutdown);
   grpc_register_plugin(grpc_http_filters_init,
                        grpc_http_filters_shutdown);
   grpc_register_plugin(grpc_chttp2_plugin_init,
                        grpc_chttp2_plugin_shutdown);
-  grpc_register_plugin(grpc_deadline_filter_init,
-                       grpc_deadline_filter_shutdown);
   grpc_register_plugin(grpc_client_channel_init,
                        grpc_client_channel_shutdown);
   grpc_register_plugin(grpc_tsi_alts_init,
                        grpc_tsi_alts_shutdown);
-  grpc_register_plugin(grpc_server_load_reporting_plugin_init,
-                       grpc_server_load_reporting_plugin_shutdown);
 }
diff --git a/src/core/tsi/ssl/session_cache/ssl_session.h b/src/core/tsi/ssl/session_cache/ssl_session.h
new file mode 100644
index 0000000..115221e
--- /dev/null
+++ b/src/core/tsi/ssl/session_cache/ssl_session.h
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright 2018 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_TSI_SSL_SESSION_CACHE_SSL_SESSION_H
+#define GRPC_CORE_TSI_SSL_SESSION_CACHE_SSL_SESSION_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/slice.h>
+
+extern "C" {
+#include <openssl/ssl.h>
+}
+
+#include "src/core/lib/gprpp/ref_counted.h"
+
+// The main purpose of code here is to provide means to cache SSL sessions
+// in a way that they can be shared between connections.
+//
+// SSL_SESSION stands for single instance of session and is not generally safe
+// to share between SSL contexts with different lifetimes. It happens because
+// not all SSL implementations guarantee immutability of SSL_SESSION object.
+// See SSL_SESSION documentation in BoringSSL and OpenSSL for more details.
+
+namespace tsi {
+
+struct SslSessionDeleter {
+  void operator()(SSL_SESSION* session) { SSL_SESSION_free(session); }
+};
+
+typedef std::unique_ptr<SSL_SESSION, SslSessionDeleter> SslSessionPtr;
+
+/// SslCachedSession is an immutable thread-safe storage for single session
+/// representation. It provides means to share SSL session data (e.g. TLS
+/// ticket) between encrypted connections regardless of SSL context lifetime.
+class SslCachedSession {
+ public:
+  // Not copyable nor movable.
+  SslCachedSession(const SslCachedSession&) = delete;
+  SslCachedSession& operator=(const SslCachedSession&) = delete;
+
+  /// Create single cached instance of \a session.
+  static grpc_core::UniquePtr<SslCachedSession> Create(SslSessionPtr session);
+
+  virtual ~SslCachedSession() = default;
+
+  /// Returns a copy of previously cached session.
+  virtual SslSessionPtr CopySession() const GRPC_ABSTRACT;
+
+  GRPC_ABSTRACT_BASE_CLASS
+
+ protected:
+  SslCachedSession() = default;
+};
+
+}  // namespace tsi
+
+#endif /* GRPC_CORE_TSI_SSL_SESSION_CACHE_SSL_SESSION_H */
diff --git a/src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc b/src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc
new file mode 100644
index 0000000..0da5a96
--- /dev/null
+++ b/src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright 2018 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 <grpc/support/port_platform.h>
+
+#include "src/core/tsi/ssl/session_cache/ssl_session.h"
+
+#ifdef OPENSSL_IS_BORINGSSL
+
+// BoringSSL allows SSL_SESSION to outlive SSL and SSL_CTX objects which are
+// re-created by gRPC on every certificate rotation or subchannel creation.
+// BoringSSL guarantees that SSL_SESSION is immutable so it's safe to share
+// the same original session object between different threads and connections.
+
+namespace tsi {
+namespace {
+
+class BoringSslCachedSession : public SslCachedSession {
+ public:
+  BoringSslCachedSession(SslSessionPtr session)
+      : session_(std::move(session)) {}
+
+  SslSessionPtr CopySession() const override {
+    // SslSessionPtr will dereference on destruction.
+    SSL_SESSION_up_ref(session_.get());
+    return SslSessionPtr(session_.get());
+  }
+
+ private:
+  SslSessionPtr session_;
+};
+
+}  // namespace
+
+grpc_core::UniquePtr<SslCachedSession> SslCachedSession::Create(
+    SslSessionPtr session) {
+  return grpc_core::UniquePtr<SslCachedSession>(
+      grpc_core::New<BoringSslCachedSession>(std::move(session)));
+}
+
+}  // namespace tsi
+
+#endif /* OPENSSL_IS_BORINGSSL */
diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc
new file mode 100644
index 0000000..fe4f83a
--- /dev/null
+++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc
@@ -0,0 +1,211 @@
+/*
+ *
+ * Copyright 2018 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 <grpc/support/port_platform.h>
+
+#include "src/core/tsi/ssl/session_cache/ssl_session_cache.h"
+
+#include "src/core/tsi/ssl/session_cache/ssl_session.h"
+
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+namespace tsi {
+
+static void cache_key_avl_destroy(void* key, void* unused) {}
+
+static void* cache_key_avl_copy(void* key, void* unused) { return key; }
+
+static long cache_key_avl_compare(void* key1, void* key2, void* unused) {
+  return grpc_slice_cmp(*static_cast<grpc_slice*>(key1),
+                        *static_cast<grpc_slice*>(key2));
+}
+
+static void cache_value_avl_destroy(void* value, void* unused) {}
+
+static void* cache_value_avl_copy(void* value, void* unused) { return value; }
+
+// AVL only stores pointers, ownership belonges to the linked list.
+static const grpc_avl_vtable cache_avl_vtable = {
+    cache_key_avl_destroy,   cache_key_avl_copy,   cache_key_avl_compare,
+    cache_value_avl_destroy, cache_value_avl_copy,
+};
+
+/// Node for single cached session.
+class SslSessionLRUCache::Node {
+ public:
+  Node(const grpc_slice& key, SslSessionPtr session) : key_(key) {
+    SetSession(std::move(session));
+  }
+
+  ~Node() { grpc_slice_unref(key_); }
+
+  // Not copyable nor movable.
+  Node(const Node&) = delete;
+  Node& operator=(const Node&) = delete;
+
+  void* AvlKey() { return &key_; }
+
+  /// Returns a copy of the node's cache session.
+  SslSessionPtr CopySession() const { return session_->CopySession(); }
+
+  /// Set the \a session (which is moved) for the node.
+  void SetSession(SslSessionPtr session) {
+    session_ = SslCachedSession::Create(std::move(session));
+  }
+
+ private:
+  friend class SslSessionLRUCache;
+
+  grpc_slice key_;
+  grpc_core::UniquePtr<SslCachedSession> session_;
+
+  Node* next_ = nullptr;
+  Node* prev_ = nullptr;
+};
+
+SslSessionLRUCache::SslSessionLRUCache(size_t capacity) : capacity_(capacity) {
+  GPR_ASSERT(capacity > 0);
+  gpr_mu_init(&lock_);
+  entry_by_key_ = grpc_avl_create(&cache_avl_vtable);
+}
+
+SslSessionLRUCache::~SslSessionLRUCache() {
+  Node* node = use_order_list_head_;
+  while (node) {
+    Node* next = node->next_;
+    grpc_core::Delete(node);
+    node = next;
+  }
+  grpc_avl_unref(entry_by_key_, nullptr);
+  gpr_mu_destroy(&lock_);
+}
+
+size_t SslSessionLRUCache::Size() {
+  grpc_core::mu_guard guard(&lock_);
+  return use_order_list_size_;
+}
+
+SslSessionLRUCache::Node* SslSessionLRUCache::FindLocked(
+    const grpc_slice& key) {
+  void* value =
+      grpc_avl_get(entry_by_key_, const_cast<grpc_slice*>(&key), nullptr);
+  if (value == nullptr) {
+    return nullptr;
+  }
+  Node* node = static_cast<Node*>(value);
+  // Move to the beginning.
+  Remove(node);
+  PushFront(node);
+  AssertInvariants();
+  return node;
+}
+
+void SslSessionLRUCache::Put(const char* key, SslSessionPtr session) {
+  grpc_core::mu_guard guard(&lock_);
+  Node* node = FindLocked(grpc_slice_from_static_string(key));
+  if (node != nullptr) {
+    node->SetSession(std::move(session));
+    return;
+  }
+  grpc_slice key_slice = grpc_slice_from_copied_string(key);
+  node = grpc_core::New<Node>(key_slice, std::move(session));
+  PushFront(node);
+  entry_by_key_ = grpc_avl_add(entry_by_key_, node->AvlKey(), node, nullptr);
+  AssertInvariants();
+  if (use_order_list_size_ > capacity_) {
+    GPR_ASSERT(use_order_list_tail_);
+    node = use_order_list_tail_;
+    Remove(node);
+    // Order matters, key is destroyed after deleting node.
+    entry_by_key_ = grpc_avl_remove(entry_by_key_, node->AvlKey(), nullptr);
+    grpc_core::Delete(node);
+    AssertInvariants();
+  }
+}
+
+SslSessionPtr SslSessionLRUCache::Get(const char* key) {
+  grpc_core::mu_guard guard(&lock_);
+  // Key is only used for lookups.
+  grpc_slice key_slice = grpc_slice_from_static_string(key);
+  Node* node = FindLocked(key_slice);
+  if (node == nullptr) {
+    return nullptr;
+  }
+  return node->CopySession();
+}
+
+void SslSessionLRUCache::Remove(SslSessionLRUCache::Node* node) {
+  if (node->prev_ == nullptr) {
+    use_order_list_head_ = node->next_;
+  } else {
+    node->prev_->next_ = node->next_;
+  }
+  if (node->next_ == nullptr) {
+    use_order_list_tail_ = node->prev_;
+  } else {
+    node->next_->prev_ = node->prev_;
+  }
+  GPR_ASSERT(use_order_list_size_ >= 1);
+  use_order_list_size_--;
+}
+
+void SslSessionLRUCache::PushFront(SslSessionLRUCache::Node* node) {
+  if (use_order_list_head_ == nullptr) {
+    use_order_list_head_ = node;
+    use_order_list_tail_ = node;
+    node->next_ = nullptr;
+    node->prev_ = nullptr;
+  } else {
+    node->next_ = use_order_list_head_;
+    node->next_->prev_ = node;
+    use_order_list_head_ = node;
+    node->prev_ = nullptr;
+  }
+  use_order_list_size_++;
+}
+
+#ifndef NDEBUG
+static size_t calculate_tree_size(grpc_avl_node* node) {
+  if (node == nullptr) {
+    return 0;
+  }
+  return 1 + calculate_tree_size(node->left) + calculate_tree_size(node->right);
+}
+
+void SslSessionLRUCache::AssertInvariants() {
+  size_t size = 0;
+  Node* prev = nullptr;
+  Node* current = use_order_list_head_;
+  while (current != nullptr) {
+    size++;
+    GPR_ASSERT(current->prev_ == prev);
+    void* node = grpc_avl_get(entry_by_key_, current->AvlKey(), nullptr);
+    GPR_ASSERT(node == current);
+    prev = current;
+    current = current->next_;
+  }
+  GPR_ASSERT(prev == use_order_list_tail_);
+  GPR_ASSERT(size == use_order_list_size_);
+  GPR_ASSERT(calculate_tree_size(entry_by_key_.root) == use_order_list_size_);
+}
+#else
+void SslSessionLRUCache::AssertInvariants() {}
+#endif
+
+}  // namespace tsi
diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.h b/src/core/tsi/ssl/session_cache/ssl_session_cache.h
new file mode 100644
index 0000000..488638c
--- /dev/null
+++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.h
@@ -0,0 +1,93 @@
+/*
+ *
+ * Copyright 2018 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_TSI_SSL_SESSION_CACHE_SSL_SESSION_CACHE_H
+#define GRPC_CORE_TSI_SSL_SESSION_CACHE_SSL_SESSION_CACHE_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/slice.h>
+#include <grpc/support/sync.h>
+
+extern "C" {
+#include <openssl/ssl.h>
+}
+
+#include "src/core/lib/avl/avl.h"
+#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/tsi/ssl/session_cache/ssl_session.h"
+
+/// Cache for SSL sessions for sessions resumption.
+///
+/// Older sessions may be evicted from the cache using LRU policy if capacity
+/// limit is hit. All sessions are associated with some key, usually server
+/// name. Note that servers are required to share session ticket encryption keys
+/// in order for cache to be effective.
+///
+/// This class is thread safe.
+
+namespace tsi {
+
+class SslSessionLRUCache : public grpc_core::RefCounted<SslSessionLRUCache> {
+ public:
+  /// Create new LRU cache with the given capacity.
+  static grpc_core::RefCountedPtr<SslSessionLRUCache> Create(size_t capacity) {
+    return grpc_core::MakeRefCounted<SslSessionLRUCache>(capacity);
+  }
+
+  // Not copyable nor movable.
+  SslSessionLRUCache(const SslSessionLRUCache&) = delete;
+  SslSessionLRUCache& operator=(const SslSessionLRUCache&) = delete;
+
+  /// Returns current number of sessions in the cache.
+  size_t Size();
+  /// Add \a session in the cache using \a key. This operation may discard older
+  /// sessions.
+  void Put(const char* key, SslSessionPtr session);
+  /// Returns the session from the cache associated with \a key or null if not
+  /// found.
+  SslSessionPtr Get(const char* key);
+
+ private:
+  // So New() can call our private ctor.
+  template <typename T, typename... Args>
+  friend T* grpc_core::New(Args&&... args);
+
+  class Node;
+
+  explicit SslSessionLRUCache(size_t capacity);
+  ~SslSessionLRUCache();
+
+  Node* FindLocked(const grpc_slice& key);
+  void Remove(Node* node);
+  void PushFront(Node* node);
+  void AssertInvariants();
+
+  gpr_mu lock_;
+  size_t capacity_;
+
+  Node* use_order_list_head_ = nullptr;
+  Node* use_order_list_tail_ = nullptr;
+  size_t use_order_list_size_ = 0;
+  grpc_avl entry_by_key_;
+};
+
+}  // namespace tsi
+
+#endif /* GRPC_CORE_TSI_SSL_SESSION_CACHE_SSL_SESSION_CACHE_H */
diff --git a/src/core/tsi/ssl/session_cache/ssl_session_openssl.cc b/src/core/tsi/ssl/session_cache/ssl_session_openssl.cc
new file mode 100644
index 0000000..61c036c
--- /dev/null
+++ b/src/core/tsi/ssl/session_cache/ssl_session_openssl.cc
@@ -0,0 +1,76 @@
+/*
+ *
+ * Copyright 2018 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 <grpc/support/port_platform.h>
+
+#include "src/core/tsi/ssl/session_cache/ssl_session.h"
+
+#include <grpc/support/log.h>
+
+#ifndef OPENSSL_IS_BORINGSSL
+
+// OpenSSL invalidates SSL_SESSION on SSL destruction making it pointless
+// to cache sessions. The workaround is to serialize (relatively expensive)
+// session into binary blob and re-create it from blob on every handshake.
+// Note that it's safe to keep serialized session outside of SSL lifetime
+// as openssl performs all necessary validation while attempting to use a
+// session and creates a new one if something is wrong (e.g. server changed
+// set of allowed codecs).
+
+namespace tsi {
+namespace {
+
+class OpenSslCachedSession : public SslCachedSession {
+ public:
+  OpenSslCachedSession(SslSessionPtr session) {
+    int size = i2d_SSL_SESSION(session.get(), nullptr);
+    GPR_ASSERT(size > 0);
+    grpc_slice slice = grpc_slice_malloc(size_t(size));
+    unsigned char* start = GRPC_SLICE_START_PTR(slice);
+    int second_size = i2d_SSL_SESSION(session.get(), &start);
+    GPR_ASSERT(size == second_size);
+    serialized_session_ = slice;
+  }
+
+  virtual ~OpenSslCachedSession() { grpc_slice_unref(serialized_session_); }
+
+  SslSessionPtr CopySession() const override {
+    const unsigned char* data = GRPC_SLICE_START_PTR(serialized_session_);
+    size_t length = GRPC_SLICE_LENGTH(serialized_session_);
+    SSL_SESSION* session = d2i_SSL_SESSION(nullptr, &data, length);
+    if (session == nullptr) {
+      return SslSessionPtr();
+    }
+    return SslSessionPtr(session);
+  }
+
+ private:
+  grpc_slice serialized_session_;
+};
+
+}  // namespace
+
+grpc_core::UniquePtr<SslCachedSession> SslCachedSession::Create(
+    SslSessionPtr session) {
+  return grpc_core::UniquePtr<SslCachedSession>(
+      grpc_core::New<OpenSslCachedSession>(std::move(session)));
+}
+
+}  // namespace tsi
+
+#endif /* OPENSSL_IS_BORINGSSL */
diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc
index 971170b..0fc2926 100644
--- a/src/core/tsi/ssl_transport_security.cc
+++ b/src/core/tsi/ssl_transport_security.cc
@@ -35,6 +35,7 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd_id.h>
 
@@ -47,6 +48,8 @@
 #include <openssl/x509v3.h>
 }
 
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/tsi/ssl/session_cache/ssl_session_cache.h"
 #include "src/core/tsi/ssl_types.h"
 #include "src/core/tsi/transport_security.h"
 
@@ -78,6 +81,7 @@
   SSL_CTX* ssl_context;
   unsigned char* alpn_protocol_list;
   size_t alpn_protocol_list_length;
+  grpc_core::RefCountedPtr<tsi::SslSessionLRUCache> session_cache;
 };
 
 struct tsi_ssl_server_handshaker_factory {
@@ -111,17 +115,19 @@
 
 /* --- Library Initialization. ---*/
 
-static gpr_once init_openssl_once = GPR_ONCE_INIT;
-static gpr_mu* openssl_mutexes = nullptr;
+static gpr_once g_init_openssl_once = GPR_ONCE_INIT;
+static gpr_mu* g_openssl_mutexes = nullptr;
+static int g_ssl_ctx_ex_factory_index = -1;
 static void openssl_locking_cb(int mode, int type, const char* file,
                                int line) GRPC_UNUSED;
 static unsigned long openssl_thread_id_cb(void) GRPC_UNUSED;
+static const unsigned char kSslSessionIdContext[] = {'g', 'r', 'p', 'c'};
 
 static void openssl_locking_cb(int mode, int type, const char* file, int line) {
   if (mode & CRYPTO_LOCK) {
-    gpr_mu_lock(&openssl_mutexes[type]);
+    gpr_mu_lock(&g_openssl_mutexes[type]);
   } else {
-    gpr_mu_unlock(&openssl_mutexes[type]);
+    gpr_mu_unlock(&g_openssl_mutexes[type]);
   }
 }
 
@@ -137,13 +143,16 @@
   OpenSSL_add_all_algorithms();
   num_locks = CRYPTO_num_locks();
   GPR_ASSERT(num_locks > 0);
-  openssl_mutexes = static_cast<gpr_mu*>(
+  g_openssl_mutexes = static_cast<gpr_mu*>(
       gpr_malloc(static_cast<size_t>(num_locks) * sizeof(gpr_mu)));
   for (i = 0; i < CRYPTO_num_locks(); i++) {
-    gpr_mu_init(&openssl_mutexes[i]);
+    gpr_mu_init(&g_openssl_mutexes[i]);
   }
   CRYPTO_set_locking_callback(openssl_locking_cb);
   CRYPTO_set_id_callback(openssl_thread_id_cb);
+  g_ssl_ctx_ex_factory_index =
+      SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
+  GPR_ASSERT(g_ssl_ctx_ex_factory_index != -1);
 }
 
 /* --- Ssl utils. ---*/
@@ -721,6 +730,23 @@
   return 1;
 }
 
+/* --- tsi_ssl_session_cache methods implementation. ---*/
+
+tsi_ssl_session_cache* tsi_ssl_session_cache_create_lru(size_t capacity) {
+  /* Pointer will be dereferenced by unref call. */
+  return reinterpret_cast<tsi_ssl_session_cache*>(
+      tsi::SslSessionLRUCache::Create(capacity).release());
+}
+
+void tsi_ssl_session_cache_ref(tsi_ssl_session_cache* cache) {
+  /* Pointer will be dereferenced by unref call. */
+  reinterpret_cast<tsi::SslSessionLRUCache*>(cache)->Ref().release();
+}
+
+void tsi_ssl_session_cache_unref(tsi_ssl_session_cache* cache) {
+  reinterpret_cast<tsi::SslSessionLRUCache*>(cache)->Unref();
+}
+
 /* --- tsi_frame_protector methods implementation. ---*/
 
 static tsi_result ssl_protector_protect(tsi_frame_protector* self,
@@ -1015,25 +1041,34 @@
     SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected,
                                    &alpn_selected_len);
   }
+
+  // 1 is for session reused property.
+  size_t new_property_count = peer->property_count + 1;
+  if (alpn_selected != nullptr) new_property_count++;
+  tsi_peer_property* new_properties = static_cast<tsi_peer_property*>(
+      gpr_zalloc(sizeof(*new_properties) * new_property_count));
+  for (size_t i = 0; i < peer->property_count; i++) {
+    new_properties[i] = peer->properties[i];
+  }
+  if (peer->properties != nullptr) gpr_free(peer->properties);
+  peer->properties = new_properties;
+
   if (alpn_selected != nullptr) {
-    size_t i;
-    tsi_peer_property* new_properties = static_cast<tsi_peer_property*>(
-        gpr_zalloc(sizeof(*new_properties) * (peer->property_count + 1)));
-    for (i = 0; i < peer->property_count; i++) {
-      new_properties[i] = peer->properties[i];
-    }
     result = tsi_construct_string_peer_property(
         TSI_SSL_ALPN_SELECTED_PROTOCOL,
         reinterpret_cast<const char*>(alpn_selected), alpn_selected_len,
-        &new_properties[peer->property_count]);
-    if (result != TSI_OK) {
-      gpr_free(new_properties);
-      return result;
-    }
-    if (peer->properties != nullptr) gpr_free(peer->properties);
+        &peer->properties[peer->property_count]);
+    if (result != TSI_OK) return result;
     peer->property_count++;
-    peer->properties = new_properties;
   }
+
+  const char* session_reused = SSL_session_reused(impl->ssl) ? "true" : "false";
+  result = tsi_construct_string_peer_property(
+      TSI_SSL_SESSION_REUSED_PEER_PROPERTY, session_reused,
+      strlen(session_reused) + 1, &peer->properties[peer->property_count]);
+  if (result != TSI_OK) return result;
+  peer->property_count++;
+
   return result;
 }
 
@@ -1103,6 +1138,19 @@
 
 /* --- tsi_ssl_handshaker_factory common methods. --- */
 
+static void tsi_ssl_handshaker_resume_session(
+    SSL* ssl, tsi::SslSessionLRUCache* session_cache) {
+  const char* server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+  if (server_name == nullptr) {
+    return;
+  }
+  tsi::SslSessionPtr session = session_cache->Get(server_name);
+  if (session != nullptr) {
+    // SSL_set_session internally increments reference counter.
+    SSL_set_session(ssl, session.get());
+  }
+}
+
 static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client,
                                             const char* server_name_indication,
                                             tsi_ssl_handshaker_factory* factory,
@@ -1139,6 +1187,12 @@
         return TSI_INTERNAL_ERROR;
       }
     }
+    tsi_ssl_client_handshaker_factory* client_factory =
+        reinterpret_cast<tsi_ssl_client_handshaker_factory*>(factory);
+    if (client_factory->session_cache != nullptr) {
+      tsi_ssl_handshaker_resume_session(ssl,
+                                        client_factory->session_cache.get());
+    }
     ssl_result = SSL_do_handshake(ssl);
     ssl_result = SSL_get_error(ssl, ssl_result);
     if (ssl_result != SSL_ERROR_WANT_READ) {
@@ -1214,6 +1268,7 @@
       reinterpret_cast<tsi_ssl_client_handshaker_factory*>(factory);
   if (self->ssl_context != nullptr) SSL_CTX_free(self->ssl_context);
   if (self->alpn_protocol_list != nullptr) gpr_free(self->alpn_protocol_list);
+  self->session_cache.reset();
   gpr_free(self);
 }
 
@@ -1357,6 +1412,30 @@
   return SSL_TLSEXT_ERR_OK;
 }
 
+/// This callback is called when new \a session is established and ready to
+/// be cached. This session can be reused for new connections to similar
+/// servers at later point of time.
+/// It's intended to be used with SSL_CTX_sess_set_new_cb function.
+///
+/// It returns 1 if callback takes ownership over \a session and 0 otherwise.
+static int server_handshaker_factory_new_session_callback(
+    SSL* ssl, SSL_SESSION* session) {
+  SSL_CTX* ssl_context = SSL_get_SSL_CTX(ssl);
+  if (ssl_context == nullptr) {
+    return 0;
+  }
+  void* arg = SSL_CTX_get_ex_data(ssl_context, g_ssl_ctx_ex_factory_index);
+  tsi_ssl_client_handshaker_factory* factory =
+      static_cast<tsi_ssl_client_handshaker_factory*>(arg);
+  const char* server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+  if (server_name == nullptr) {
+    return 0;
+  }
+  factory->session_cache->Put(server_name, tsi::SslSessionPtr(session));
+  // Return 1 to indicate transfered ownership over the given session.
+  return 1;
+}
+
 /* --- tsi_ssl_handshaker_factory constructors. --- */
 
 static tsi_ssl_handshaker_factory_vtable client_handshaker_factory_vtable = {
@@ -1367,15 +1446,29 @@
     const char* pem_root_certs, const char* cipher_suites,
     const char** alpn_protocols, uint16_t num_alpn_protocols,
     tsi_ssl_client_handshaker_factory** factory) {
+  tsi_ssl_client_handshaker_options options;
+  memset(&options, 0, sizeof(options));
+  options.pem_key_cert_pair = pem_key_cert_pair;
+  options.pem_root_certs = pem_root_certs;
+  options.cipher_suites = cipher_suites;
+  options.alpn_protocols = alpn_protocols;
+  options.num_alpn_protocols = num_alpn_protocols;
+  return tsi_create_ssl_client_handshaker_factory_with_options(&options,
+                                                               factory);
+}
+
+tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
+    const tsi_ssl_client_handshaker_options* options,
+    tsi_ssl_client_handshaker_factory** factory) {
   SSL_CTX* ssl_context = nullptr;
   tsi_ssl_client_handshaker_factory* impl = nullptr;
   tsi_result result = TSI_OK;
 
-  gpr_once_init(&init_openssl_once, init_openssl);
+  gpr_once_init(&g_init_openssl_once, init_openssl);
 
   if (factory == nullptr) return TSI_INVALID_ARGUMENT;
   *factory = nullptr;
-  if (pem_root_certs == nullptr) return TSI_INVALID_ARGUMENT;
+  if (options->pem_root_certs == nullptr) return TSI_INVALID_ARGUMENT;
 
   ssl_context = SSL_CTX_new(TLSv1_2_method());
   if (ssl_context == nullptr) {
@@ -1390,21 +1483,33 @@
 
   impl->ssl_context = ssl_context;
 
+  if (options->session_cache != nullptr) {
+    // Unref is called manually on factory destruction.
+    impl->session_cache =
+        reinterpret_cast<tsi::SslSessionLRUCache*>(options->session_cache)
+            ->Ref();
+    SSL_CTX_set_ex_data(ssl_context, g_ssl_ctx_ex_factory_index, impl);
+    SSL_CTX_sess_set_new_cb(ssl_context,
+                            server_handshaker_factory_new_session_callback);
+    SSL_CTX_set_session_cache_mode(ssl_context, SSL_SESS_CACHE_CLIENT);
+  }
+
   do {
-    result =
-        populate_ssl_context(ssl_context, pem_key_cert_pair, cipher_suites);
+    result = populate_ssl_context(ssl_context, options->pem_key_cert_pair,
+                                  options->cipher_suites);
     if (result != TSI_OK) break;
-    result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs,
-                                             strlen(pem_root_certs), nullptr);
+    result = ssl_ctx_load_verification_certs(
+        ssl_context, options->pem_root_certs, strlen(options->pem_root_certs),
+        nullptr);
     if (result != TSI_OK) {
       gpr_log(GPR_ERROR, "Cannot load server root certificates.");
       break;
     }
 
-    if (num_alpn_protocols != 0) {
-      result = build_alpn_protocol_name_list(alpn_protocols, num_alpn_protocols,
-                                             &impl->alpn_protocol_list,
-                                             &impl->alpn_protocol_list_length);
+    if (options->num_alpn_protocols != 0) {
+      result = build_alpn_protocol_name_list(
+          options->alpn_protocols, options->num_alpn_protocols,
+          &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
       if (result != TSI_OK) {
         gpr_log(GPR_ERROR, "Building alpn list failed with error %s.",
                 tsi_result_to_string(result));
@@ -1457,15 +1562,32 @@
     tsi_client_certificate_request_type client_certificate_request,
     const char* cipher_suites, const char** alpn_protocols,
     uint16_t num_alpn_protocols, tsi_ssl_server_handshaker_factory** factory) {
+  tsi_ssl_server_handshaker_options options;
+  memset(&options, 0, sizeof(options));
+  options.pem_key_cert_pairs = pem_key_cert_pairs;
+  options.num_key_cert_pairs = num_key_cert_pairs;
+  options.pem_client_root_certs = pem_client_root_certs;
+  options.client_certificate_request = client_certificate_request;
+  options.cipher_suites = cipher_suites;
+  options.alpn_protocols = alpn_protocols;
+  options.num_alpn_protocols = num_alpn_protocols;
+  return tsi_create_ssl_server_handshaker_factory_with_options(&options,
+                                                               factory);
+}
+
+tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
+    const tsi_ssl_server_handshaker_options* options,
+    tsi_ssl_server_handshaker_factory** factory) {
   tsi_ssl_server_handshaker_factory* impl = nullptr;
   tsi_result result = TSI_OK;
   size_t i = 0;
 
-  gpr_once_init(&init_openssl_once, init_openssl);
+  gpr_once_init(&g_init_openssl_once, init_openssl);
 
   if (factory == nullptr) return TSI_INVALID_ARGUMENT;
   *factory = nullptr;
-  if (num_key_cert_pairs == 0 || pem_key_cert_pairs == nullptr) {
+  if (options->num_key_cert_pairs == 0 ||
+      options->pem_key_cert_pairs == nullptr) {
     return TSI_INVALID_ARGUMENT;
   }
 
@@ -1474,28 +1596,28 @@
   tsi_ssl_handshaker_factory_init(&impl->base);
   impl->base.vtable = &server_handshaker_factory_vtable;
 
-  impl->ssl_contexts =
-      static_cast<SSL_CTX**>(gpr_zalloc(num_key_cert_pairs * sizeof(SSL_CTX*)));
-  impl->ssl_context_x509_subject_names =
-      static_cast<tsi_peer*>(gpr_zalloc(num_key_cert_pairs * sizeof(tsi_peer)));
+  impl->ssl_contexts = static_cast<SSL_CTX**>(
+      gpr_zalloc(options->num_key_cert_pairs * sizeof(SSL_CTX*)));
+  impl->ssl_context_x509_subject_names = static_cast<tsi_peer*>(
+      gpr_zalloc(options->num_key_cert_pairs * sizeof(tsi_peer)));
   if (impl->ssl_contexts == nullptr ||
       impl->ssl_context_x509_subject_names == nullptr) {
     tsi_ssl_handshaker_factory_unref(&impl->base);
     return TSI_OUT_OF_RESOURCES;
   }
-  impl->ssl_context_count = num_key_cert_pairs;
+  impl->ssl_context_count = options->num_key_cert_pairs;
 
-  if (num_alpn_protocols > 0) {
-    result = build_alpn_protocol_name_list(alpn_protocols, num_alpn_protocols,
-                                           &impl->alpn_protocol_list,
-                                           &impl->alpn_protocol_list_length);
+  if (options->num_alpn_protocols > 0) {
+    result = build_alpn_protocol_name_list(
+        options->alpn_protocols, options->num_alpn_protocols,
+        &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
     if (result != TSI_OK) {
       tsi_ssl_handshaker_factory_unref(&impl->base);
       return result;
     }
   }
 
-  for (i = 0; i < num_key_cert_pairs; i++) {
+  for (i = 0; i < options->num_key_cert_pairs; i++) {
     do {
       impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
       if (impl->ssl_contexts[i] == nullptr) {
@@ -1504,20 +1626,44 @@
         break;
       }
       result = populate_ssl_context(impl->ssl_contexts[i],
-                                    &pem_key_cert_pairs[i], cipher_suites);
+                                    &options->pem_key_cert_pairs[i],
+                                    options->cipher_suites);
       if (result != TSI_OK) break;
 
-      if (pem_client_root_certs != nullptr) {
+      // TODO(elessar): Provide ability to disable session ticket keys.
+
+      // Allow client cache sessions (it's needed for OpenSSL only).
+      int set_sid_ctx_result = SSL_CTX_set_session_id_context(
+          impl->ssl_contexts[i], kSslSessionIdContext,
+          GPR_ARRAY_SIZE(kSslSessionIdContext));
+      if (set_sid_ctx_result == 0) {
+        gpr_log(GPR_ERROR, "Failed to set session id context.");
+        result = TSI_INTERNAL_ERROR;
+        break;
+      }
+
+      if (options->session_ticket_key != nullptr) {
+        if (SSL_CTX_set_tlsext_ticket_keys(
+                impl->ssl_contexts[i],
+                const_cast<char*>(options->session_ticket_key),
+                options->session_ticket_key_size) == 0) {
+          gpr_log(GPR_ERROR, "Invalid STEK size.");
+          result = TSI_INVALID_ARGUMENT;
+          break;
+        }
+      }
+
+      if (options->pem_client_root_certs != nullptr) {
         STACK_OF(X509_NAME)* root_names = nullptr;
         result = ssl_ctx_load_verification_certs(
-            impl->ssl_contexts[i], pem_client_root_certs,
-            strlen(pem_client_root_certs), &root_names);
+            impl->ssl_contexts[i], options->pem_client_root_certs,
+            strlen(options->pem_client_root_certs), &root_names);
         if (result != TSI_OK) {
           gpr_log(GPR_ERROR, "Invalid verification certs.");
           break;
         }
         SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
-        switch (client_certificate_request) {
+        switch (options->client_certificate_request) {
           case TSI_DONT_REQUEST_CLIENT_CERTIFICATE:
             SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_NONE, nullptr);
             break;
@@ -1544,7 +1690,7 @@
       }
 
       result = extract_x509_subject_names_from_pem_cert(
-          pem_key_cert_pairs[i].cert_chain,
+          options->pem_key_cert_pairs[i].cert_chain,
           &impl->ssl_context_x509_subject_names[i]);
       if (result != TSI_OK) break;
 
diff --git a/src/core/tsi/ssl_transport_security.h b/src/core/tsi/ssl_transport_security.h
index edebadc..29d209b 100644
--- a/src/core/tsi/ssl_transport_security.h
+++ b/src/core/tsi/ssl_transport_security.h
@@ -30,11 +30,27 @@
 #define TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY "x509_subject_common_name"
 #define TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY \
   "x509_subject_alternative_name"
+#define TSI_SSL_SESSION_REUSED_PEER_PROPERTY "ssl_session_reused"
 
 #define TSI_X509_PEM_CERT_PROPERTY "x509_pem_cert"
 
 #define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol"
 
+/* --- tsi_ssl_session_cache object ---
+
+   Cache for SSL sessions for sessions resumption.  */
+
+typedef struct tsi_ssl_session_cache tsi_ssl_session_cache;
+
+/* Create LRU cache for SSL sessions with \a capacity.  */
+tsi_ssl_session_cache* tsi_ssl_session_cache_create_lru(size_t capacity);
+
+/* Increment reference counter of \a cache.  */
+void tsi_ssl_session_cache_ref(tsi_ssl_session_cache* cache);
+
+/* Decrement reference counter of \a cache.  */
+void tsi_ssl_session_cache_unref(tsi_ssl_session_cache* cache);
+
 /* --- tsi_ssl_client_handshaker_factory object ---
 
    This object creates a client tsi_handshaker objects implemented in terms of
@@ -81,6 +97,43 @@
     const char** alpn_protocols, uint16_t num_alpn_protocols,
     tsi_ssl_client_handshaker_factory** factory);
 
+typedef struct {
+  /* pem_key_cert_pair is a pointer to the object containing client's private
+     key and certificate chain. This parameter can be NULL if the client does
+     not have such a key/cert pair. */
+  const tsi_ssl_pem_key_cert_pair* pem_key_cert_pair;
+  /* pem_roots_cert is the NULL-terminated string containing the PEM encoding of
+     the client root certificates. This parameter may be NULL if the server does
+     not want the client to be authenticated with SSL. */
+  const char* pem_root_certs;
+  /* cipher_suites contains an optional list of the ciphers that the client
+     supports. The format of this string is described in:
+     https://www.openssl.org/docs/apps/ciphers.html.
+     This parameter can be set to NULL to use the default set of ciphers.
+     TODO(jboeuf): Revisit the format of this parameter. */
+  const char* cipher_suites;
+  /* alpn_protocols is an array containing the NULL terminated protocol names
+     that the handshakers created with this factory support. This parameter can
+     be NULL. */
+  const char** alpn_protocols;
+  /* num_alpn_protocols is the number of alpn protocols and associated lengths
+     specified. If this parameter is 0, the other alpn parameters must be
+     NULL. */
+  size_t num_alpn_protocols;
+  /* ssl_session_cache is a cache for reusable client-side sessions. */
+  tsi_ssl_session_cache* session_cache;
+} tsi_ssl_client_handshaker_options;
+
+/* Creates a client handshaker factory.
+   - options is the options used to create a factory.
+   - factory is the address of the factory pointer to be created.
+
+   - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
+     where a parameter is invalid. */
+tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
+    const tsi_ssl_client_handshaker_options* options,
+    tsi_ssl_client_handshaker_factory** factory);
+
 /* Creates a client handshaker.
   - self is the factory from which the handshaker will be created.
   - server_name_indication indicates the name of the server the client is
@@ -147,6 +200,51 @@
     const char* cipher_suites, const char** alpn_protocols,
     uint16_t num_alpn_protocols, tsi_ssl_server_handshaker_factory** factory);
 
+typedef struct {
+  /* pem_key_cert_pairs is an array private key / certificate chains of the
+     server. */
+  const tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs;
+  /* num_key_cert_pairs is the number of items in the pem_key_cert_pairs
+     array. */
+  size_t num_key_cert_pairs;
+  /* pem_root_certs is the NULL-terminated string containing the PEM encoding
+     of the server root certificates. */
+  const char* pem_client_root_certs;
+  /* client_certificate_request, if set to non-zero will force the client to
+     authenticate with an SSL cert. Note that this option is ignored if
+     pem_client_root_certs is NULL or pem_client_roots_certs_size is 0. */
+  tsi_client_certificate_request_type client_certificate_request;
+  /* cipher_suites contains an optional list of the ciphers that the server
+     supports. The format of this string is described in:
+     https://www.openssl.org/docs/apps/ciphers.html.
+     This parameter can be set to NULL to use the default set of ciphers.
+     TODO(jboeuf): Revisit the format of this parameter. */
+  const char* cipher_suites;
+  /* alpn_protocols is an array containing the NULL terminated protocol names
+     that the handshakers created with this factory support. This parameter can
+     be NULL. */
+  const char** alpn_protocols;
+  /* num_alpn_protocols is the number of alpn protocols and associated lengths
+     specified. If this parameter is 0, the other alpn parameters must be
+     NULL. */
+  uint16_t num_alpn_protocols;
+  /* session_ticket_key is optional key for encrypting session keys. If paramter
+     is not specified it must be NULL. */
+  const char* session_ticket_key;
+  /* session_ticket_key_size is a size of session ticket encryption key. */
+  size_t session_ticket_key_size;
+} tsi_ssl_server_handshaker_options;
+
+/* Creates a server handshaker factory.
+   - options is the options used to create a factory.
+   - factory is the address of the factory pointer to be created.
+
+   - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
+     where a parameter is invalid. */
+tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
+    const tsi_ssl_server_handshaker_options* options,
+    tsi_ssl_server_handshaker_factory** factory);
+
 /* Creates a server handshaker.
   - self is the factory from which the handshaker will be created.
   - handshaker is the address of the handshaker pointer to be created.
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index 760aaa4..391ca44 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -45,6 +45,7 @@
 #include "src/cpp/thread_manager/thread_manager.h"
 
 namespace grpc {
+namespace {
 
 class DefaultGlobalCallbacks final : public Server::GlobalCallbacks {
  public:
@@ -53,16 +54,29 @@
   void PostSynchronousRequest(ServerContext* context) override {}
 };
 
-static std::shared_ptr<Server::GlobalCallbacks> g_callbacks = nullptr;
-static gpr_once g_once_init_callbacks = GPR_ONCE_INIT;
+std::shared_ptr<Server::GlobalCallbacks> g_callbacks = nullptr;
+gpr_once g_once_init_callbacks = GPR_ONCE_INIT;
 
-static void InitGlobalCallbacks() {
+void InitGlobalCallbacks() {
   if (!g_callbacks) {
     g_callbacks.reset(new DefaultGlobalCallbacks());
   }
 }
 
-class Server::UnimplementedAsyncRequestContext {
+class ShutdownTag : public internal::CompletionQueueTag {
+ public:
+  bool FinalizeResult(void** tag, bool* status) { return false; }
+};
+
+class DummyTag : public internal::CompletionQueueTag {
+ public:
+  bool FinalizeResult(void** tag, bool* status) {
+    *status = true;
+    return true;
+  }
+};
+
+class UnimplementedAsyncRequestContext {
  protected:
   UnimplementedAsyncRequestContext() : generic_stream_(&server_context_) {}
 
@@ -70,8 +84,14 @@
   GenericServerAsyncReaderWriter generic_stream_;
 };
 
+}  // namespace
+
+/// Use private inheritance rather than composition only to establish order
+/// of construction, since the public base class should be constructed after the
+/// elements belonging to the private base class are constructed. This is not
+/// possible using true composition.
 class Server::UnimplementedAsyncRequest final
-    : public UnimplementedAsyncRequestContext,
+    : private UnimplementedAsyncRequestContext,
       public GenericAsyncRequest {
  public:
   UnimplementedAsyncRequest(Server* server, ServerCompletionQueue* cq)
@@ -90,38 +110,27 @@
   ServerCompletionQueue* const cq_;
 };
 
-typedef internal::SneakyCallOpSet<internal::CallOpSendInitialMetadata,
-                                  internal::CallOpServerSendStatus>
-    UnimplementedAsyncResponseOp;
+/// UnimplementedAsyncResponse should not post user-visible completions to the
+/// C++ completion queue, but is generated as a CQ event by the core
 class Server::UnimplementedAsyncResponse final
-    : public UnimplementedAsyncResponseOp {
+    : public internal::CallOpSet<internal::CallOpSendInitialMetadata,
+                                 internal::CallOpServerSendStatus> {
  public:
   UnimplementedAsyncResponse(UnimplementedAsyncRequest* request);
   ~UnimplementedAsyncResponse() { delete request_; }
 
   bool FinalizeResult(void** tag, bool* status) override {
-    bool r = UnimplementedAsyncResponseOp::FinalizeResult(tag, status);
+    internal::CallOpSet<
+        internal::CallOpSendInitialMetadata,
+        internal::CallOpServerSendStatus>::FinalizeResult(tag, status);
     delete this;
-    return r;
+    return false;
   }
 
  private:
   UnimplementedAsyncRequest* const request_;
 };
 
-class ShutdownTag : public internal::CompletionQueueTag {
- public:
-  bool FinalizeResult(void** tag, bool* status) { return false; }
-};
-
-class DummyTag : public internal::CompletionQueueTag {
- public:
-  bool FinalizeResult(void** tag, bool* status) {
-    *status = true;
-    return true;
-  }
-};
-
 class Server::SyncRequest final : public internal::CompletionQueueTag {
  public:
   SyncRequest(internal::RpcServiceMethod* method, void* tag)
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index e7b30cd..abe19a6 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -160,8 +160,17 @@
             var deadlineTimespec = deadline.HasValue ? Timespec.FromDateTime(deadline.Value) : Timespec.InfFuture;
             lock (myLock)
             {
-                // pass "tcs" as "state" for WatchConnectivityStateHandler.
-                handle.WatchConnectivityState(lastObservedState, deadlineTimespec, completionQueue, WatchConnectivityStateHandler, tcs);
+                if (handle.IsClosed)
+                {
+                    // If channel has been already shutdown and handle was disposed, we would end up with
+                    // an abandoned completion added to the completion registry. Instead, we make sure we fail early.
+                    throw new ObjectDisposedException(nameof(handle), "Channel handle has already been disposed.");
+                }
+                else
+                {
+                    // pass "tcs" as "state" for WatchConnectivityStateHandler.
+                    handle.WatchConnectivityState(lastObservedState, deadlineTimespec, completionQueue, WatchConnectivityStateHandler, tcs);
+                }
             }
             return tcs.Task;
         }
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index 9e9db1f..6e17d9a 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -8,7 +8,6 @@
 
 # Install the dependencies in the main target plus all test targets.
 %w(
-  Tests
   AllTests
   RxLibraryUnitTests
   InteropTestsRemote
@@ -44,10 +43,8 @@
   target target_name do
     pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
     pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
-    pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
-    pod 'gRPC-Core/Cronet-Interface', :path => GRPC_LOCAL_SRC
     pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC
-    pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC
+    pod 'gRPC-Core/Cronet-Tests', :path => GRPC_LOCAL_SRC
   end
 end
 
diff --git a/src/objective-c/tests/analyze_link_map.py b/src/objective-c/tests/analyze_link_map.py
new file mode 100755
index 0000000..48e3441
--- /dev/null
+++ b/src/objective-c/tests/analyze_link_map.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+# Copyright 2018 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 script analyzes link map file generated by Xcode. It calculates and
+# prints out the sizes of each dependent library and the total sizes of the
+# symbols.
+# The script takes one parameter, which is the path to the link map file.
+
+import sys
+import re
+
+table_tag = {}
+state = "start"
+
+table_stats_symbol = {}
+table_stats_dead = {}
+section_total_size = 0
+symbol_total_size = 0
+
+
+file_import = sys.argv[1]
+lines = list(open(file_import))
+for line in lines:
+  line_stripped = line[:-1]
+  if "# Object files:" == line_stripped:
+    state = "object"
+    continue
+  elif "# Sections:" == line_stripped:
+    state = "section"
+    continue
+  elif "# Symbols:" == line_stripped:
+    state = "symbol"
+    continue
+  elif "# Dead Stripped Symbols:" == line_stripped:
+    state = "dead"
+    continue
+
+  if state == "object":
+    segs = re.search('(\[ *[0-9]*\]) (.*)', line_stripped)
+    table_tag[segs.group(1)] = segs.group(2)
+
+  if state == "section":
+    if len(line_stripped) == 0 or line_stripped[0] == '#':
+      continue
+    segs = re.search('^(.+?)\s+(.+?)\s+.*', line_stripped)
+    section_total_size += int(segs.group(2), 16)
+
+  if state == "symbol":
+    if len(line_stripped) == 0 or line_stripped[0] == '#':
+      continue
+    segs = re.search('^.+?\s+(.+?)\s+(\[.+?\]).*', line_stripped)
+    target = table_tag[segs.group(2)]
+    target_stripped = re.search('^(.*?)(\(.+?\))?$', target).group(1)
+    size = int(segs.group(1), 16)
+    if not target_stripped in table_stats_symbol:
+      table_stats_symbol[target_stripped] = 0
+    table_stats_symbol[target_stripped] += size
+
+print("Sections total size: %d" % section_total_size)
+
+for target in table_stats_symbol:
+  print(target)
+  print(table_stats_symbol[target])
+  symbol_total_size += table_stats_symbol[target]
+
+print("Symbols total size: %d" % symbol_total_size)
diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD
index b8e9a22..58412ed 100644
--- a/src/proto/grpc/testing/BUILD
+++ b/src/proto/grpc/testing/BUILD
@@ -26,7 +26,7 @@
 grpc_proto_library(
     name = "compiler_test_proto",
     srcs = ["compiler_test.proto"],
-    generate_mock = True,
+    generate_mocks = True,
 )
 
 grpc_proto_library(
@@ -49,7 +49,7 @@
     name = "echo_proto",
     srcs = ["echo.proto"],
     deps = ["echo_messages_proto"],
-    generate_mock = True,
+    generate_mocks = True,
 )
 
 grpc_proto_library(
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
index 0892215..2e02111 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
@@ -30,9 +30,12 @@
         tag, operations, self if retain_self else None)
     batch_operation_tag.prepare()
     cpython.Py_INCREF(batch_operation_tag)
-    return grpc_call_start_batch(
+    cdef grpc_call_error error
+    with nogil:
+      error = grpc_call_start_batch(
           self.c_call, batch_operation_tag.c_ops, batch_operation_tag.c_nops,
           <cpython.PyObject *>batch_operation_tag, NULL)
+    return error
 
   def start_client_batch(self, operations, tag):
     # We don't reference this call in the operations tag because
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 9807300..8e815fb 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -321,6 +321,9 @@
     'src/core/ext/filters/deadline/deadline_filter.cc',
     'src/core/tsi/alts_transport_security.cc',
     'src/core/tsi/fake_transport_security.cc',
+    'src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc',
+    'src/core/tsi/ssl/session_cache/ssl_session_cache.cc',
+    'src/core/tsi/ssl/session_cache/ssl_session_openssl.cc',
     'src/core/tsi/ssl_transport_security.cc',
     'src/core/tsi/transport_security_grpc.cc',
     'src/core/ext/transport/chttp2/server/chttp2_server.cc',
diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json
index bbbc3ea..d38ee51 100644
--- a/src/python/grpcio_tests/tests/tests.json
+++ b/src/python/grpcio_tests/tests/tests.json
@@ -38,168 +38,6 @@
   "unit._cython.cygrpc_test.InsecureServerInsecureClient",
   "unit._cython.cygrpc_test.SecureServerSecureClient",
   "unit._cython.cygrpc_test.TypeSmokeTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyEmptyRequestsZeroReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManyLargeRequestsZeroReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ManySmallRequestsZeroReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoEmptyRequestsZeroReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoLargeRequestsZeroReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.TwoSmallRequestsZeroReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroEmptyRequestsZeroReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroLargeRequestsZeroReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsTwoReadZeroSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadManyEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadManyLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadManySmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadTwoLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadTwoSmallResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadZeroLargeResponsesEarlyOKTest",
-  "unit._early_ok_test.ZeroSmallRequestsZeroReadZeroSmallResponsesEarlyOKTest",
   "unit._empty_message_test.EmptyMessageTest",
   "unit._exit_test.ExitTest",
   "unit._interceptor_test.InterceptorTest",
diff --git a/src/python/grpcio_tests/tests/unit/_auth_context_test.py b/src/python/grpcio_tests/tests/unit/_auth_context_test.py
index 468869a..8c1a30e 100644
--- a/src/python/grpcio_tests/tests/unit/_auth_context_test.py
+++ b/src/python/grpcio_tests/tests/unit/_auth_context_test.py
@@ -102,7 +102,8 @@
         self.assertIsNone(auth_data[_ID])
         self.assertIsNone(auth_data[_ID_KEY])
         self.assertDictEqual({
-            'transport_security_type': [b'ssl']
+            'transport_security_type': [b'ssl'],
+            'ssl_session_reused': [b'false'],
         }, auth_data[_AUTH_CTX])
 
     def testSecureClientCert(self):
diff --git a/src/python/grpcio_tests/tests/unit/_compression_test.py b/src/python/grpcio_tests/tests/unit/_compression_test.py
index da1996b..7550cd3 100644
--- a/src/python/grpcio_tests/tests/unit/_compression_test.py
+++ b/src/python/grpcio_tests/tests/unit/_compression_test.py
@@ -32,10 +32,12 @@
 
 
 def handle_stream(request_iterator, servicer_context):
+    # TODO(issue:#6891) We should be able to remove this loop,
+    # and replace with return; yield
     servicer_context.send_initial_metadata([('grpc-internal-encoding-request',
                                              'gzip')])
-    return
-    yield
+    for request in request_iterator:
+        yield request
 
 
 class _MethodHandler(grpc.RpcMethodHandler):
diff --git a/src/python/grpcio_tests/tests/unit/_early_ok_test.py b/src/python/grpcio_tests/tests/unit/_early_ok_test.py
deleted file mode 100644
index 041532c..0000000
--- a/src/python/grpcio_tests/tests/unit/_early_ok_test.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# Copyright 2018 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.
-"""Tests servicers sending OK status without having read all requests.
-
-This is a regression test of https://github.com/grpc/grpc/issues/6891.
-"""
-
-import enum
-import unittest
-
-import six
-
-import grpc
-
-from tests.unit import test_common
-from tests.unit.framework.common import test_constants
-
-_RPC_METHOD = '/serffice/Meffod'
-
-
-@enum.unique
-class _MessageCount(enum.Enum):
-
-    ZERO = (
-        0,
-        'Zero',
-    )
-    TWO = (
-        1,
-        'Two',
-    )
-    MANY = (
-        test_constants.STREAM_LENGTH,
-        'Many',
-    )
-
-
-@enum.unique
-class _MessageSize(enum.Enum):
-    EMPTY = (
-        0,
-        'Empty',
-    )
-    SMALL = (
-        32,
-        'Small',
-    )  # Smaller than any flow control window.
-    LARGE = (
-        3 * 1024 * 1024,
-        'Large',
-    )  # Larger than any flow control window.
-
-
-_ZERO_MESSAGE = b''
-_SMALL_MESSAGE = b'\x07' * _MessageSize.SMALL.value[0]
-_LARGE_MESSAGE = b'abc' * (_MessageSize.LARGE.value[0] // 3)
-
-
-@enum.unique
-class _ReadRequests(enum.Enum):
-
-    ZERO = (
-        0,
-        'Zero',
-    )
-    TWO = (
-        2,
-        'Two',
-    )
-
-
-class _Case(object):
-
-    def __init__(self, request_count, request_size, request_reading,
-                 response_count, response_size):
-        self.request_count = request_count
-        self.request_size = request_size
-        self.request_reading = request_reading
-        self.response_count = response_count
-        self.response_size = response_size
-
-    def create_test_case_name(self):
-        return '{}{}Requests{}Read{}{}ResponsesEarlyOKTest'.format(
-            self.request_count.value[1], self.request_size.value[1],
-            self.request_reading.value[1], self.response_count.value[1],
-            self.response_size.value[1])
-
-
-def _message(message_size):
-    if message_size is _MessageSize.EMPTY:
-        return _ZERO_MESSAGE
-    elif message_size is _MessageSize.SMALL:
-        return _SMALL_MESSAGE
-    elif message_size is _MessageSize.LARGE:
-        return _LARGE_MESSAGE
-
-
-def _messages_to_send(count, size):
-    for _ in range(count.value[0]):
-        yield _message(size)
-
-
-def _draw_requests(case, request_iterator):
-    for _ in range(
-            min(case.request_count.value[0], case.request_reading.value[0])):
-        next(request_iterator)
-
-
-def _draw_responses(case, response_iterator):
-    for _ in range(case.response_count.value[0]):
-        next(response_iterator)
-
-
-class _MethodHandler(grpc.RpcMethodHandler):
-
-    def __init__(self, case):
-        self.request_streaming = True
-        self.response_streaming = True
-        self.request_deserializer = None
-        self.response_serializer = None
-        self.unary_unary = None
-        self.unary_stream = None
-        self.stream_unary = None
-        self._case = case
-
-    def stream_stream(self, request_iterator, servicer_context):
-        _draw_requests(self._case, request_iterator)
-
-        for response in _messages_to_send(self._case.response_count,
-                                          self._case.response_size):
-            yield response
-
-
-class _GenericHandler(grpc.GenericRpcHandler):
-
-    def __init__(self, case):
-        self._case = case
-
-    def service(self, handler_call_details):
-        return _MethodHandler(self._case)
-
-
-class _EarlyOkTest(unittest.TestCase):
-
-    def setUp(self):
-        self._server = test_common.test_server()
-        port = self._server.add_insecure_port('[::]:0')
-        self._server.add_generic_rpc_handlers((_GenericHandler(self.case),))
-        self._server.start()
-
-        self._channel = grpc.insecure_channel('localhost:%d' % port)
-        self._multi_callable = self._channel.stream_stream(_RPC_METHOD)
-
-    def tearDown(self):
-        self._server.stop(None)
-
-    def test_early_ok(self):
-        requests = _messages_to_send(self.case.request_count,
-                                     self.case.request_size)
-
-        response_iterator_call = self._multi_callable(requests)
-
-        _draw_responses(self.case, response_iterator_call)
-
-        self.assertIs(grpc.StatusCode.OK, response_iterator_call.code())
-
-
-def _cases():
-    for request_count in _MessageCount:
-        for request_size in _MessageSize:
-            for request_reading in _ReadRequests:
-                for response_count in _MessageCount:
-                    for response_size in _MessageSize:
-                        yield _Case(request_count, request_size,
-                                    request_reading, response_count,
-                                    response_size)
-
-
-def _test_case_classes():
-    for case in _cases():
-        yield type(case.create_test_case_name(), (_EarlyOkTest,), {
-            'case': case,
-            '__module__': _EarlyOkTest.__module__,
-        })
-
-
-def load_tests(loader, tests, pattern):
-    return unittest.TestSuite(
-        tests=tuple(
-            loader.loadTestsFromTestCase(test_case_class)
-            for test_case_class in _test_case_classes()))
-
-
-if __name__ == '__main__':
-    unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py
index a6cdf32..ca10bd4 100644
--- a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py
+++ b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py
@@ -107,6 +107,9 @@
             self._received_client_metadata = context.invocation_metadata()
             context.send_initial_metadata(_SERVER_INITIAL_METADATA)
             context.set_trailing_metadata(_SERVER_TRAILING_METADATA)
+            # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the
+            # request iterator.
+            list(request_iterator)
             if self._abort_call:
                 context.abort(self._code, self._details)
             else:
@@ -124,6 +127,9 @@
             self._received_client_metadata = context.invocation_metadata()
             context.send_initial_metadata(_SERVER_INITIAL_METADATA)
             context.set_trailing_metadata(_SERVER_TRAILING_METADATA)
+            # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the
+            # request iterator.
+            list(request_iterator)
             if self._abort_call:
                 context.abort(self._code, self._details)
             else:
diff --git a/src/python/grpcio_tests/tests/unit/_metadata_test.py b/src/python/grpcio_tests/tests/unit/_metadata_test.py
index 2309eeb..5908421 100644
--- a/src/python/grpcio_tests/tests/unit/_metadata_test.py
+++ b/src/python/grpcio_tests/tests/unit/_metadata_test.py
@@ -117,6 +117,9 @@
     validate_client_metadata(test, servicer_context)
     servicer_context.send_initial_metadata(_INITIAL_METADATA)
     servicer_context.set_trailing_metadata(_TRAILING_METADATA)
+    # TODO(issue:#6891) We should be able to remove this loop
+    for request in request_iterator:
+        pass
     return _RESPONSE
 
 
@@ -124,8 +127,10 @@
     validate_client_metadata(test, servicer_context)
     servicer_context.send_initial_metadata(_INITIAL_METADATA)
     servicer_context.set_trailing_metadata(_TRAILING_METADATA)
-    return
-    yield
+    # TODO(issue:#6891) We should be able to remove this loop,
+    # and replace with return; yield
+    for request in request_iterator:
+        yield _RESPONSE
 
 
 class _MethodHandler(grpc.RpcMethodHandler):
diff --git a/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py b/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py
index e35f8f1..df4b129 100644
--- a/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py
+++ b/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py
@@ -77,13 +77,18 @@
 
 def handle_stream_unary(trigger, request_iterator, servicer_context):
     trigger.await_trigger()
+    # TODO(issue:#6891) We should be able to remove this loop
+    for request in request_iterator:
+        pass
     return _RESPONSE
 
 
 def handle_stream_stream(trigger, request_iterator, servicer_context):
     trigger.await_trigger()
-    return
-    yield
+    # TODO(issue:#6891) We should be able to remove this loop,
+    # and replace with return; yield
+    for request in request_iterator:
+        yield _RESPONSE
 
 
 class _MethodHandler(grpc.RpcMethodHandler):
diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb
index c1a0c56..e8e87e4 100644
--- a/src/ruby/ext/grpc/extconf.rb
+++ b/src/ruby/ext/grpc/extconf.rb
@@ -94,7 +94,6 @@
 $CFLAGS << ' -Wall '
 $CFLAGS << ' -Wextra '
 $CFLAGS << ' -pedantic '
-$CFLAGS << ' -Wno-format '
 
 output = File.join('grpc', 'grpc_c')
 puts 'Generating Makefile for ' + output
diff --git a/src/ruby/ext/grpc/rb_compression_options.c b/src/ruby/ext/grpc/rb_compression_options.c
index 7fdec2e..4ba6991 100644
--- a/src/ruby/ext/grpc/rb_compression_options.c
+++ b/src/ruby/ext/grpc/rb_compression_options.c
@@ -186,7 +186,7 @@
     error_message_ruby_str =
         rb_str_new(error_message_str, strlen(error_message_str));
     gpr_free(error_message_str);
-    rb_raise(rb_eNameError, StringValueCStr(error_message_ruby_str));
+    rb_raise(rb_eNameError, "%s", StringValueCStr(error_message_ruby_str));
   }
 
   grpc_slice_unref(name_slice);
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 1c04273..a12819e 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -108,6 +108,9 @@
 grpc_auth_context_add_property_type grpc_auth_context_add_property_import;
 grpc_auth_context_add_cstring_property_type grpc_auth_context_add_cstring_property_import;
 grpc_auth_context_set_peer_identity_property_name_type grpc_auth_context_set_peer_identity_property_name_import;
+grpc_ssl_session_cache_create_lru_type grpc_ssl_session_cache_create_lru_import;
+grpc_ssl_session_cache_destroy_type grpc_ssl_session_cache_destroy_import;
+grpc_ssl_session_cache_create_channel_arg_type grpc_ssl_session_cache_create_channel_arg_import;
 grpc_channel_credentials_release_type grpc_channel_credentials_release_import;
 grpc_google_default_credentials_create_type grpc_google_default_credentials_create_import;
 grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import;
@@ -346,6 +349,9 @@
   grpc_auth_context_add_property_import = (grpc_auth_context_add_property_type) GetProcAddress(library, "grpc_auth_context_add_property");
   grpc_auth_context_add_cstring_property_import = (grpc_auth_context_add_cstring_property_type) GetProcAddress(library, "grpc_auth_context_add_cstring_property");
   grpc_auth_context_set_peer_identity_property_name_import = (grpc_auth_context_set_peer_identity_property_name_type) GetProcAddress(library, "grpc_auth_context_set_peer_identity_property_name");
+  grpc_ssl_session_cache_create_lru_import = (grpc_ssl_session_cache_create_lru_type) GetProcAddress(library, "grpc_ssl_session_cache_create_lru");
+  grpc_ssl_session_cache_destroy_import = (grpc_ssl_session_cache_destroy_type) GetProcAddress(library, "grpc_ssl_session_cache_destroy");
+  grpc_ssl_session_cache_create_channel_arg_import = (grpc_ssl_session_cache_create_channel_arg_type) GetProcAddress(library, "grpc_ssl_session_cache_create_channel_arg");
   grpc_channel_credentials_release_import = (grpc_channel_credentials_release_type) GetProcAddress(library, "grpc_channel_credentials_release");
   grpc_google_default_credentials_create_import = (grpc_google_default_credentials_create_type) GetProcAddress(library, "grpc_google_default_credentials_create");
   grpc_set_ssl_roots_override_callback_import = (grpc_set_ssl_roots_override_callback_type) GetProcAddress(library, "grpc_set_ssl_roots_override_callback");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 9a09321..089cb8a 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -299,6 +299,15 @@
 typedef int(*grpc_auth_context_set_peer_identity_property_name_type)(grpc_auth_context* ctx, const char* name);
 extern grpc_auth_context_set_peer_identity_property_name_type grpc_auth_context_set_peer_identity_property_name_import;
 #define grpc_auth_context_set_peer_identity_property_name grpc_auth_context_set_peer_identity_property_name_import
+typedef grpc_ssl_session_cache*(*grpc_ssl_session_cache_create_lru_type)(size_t capacity);
+extern grpc_ssl_session_cache_create_lru_type grpc_ssl_session_cache_create_lru_import;
+#define grpc_ssl_session_cache_create_lru grpc_ssl_session_cache_create_lru_import
+typedef void(*grpc_ssl_session_cache_destroy_type)(grpc_ssl_session_cache* cache);
+extern grpc_ssl_session_cache_destroy_type grpc_ssl_session_cache_destroy_import;
+#define grpc_ssl_session_cache_destroy grpc_ssl_session_cache_destroy_import
+typedef grpc_arg(*grpc_ssl_session_cache_create_channel_arg_type)(grpc_ssl_session_cache* cache);
+extern grpc_ssl_session_cache_create_channel_arg_type grpc_ssl_session_cache_create_channel_arg_import;
+#define grpc_ssl_session_cache_create_channel_arg grpc_ssl_session_cache_create_channel_arg_import
 typedef void(*grpc_channel_credentials_release_type)(grpc_channel_credentials* creds);
 extern grpc_channel_credentials_release_type grpc_channel_credentials_release_import;
 #define grpc_channel_credentials_release grpc_channel_credentials_release_import
diff --git a/summerofcode/ideas.md b/summerofcode/ideas.md
index 4052972..de59be8 100644
--- a/summerofcode/ideas.md
+++ b/summerofcode/ideas.md
@@ -17,6 +17,10 @@
 
 gRPC Core:
 
+1. Implement ["early OK" semantics](https://github.com/grpc/grpc/issues/7032). The gRPC wire protocol allows servers to complete an RPC with OK status without having processed all requests ever sent to the client; it's the gRPC Core that currently restricts applications from so behaving. This behavioral gap in the gRPC Core should be filled in.
+    * **Required skills:** C programming language, C++ programming language.
+    * **Likely mentors:** [Nathaniel Manista](https://github.com/nathanielmanistaatgoogle), [Nicolas Noble](https://github.com/nicolasnoble).
+
 1. [Make channel-connectivity-watching cancellable](https://github.com/grpc/grpc/issues/3064). Anything worth waiting for is worth cancelling. The fact that channel connectivity is currently poll-based means that clean shutdown of gRPC channels can take as long as the poll interval. No one should have to wait two hundred milliseconds to garbage-collect an object.
     * **Required skills:** C programming language, C++ programming language, Python programming language.
     * **Likely mentors:** [Nathaniel Manista](https://github.com/nathanielmanistaatgoogle), [Vijay Pai](https://github.com/vjpai).
diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template
index af97d81..33a8a8b 100644
--- a/templates/gRPC-Core.podspec.template
+++ b/templates/gRPC-Core.podspec.template
@@ -42,21 +42,21 @@
     out = grpc_lib_files(libs, ("grpc", "gpr"), ("headers",))
     return [file for file in out if not file.startswith("third_party/nanopb/")]
 
-  def grpc_cronet_files(libs):
-    out = grpc_lib_files(libs, ("grpc_cronet",), ("src", "headers"))
-    excl = grpc_private_files(libs)
-    excl += [
-        # We do not need cronet dedicated plugin registry
-        "src/core/plugin_registry/grpc_cronet_plugin_registry.cc",
-        # We do not need dummy cronet API for ObjC
+  def grpc_cronet_private_files(libs):
+    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("headers", "src"))
+    excl = [
+        # We do not want dummy cronet API for ObjC
         "src/core/ext/transport/cronet/transport/cronet_api_dummy.cc",
     ]
     return [file for file in out if not file in excl]
 
   def grpc_cronet_public_headers(libs):
-    out = grpc_lib_files(libs, ("grpc_cronet",), ("public_headers",))
-    excl = grpc_public_headers(libs)
-    return [file for file in out if not file in excl]
+    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("public_headers",))
+    return out
+
+  def grpc_cronet_private_headers(libs):
+    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("headers",))
+    return out
 
   def grpc_test_util_files(libs):
     out = grpc_lib_files(libs, ("grpc_test_util", "gpr_test_util"), ("src", "headers"))
@@ -169,7 +169,6 @@
       ss.dependency 'BoringSSL', '~> 10.0'
       ss.dependency 'nanopb', '~> 0.3'
 
-      # To save you from scrolling, this is the last part of the podspec.
       ss.source_files = ${ruby_multiline_list(grpc_private_files(libs), 22)}
 
       ss.private_header_files = ${ruby_multiline_list(grpc_private_headers(libs), 30)}
@@ -182,19 +181,21 @@
 
     s.subspec 'Cronet-Implementation' do |ss|
       ss.header_mappings_dir = '.'
-
-      ss.dependency "#{s.name}/Interface", version
-      ss.dependency "#{s.name}/Implementation", version
+      ss.libraries = 'z'
       ss.dependency "#{s.name}/Cronet-Interface", version
+      ss.dependency 'BoringSSL', '~> 10.0'
+      ss.dependency 'nanopb', '~> 0.3'
 
-      ss.source_files = ${ruby_multiline_list(grpc_cronet_files(libs), 22)}
+      ss.source_files = ${ruby_multiline_list(grpc_cronet_private_files(libs), 22)}
+
+      ss.private_header_files = ${ruby_multiline_list(grpc_cronet_private_headers(libs), 30)}
     end
 
-    s.subspec 'Tests' do |ss|
+    s.subspec 'Cronet-Tests' do |ss|
       ss.header_mappings_dir = '.'
 
-      ss.dependency "#{s.name}/Interface", version
-      ss.dependency "#{s.name}/Implementation", version
+      ss.dependency "#{s.name}/Cronet-Interface", version
+      ss.dependency "#{s.name}/Cronet-Implementation", version
 
       ss.source_files = ${ruby_multiline_list(grpc_test_util_files(libs), 22)},
                         ${ruby_multiline_list(end2end_tests_files(libs), 22)}
diff --git a/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
new file mode 100644
index 0000000..1bbfdfd
--- /dev/null
+++ b/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
@@ -0,0 +1,57 @@
+%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.
+  
+  FROM alpine:3.5
+  
+  # Install Git and basic packages.
+  RUN apk update && apk add ${'\\'}
+    autoconf ${'\\'}
+    automake ${'\\'}
+    bzip2 ${'\\'}
+    build-base ${'\\'}
+    cmake ${'\\'}
+    ccache ${'\\'}
+    curl ${'\\'}
+    gcc ${'\\'}
+    git ${'\\'}
+    libtool ${'\\'}
+    linux-headers ${'\\'}
+    make ${'\\'}
+    perl ${'\\'}
+    strace ${'\\'}
+    python-dev ${'\\'}
+    py-pip ${'\\'}
+    unzip ${'\\'}
+    wget ${'\\'}
+    zip
+  
+  # Install Python packages from PyPI
+  RUN pip install --upgrade pip==9.0.1
+  RUN pip install virtualenv
+  RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+  
+  # Google Cloud platform API libraries
+  RUN pip install --upgrade google-api-python-client
+  
+  # Install gflags
+  RUN git clone https://github.com/gflags/gflags.git && cd gflags && git checkout v2.2.0
+  RUN cd gflags && cmake . && make && make install
+  RUN ln -s /usr/local/include/gflags /usr/include/gflags
+  
+  <%include file="../../run_tests_addons.include"/>
+  
+  # Define the default command.
+  CMD ["bash"]
diff --git a/test/core/end2end/BUILD b/test/core/end2end/BUILD
index 952f350..dd16694 100644
--- a/test/core/end2end/BUILD
+++ b/test/core/end2end/BUILD
@@ -163,3 +163,20 @@
 )
 
 grpc_end2end_tests()
+
+grpc_cc_test(
+    name = "h2_ssl_session_reuse_test",
+    srcs = ["h2_ssl_session_reuse_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    deps = [
+        ':end2end_tests',
+        '//:gpr',
+        '//:grpc',
+        '//:tsi',
+        '//test/core/util:gpr_test_util',
+        '//test/core/util:grpc_test_util',
+    ],
+)
diff --git a/test/core/end2end/goaway_server_test.cc b/test/core/end2end/goaway_server_test.cc
index 8ff14e2..0188698 100644
--- a/test/core/end2end/goaway_server_test.cc
+++ b/test/core/end2end/goaway_server_test.cc
@@ -82,7 +82,7 @@
     sa->sin_family = GRPC_AF_INET;
     sa->sin_addr.s_addr = 0x100007f;
     sa->sin_port = grpc_htons(static_cast<uint16_t>(g_resolve_port));
-    (*addrs)->addrs[0].len = sizeof(*sa);
+    (*addrs)->addrs[0].len = static_cast<socklen_t>(sizeof(*sa));
     gpr_mu_unlock(&g_mu);
   }
   GRPC_CLOSURE_SCHED(on_done, error);
diff --git a/test/core/end2end/h2_ssl_session_reuse_test.cc b/test/core/end2end/h2_ssl_session_reuse_test.cc
new file mode 100644
index 0000000..d5984be
--- /dev/null
+++ b/test/core/end2end/h2_ssl_session_reuse_test.cc
@@ -0,0 +1,280 @@
+/*
+ *
+ * Copyright 2018 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 "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/host_port.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gpr/tmpfile.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "test/core/end2end/cq_verifier.h"
+#include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+#include <gtest/gtest.h>
+
+namespace grpc {
+namespace testing {
+namespace {
+
+void* tag(intptr_t t) { return (void*)t; }
+
+gpr_timespec five_seconds_time() { return grpc_timeout_seconds_to_deadline(5); }
+
+grpc_server* server_create(grpc_completion_queue* cq, char* server_addr) {
+  grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key,
+                                                  test_server1_cert};
+  grpc_server_credentials* server_creds = grpc_ssl_server_credentials_create_ex(
+      test_root_cert, &pem_cert_key_pair, 1,
+      GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, nullptr);
+
+  grpc_server* server = grpc_server_create(nullptr, nullptr);
+  grpc_server_register_completion_queue(server, cq, nullptr);
+  GPR_ASSERT(
+      grpc_server_add_secure_http2_port(server, server_addr, server_creds));
+  grpc_server_credentials_release(server_creds);
+  grpc_server_start(server);
+
+  return server;
+}
+
+grpc_channel* client_create(char* server_addr, grpc_ssl_session_cache* cache) {
+  grpc_ssl_pem_key_cert_pair signed_client_key_cert_pair = {
+      test_signed_client_key, test_signed_client_cert};
+  grpc_channel_credentials* client_creds = grpc_ssl_credentials_create(
+      test_root_cert, &signed_client_key_cert_pair, nullptr);
+
+  grpc_arg args[] = {
+      grpc_channel_arg_string_create(
+          const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
+          const_cast<char*>("waterzooi.test.google.be")),
+      grpc_ssl_session_cache_create_channel_arg(cache),
+  };
+
+  grpc_channel_args* client_args =
+      grpc_channel_args_copy_and_add(nullptr, args, GPR_ARRAY_SIZE(args));
+
+  grpc_channel* client = grpc_secure_channel_create(client_creds, server_addr,
+                                                    client_args, nullptr);
+  GPR_ASSERT(client != nullptr);
+  grpc_channel_credentials_release(client_creds);
+
+  {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_channel_args_destroy(client_args);
+  }
+
+  return client;
+}
+
+void do_round_trip(grpc_completion_queue* cq, grpc_server* server,
+                   char* server_addr, grpc_ssl_session_cache* cache,
+                   bool expect_session_reuse) {
+  grpc_channel* client = client_create(server_addr, cache);
+
+  cq_verifier* cqv = cq_verifier_create(cq);
+  grpc_op ops[6];
+  grpc_op* op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  grpc_slice details;
+  int was_cancelled = 2;
+
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(60);
+  grpc_call* c = grpc_channel_create_call(
+      client, nullptr, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr);
+  GPR_ASSERT(c);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  grpc_call* s;
+  error = grpc_server_request_call(server, &s, &call_details,
+                                   &request_metadata_recv, cq, cq, tag(101));
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+  cq_verify(cqv);
+
+  grpc_auth_context* auth = grpc_call_auth_context(s);
+  grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
+      auth, GRPC_SSL_SESSION_REUSED_PROPERTY);
+  const grpc_auth_property* property = grpc_auth_property_iterator_next(&it);
+  GPR_ASSERT(property != nullptr);
+
+  if (expect_session_reuse) {
+    GPR_ASSERT(strcmp(property->value, "true") == 0);
+  } else {
+    GPR_ASSERT(strcmp(property->value, "false") == 0);
+  }
+  grpc_auth_context_release(auth);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_OK;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(103),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
+  CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  grpc_call_unref(c);
+  grpc_call_unref(s);
+
+  cq_verifier_destroy(cqv);
+
+  grpc_channel_destroy(client);
+}
+
+void drain_cq(grpc_completion_queue* cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_time(), nullptr);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+TEST(H2SessionReuseTest, SingleReuse) {
+  int port = grpc_pick_unused_port_or_die();
+
+  char* server_addr;
+  gpr_join_host_port(&server_addr, "localhost", port);
+
+  grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
+  grpc_ssl_session_cache* cache = grpc_ssl_session_cache_create_lru(16);
+
+  grpc_server* server = server_create(cq, server_addr);
+
+  do_round_trip(cq, server, server_addr, cache, false);
+  do_round_trip(cq, server, server_addr, cache, true);
+  do_round_trip(cq, server, server_addr, cache, true);
+
+  gpr_free(server_addr);
+  grpc_ssl_session_cache_destroy(cache);
+
+  GPR_ASSERT(grpc_completion_queue_next(
+                 cq, grpc_timeout_milliseconds_to_deadline(100), nullptr)
+                 .type == GRPC_QUEUE_TIMEOUT);
+
+  grpc_completion_queue* shutdown_cq =
+      grpc_completion_queue_create_for_pluck(nullptr);
+  grpc_server_shutdown_and_notify(server, shutdown_cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, tag(1000),
+                                         grpc_timeout_seconds_to_deadline(5),
+                                         nullptr)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(server);
+  grpc_completion_queue_destroy(shutdown_cq);
+
+  grpc_completion_queue_shutdown(cq);
+  drain_cq(cq);
+  grpc_completion_queue_destroy(cq);
+}
+
+}  // namespace
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  FILE* roots_file;
+  size_t roots_size = strlen(test_root_cert);
+  char* roots_filename;
+
+  grpc_test_init(argc, argv);
+  /* Set the SSL roots env var. */
+  roots_file = gpr_tmpfile("chttp2_ssl_session_reuse_test", &roots_filename);
+  GPR_ASSERT(roots_filename != nullptr);
+  GPR_ASSERT(roots_file != nullptr);
+  GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size);
+  fclose(roots_file);
+  gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename);
+
+  grpc_init();
+  ::testing::InitGoogleTest(&argc, argv);
+  int ret = RUN_ALL_TESTS();
+  grpc_shutdown();
+
+  /* Cleanup. */
+  remove(roots_filename);
+  gpr_free(roots_filename);
+
+  return ret;
+}
diff --git a/test/core/end2end/no_server_test.cc b/test/core/end2end/no_server_test.cc
index 6113885..e8ce403 100644
--- a/test/core/end2end/no_server_test.cc
+++ b/test/core/end2end/no_server_test.cc
@@ -22,45 +22,47 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
+#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
 #include "test/core/end2end/cq_verifier.h"
 #include "test/core/util/test_config.h"
 
 static void* tag(intptr_t i) { return (void*)i; }
 
-int main(int argc, char** argv) {
-  grpc_channel* chan;
-  grpc_call* call;
-  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2);
-  grpc_completion_queue* cq;
-  cq_verifier* cqv;
-  grpc_op ops[6];
-  grpc_op* op;
-  grpc_metadata_array trailing_metadata_recv;
-  grpc_status_code status;
-  grpc_slice details;
+void run_test(bool wait_for_ready) {
+  gpr_log(GPR_INFO, "TEST: wait_for_ready=%d", wait_for_ready);
 
-  grpc_test_init(argc, argv);
   grpc_init();
 
-  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
+  cq_verifier* cqv = cq_verifier_create(cq);
 
-  cq = grpc_completion_queue_create_for_next(nullptr);
-  cqv = cq_verifier_create(cq);
+  grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
+      response_generator =
+          grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
+  grpc_arg arg = grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
+      response_generator.get());
+  grpc_channel_args args = {1, &arg};
 
   /* create a call, channel to a non existant server */
-  chan = grpc_insecure_channel_create("nonexistant:54321", nullptr, nullptr);
-  grpc_slice host = grpc_slice_from_static_string("nonexistant");
-  call = grpc_channel_create_call(chan, nullptr, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  grpc_slice_from_static_string("/Foo"), &host,
-                                  deadline, nullptr);
+  grpc_channel* chan =
+      grpc_insecure_channel_create("fake:nonexistant", &args, nullptr);
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(2);
+  grpc_call* call = grpc_channel_create_call(
+      chan, nullptr, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/Foo"), nullptr, deadline, nullptr);
 
+  grpc_op ops[6];
   memset(ops, 0, sizeof(ops));
-  op = ops;
+  grpc_op* op = ops;
   op->op = GRPC_OP_SEND_INITIAL_METADATA;
   op->data.send_initial_metadata.count = 0;
-  op->flags = 0;
+  op->flags = wait_for_ready ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 0;
   op->reserved = nullptr;
   op++;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_status_code status;
+  grpc_slice details;
   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
@@ -71,11 +73,25 @@
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call, ops,
                                                    (size_t)(op - ops), tag(1),
                                                    nullptr));
+
+  {
+    grpc_core::ExecCtx exec_ctx;
+    response_generator->SetFailure();
+  }
+
   /* verify that all tags get completed */
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED);
+  gpr_log(GPR_INFO, "call status: %d", status);
+  if (wait_for_ready) {
+    GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED);
+  } else {
+    GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
+  }
+
+  grpc_slice_unref(details);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
 
   grpc_completion_queue_shutdown(cq);
   while (grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
@@ -87,10 +103,12 @@
   grpc_channel_destroy(chan);
   cq_verifier_destroy(cqv);
 
-  grpc_slice_unref(details);
-  grpc_metadata_array_destroy(&trailing_metadata_recv);
-
   grpc_shutdown();
+}
 
+int main(int argc, char** argv) {
+  grpc_test_init(argc, argv);
+  run_test(true /* wait_for_ready */);
+  run_test(false /* wait_for_ready */);
   return 0;
 }
diff --git a/test/core/end2end/tests/bad_ping.cc b/test/core/end2end/tests/bad_ping.cc
index 95f72ca..239c608 100644
--- a/test/core/end2end/tests/bad_ping.cc
+++ b/test/core/end2end/tests/bad_ping.cc
@@ -28,7 +28,7 @@
 #include "src/core/lib/gpr/useful.h"
 #include "test/core/end2end/cq_verifier.h"
 
-#define MAX_PING_STRIKES 1
+#define MAX_PING_STRIKES 2
 
 static void* tag(intptr_t t) { return (void*)t; }
 
@@ -62,6 +62,7 @@
   grpc_completion_queue_destroy(f->shutdown_cq);
 }
 
+// Send more pings than server allows to trigger server's GOAWAY.
 static void test_bad_ping(grpc_end2end_test_config config) {
   grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr);
   cq_verifier* cqv = cq_verifier_create(f.cq);
@@ -221,9 +222,170 @@
   config.tear_down_data(&f);
 }
 
+// Try sending more pings than server allows, but server should be fine because
+// max_pings_without_data should limit pings sent out on wire.
+static void test_pings_without_data(grpc_end2end_test_config config) {
+  grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr);
+  cq_verifier* cqv = cq_verifier_create(f.cq);
+  grpc_arg client_a[3];
+  client_a[0].type = GRPC_ARG_INTEGER;
+  client_a[0].key =
+      const_cast<char*>(GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS);
+  client_a[0].value.integer = 10;
+  // Only allow MAX_PING_STRIKES pings without data (DATA/HEADERS/WINDOW_UPDATE)
+  // so that the transport will throttle the excess pings.
+  client_a[1].type = GRPC_ARG_INTEGER;
+  client_a[1].key = const_cast<char*>(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA);
+  client_a[1].value.integer = MAX_PING_STRIKES;
+  client_a[2].type = GRPC_ARG_INTEGER;
+  client_a[2].key = const_cast<char*>(GRPC_ARG_HTTP2_BDP_PROBE);
+  client_a[2].value.integer = 0;
+  grpc_arg server_a[3];
+  server_a[0].type = GRPC_ARG_INTEGER;
+  server_a[0].key =
+      const_cast<char*>(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS);
+  server_a[0].value.integer = 300000 /* 5 minutes */;
+  server_a[1].type = GRPC_ARG_INTEGER;
+  server_a[1].key = const_cast<char*>(GRPC_ARG_HTTP2_MAX_PING_STRIKES);
+  server_a[1].value.integer = MAX_PING_STRIKES;
+  server_a[2].type = GRPC_ARG_INTEGER;
+  server_a[2].key = const_cast<char*>(GRPC_ARG_HTTP2_BDP_PROBE);
+  server_a[2].value.integer = 0;
+  grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
+  grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a};
+
+  config.init_client(&f, &client_args);
+  config.init_server(&f, &server_args);
+
+  grpc_call* c;
+  grpc_call* s;
+  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10);
+  grpc_op ops[6];
+  grpc_op* op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  grpc_slice details;
+  int was_cancelled = 2;
+
+  c = grpc_channel_create_call(
+      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
+      nullptr);
+  GPR_ASSERT(c);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->data.send_initial_metadata.metadata = nullptr;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  error =
+      grpc_server_request_call(f.server, &s, &call_details,
+                               &request_metadata_recv, f.cq, f.cq, tag(101));
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+  cq_verify(cqv);
+
+  // Send too many pings to the server similar to the prevous test case.
+  // However, since we set the MAX_PINGS_WITHOUT_DATA at the client side, only
+  // MAX_PING_STRIKES will actually be sent and the rpc will still succeed.
+  int i;
+  for (i = 1; i <= MAX_PING_STRIKES + 2; i++) {
+    grpc_channel_ping(f.client, f.cq, tag(200 + i), nullptr);
+    if (i <= MAX_PING_STRIKES) {
+      CQ_EXPECT_COMPLETION(cqv, tag(200 + i), 1);
+    }
+    cq_verify(cqv);
+  }
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
+                                nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
+  // Client call should return.
+  CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
+  CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1);
+  cq_verify(cqv);
+
+  grpc_call_unref(s);
+
+  // The rpc should be successful.
+  GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
+                                config);
+
+  grpc_slice_unref(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+  grpc_call_unref(c);
+  cq_verifier_destroy(cqv);
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
 void bad_ping(grpc_end2end_test_config config) {
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION);
   test_bad_ping(config);
+  test_pings_without_data(config);
 }
 
 void bad_ping_pre_init(void) {}
diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc
index f0dd061..c0771b8 100644
--- a/test/core/end2end/tests/keepalive_timeout.cc
+++ b/test/core/end2end/tests/keepalive_timeout.cc
@@ -102,7 +102,7 @@
   grpc_arg keepalive_arg_elems[3];
   keepalive_arg_elems[0].type = GRPC_ARG_INTEGER;
   keepalive_arg_elems[0].key = const_cast<char*>(GRPC_ARG_KEEPALIVE_TIME_MS);
-  keepalive_arg_elems[0].value.integer = 1500;
+  keepalive_arg_elems[0].value.integer = 3500;
   keepalive_arg_elems[1].type = GRPC_ARG_INTEGER;
   keepalive_arg_elems[1].key = const_cast<char*>(GRPC_ARG_KEEPALIVE_TIMEOUT_MS);
   keepalive_arg_elems[1].value.integer = 0;
diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc
index b900afa..2a35742 100644
--- a/test/core/gprpp/inlined_vector_test.cc
+++ b/test/core/gprpp/inlined_vector_test.cc
@@ -87,14 +87,17 @@
 }
 
 TEST(InlinedVectorTest, ConstIndexOperator) {
-  const int kNumElements = 10;
+  constexpr int kNumElements = 10;
   InlinedVector<int, 5> v;
   EXPECT_EQ(0UL, v.size());
   for (int i = 0; i < kNumElements; ++i) {
     v.push_back(i);
     EXPECT_EQ(i + 1UL, v.size());
   }
-  auto const_func = [kNumElements](const InlinedVector<int, 5>& v) {
+  // The following lambda function is exceptionally allowed to use an anonymous
+  // capture due to the erroneous behavior of the MSVC compiler, that refuses to
+  // capture the kNumElements constexpr, something allowed by the standard.
+  auto const_func = [&](const InlinedVector<int, 5>& v) {
     for (int i = 0; i < kNumElements; ++i) {
       EXPECT_EQ(i, v[i]);
     }
diff --git a/test/core/iomgr/sockaddr_utils_test.cc b/test/core/iomgr/sockaddr_utils_test.cc
index aa9ece3..3783f96 100644
--- a/test/core/iomgr/sockaddr_utils_test.cc
+++ b/test/core/iomgr/sockaddr_utils_test.cc
@@ -41,7 +41,7 @@
   GPR_ASSERT(data_len == sizeof(addr4->sin_addr.s_addr));
   memcpy(&addr4->sin_addr.s_addr, data, data_len);
   addr4->sin_port = grpc_htons(12345);
-  resolved_addr4.len = sizeof(grpc_sockaddr_in);
+  resolved_addr4.len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
   return resolved_addr4;
 }
 
@@ -54,7 +54,7 @@
   GPR_ASSERT(data_len == sizeof(addr6->sin6_addr.s6_addr));
   memcpy(&addr6->sin6_addr.s6_addr, data, data_len);
   addr6->sin6_port = grpc_htons(12345);
-  resolved_addr6.len = sizeof(grpc_sockaddr_in6);
+  resolved_addr6.len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in6));
   return resolved_addr6;
 }
 
diff --git a/test/core/iomgr/tcp_client_posix_test.cc b/test/core/iomgr/tcp_client_posix_test.cc
index 8a43170..a4c38af 100644
--- a/test/core/iomgr/tcp_client_posix_test.cc
+++ b/test/core/iomgr/tcp_client_posix_test.cc
@@ -89,7 +89,7 @@
   gpr_log(GPR_DEBUG, "test_succeeds");
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = sizeof(struct sockaddr_in);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
 
   /* create a dummy server */
@@ -112,7 +112,7 @@
 
   /* await the connection */
   do {
-    resolved_addr.len = sizeof(addr);
+    resolved_addr.len = static_cast<socklen_t>(sizeof(addr));
     r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr),
                reinterpret_cast<socklen_t*>(&resolved_addr.len));
   } while (r == -1 && errno == EINTR);
@@ -147,7 +147,7 @@
   gpr_log(GPR_DEBUG, "test_fails");
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = sizeof(struct sockaddr_in);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
 
   gpr_mu_lock(g_mu);
diff --git a/test/core/iomgr/tcp_server_posix_test.cc b/test/core/iomgr/tcp_server_posix_test.cc
index dde77da..d646df1 100644
--- a/test/core/iomgr/tcp_server_posix_test.cc
+++ b/test/core/iomgr/tcp_server_posix_test.cc
@@ -188,7 +188,7 @@
   LOG_TEST("test_no_op_with_port");
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = sizeof(struct sockaddr_in);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
   int port = -1;
   GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) ==
@@ -209,7 +209,7 @@
   int port = -1;
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = sizeof(struct sockaddr_in);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
   GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) ==
                  GRPC_ERROR_NONE &&
@@ -314,8 +314,8 @@
           dst_addrs != nullptr ? "<specific>" : "::", test_dst_addrs);
   memset(&resolved_addr, 0, sizeof(resolved_addr));
   memset(&resolved_addr1, 0, sizeof(resolved_addr1));
-  resolved_addr.len = sizeof(struct sockaddr_storage);
-  resolved_addr1.len = sizeof(struct sockaddr_storage);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
+  resolved_addr1.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
   addr->ss_family = addr1->ss_family = AF_INET;
   GPR_ASSERT(GRPC_LOG_IF_ERROR(
       "grpc_tcp_server_add_port",
@@ -387,7 +387,7 @@
         size_t connect_num;
         test_addr dst;
         GPR_ASSERT(fd >= 0);
-        dst.addr.len = sizeof(dst.addr.addr);
+        dst.addr.len = static_cast<socklen_t>(sizeof(dst.addr.addr));
         GPR_ASSERT(getsockname(fd, (struct sockaddr*)dst.addr.addr,
                                (socklen_t*)&dst.addr.len) == 0);
         GPR_ASSERT(dst.addr.len <= sizeof(dst.addr.addr));
@@ -460,10 +460,10 @@
         continue;
       } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
         dst_addrs->addrs[dst_addrs->naddrs].addr.len =
-            sizeof(struct sockaddr_in);
+            static_cast<socklen_t>(sizeof(struct sockaddr_in));
       } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
         dst_addrs->addrs[dst_addrs->naddrs].addr.len =
-            sizeof(struct sockaddr_in6);
+            static_cast<socklen_t>(sizeof(struct sockaddr_in6));
       } else {
         continue;
       }
diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc
index 60f2939..3058e87 100644
--- a/test/core/iomgr/udp_server_test.cc
+++ b/test/core/iomgr/udp_server_test.cc
@@ -210,7 +210,7 @@
   LOG_TEST("test_no_op_with_port");
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = sizeof(struct sockaddr_in);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
   GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
                                       snd_buf_size, &handler_factory));
@@ -241,7 +241,7 @@
   LOG_TEST("test_no_op_with_port_and_socket_factory");
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = sizeof(struct sockaddr_in);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
   GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
                                       snd_buf_size, &handler_factory));
@@ -268,7 +268,7 @@
   LOG_TEST("test_no_op_with_port_and_start");
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = sizeof(struct sockaddr_in);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
   GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
                                       snd_buf_size, &handler_factory));
@@ -301,7 +301,7 @@
   g_number_of_orphan_calls = 0;
 
   memset(&resolved_addr, 0, sizeof(resolved_addr));
-  resolved_addr.len = sizeof(struct sockaddr_storage);
+  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
   addr->ss_family = AF_INET;
   GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
                                       snd_buf_size, &handler_factory));
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index d858603..866bee5 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -143,6 +143,9 @@
   printf("%lx", (unsigned long) grpc_auth_context_add_property);
   printf("%lx", (unsigned long) grpc_auth_context_add_cstring_property);
   printf("%lx", (unsigned long) grpc_auth_context_set_peer_identity_property_name);
+  printf("%lx", (unsigned long) grpc_ssl_session_cache_create_lru);
+  printf("%lx", (unsigned long) grpc_ssl_session_cache_destroy);
+  printf("%lx", (unsigned long) grpc_ssl_session_cache_create_channel_arg);
   printf("%lx", (unsigned long) grpc_channel_credentials_release);
   printf("%lx", (unsigned long) grpc_google_default_credentials_create);
   printf("%lx", (unsigned long) grpc_set_ssl_roots_override_callback);
diff --git a/test/core/tsi/BUILD b/test/core/tsi/BUILD
index 8ac3e76..ae6e8fd 100644
--- a/test/core/tsi/BUILD
+++ b/test/core/tsi/BUILD
@@ -41,6 +41,20 @@
     ],
 )
 
+grpc_cc_test(
+    name = "ssl_session_cache_test",
+    srcs = ["ssl_session_cache_test.cc"],
+    language = "C++",
+    external_deps = [
+        "gtest",
+    ],
+    deps = [
+        "//:grpc",
+        "//:gpr",
+        "//:tsi",
+        "//test/core/util:gpr_test_util",
+    ],
+)
 
 grpc_cc_test(
     name = "ssl_transport_security_test",
diff --git a/test/core/tsi/ssl_session_cache_test.cc b/test/core/tsi/ssl_session_cache_test.cc
new file mode 100644
index 0000000..72df0e5
--- /dev/null
+++ b/test/core/tsi/ssl_session_cache_test.cc
@@ -0,0 +1,154 @@
+/*
+ *
+ * Copyright 2018 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 <string>
+#include <unordered_set>
+
+#include "src/core/tsi/ssl/session_cache/ssl_session_cache.h"
+#include "test/core/util/test_config.h"
+
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <gtest/gtest.h>
+
+namespace grpc_core {
+
+namespace {
+
+class SessionTracker;
+
+struct SessionExDataId {
+  SessionTracker* tracker;
+  long id;
+};
+
+class SessionTracker {
+ public:
+  SessionTracker() { ssl_context_ = SSL_CTX_new(TLSv1_2_method()); }
+
+  ~SessionTracker() { SSL_CTX_free(ssl_context_); }
+
+  tsi::SslSessionPtr NewSession(long id) {
+    static int ex_data_id = SSL_SESSION_get_ex_new_index(
+        0, nullptr, nullptr, nullptr, DestroyExData);
+    GPR_ASSERT(ex_data_id != -1);
+    // OpenSSL and different version of BoringSSL don't agree on API
+    // so try both.
+    tsi::SslSessionPtr session = NewSessionInternal(SSL_SESSION_new);
+    SessionExDataId* data = new SessionExDataId{this, id};
+    int result = SSL_SESSION_set_ex_data(session.get(), ex_data_id, data);
+    EXPECT_EQ(result, 1);
+    alive_sessions_.insert(id);
+    return session;
+  }
+
+  bool IsAlive(long id) const {
+    return alive_sessions_.find(id) != alive_sessions_.end();
+  }
+
+  size_t AliveCount() const { return alive_sessions_.size(); }
+
+ private:
+  tsi::SslSessionPtr NewSessionInternal(SSL_SESSION* (*cb)()) {
+    return tsi::SslSessionPtr(cb());
+  }
+
+  tsi::SslSessionPtr NewSessionInternal(SSL_SESSION* (*cb)(const SSL_CTX*)) {
+    return tsi::SslSessionPtr(cb(ssl_context_));
+  }
+
+  static void DestroyExData(void* parent, void* ptr, CRYPTO_EX_DATA* ad,
+                            int index, long argl, void* argp) {
+    SessionExDataId* data = static_cast<SessionExDataId*>(ptr);
+    data->tracker->alive_sessions_.erase(data->id);
+    delete data;
+  }
+
+  SSL_CTX* ssl_context_;
+  std::unordered_set<long> alive_sessions_;
+};
+
+TEST(SslSessionCacheTest, InitialState) {
+  SessionTracker tracker;
+  // Verify session initial state.
+  {
+    tsi::SslSessionPtr tmp_sess = tracker.NewSession(1);
+    EXPECT_EQ(tmp_sess->references, 1);
+    EXPECT_TRUE(tracker.IsAlive(1));
+    EXPECT_EQ(tracker.AliveCount(), 1);
+  }
+  EXPECT_FALSE(tracker.IsAlive(1));
+  EXPECT_EQ(tracker.AliveCount(), 0);
+}
+
+TEST(SslSessionCacheTest, LruCache) {
+  SessionTracker tracker;
+  {
+    RefCountedPtr<tsi::SslSessionLRUCache> cache =
+        tsi::SslSessionLRUCache::Create(3);
+    tsi::SslSessionPtr sess2 = tracker.NewSession(2);
+    SSL_SESSION* sess2_ptr = sess2.get();
+    cache->Put("first.dropbox.com", std::move(sess2));
+    EXPECT_EQ(cache->Get("first.dropbox.com").get(), sess2_ptr);
+    EXPECT_TRUE(tracker.IsAlive(2));
+    EXPECT_EQ(tracker.AliveCount(), 1);
+    // Putting element with the same key destroys old session.
+    tsi::SslSessionPtr sess3 = tracker.NewSession(3);
+    SSL_SESSION* sess3_ptr = sess3.get();
+    cache->Put("first.dropbox.com", std::move(sess3));
+    EXPECT_FALSE(tracker.IsAlive(2));
+    EXPECT_EQ(cache->Get("first.dropbox.com").get(), sess3_ptr);
+    EXPECT_TRUE(tracker.IsAlive(3));
+    EXPECT_EQ(tracker.AliveCount(), 1);
+    // Putting three more elements discards current one.
+    for (long id = 4; id < 7; id++) {
+      EXPECT_TRUE(tracker.IsAlive(3));
+      std::string domain = std::to_string(id) + ".random.domain";
+      cache->Put(domain.c_str(), tracker.NewSession(id));
+    }
+    EXPECT_EQ(cache->Size(), 3);
+    EXPECT_FALSE(tracker.IsAlive(3));
+    EXPECT_EQ(tracker.AliveCount(), 3);
+    // Accessing element moves it into front of the queue.
+    EXPECT_TRUE(cache->Get("4.random.domain"));
+    EXPECT_TRUE(tracker.IsAlive(4));
+    EXPECT_TRUE(tracker.IsAlive(5));
+    EXPECT_TRUE(tracker.IsAlive(6));
+    // One element has to be evicted from cache->
+    cache->Put("7.random.domain", tracker.NewSession(7));
+    EXPECT_TRUE(tracker.IsAlive(4));
+    EXPECT_FALSE(tracker.IsAlive(5));
+    EXPECT_TRUE(tracker.IsAlive(6));
+    EXPECT_TRUE(tracker.IsAlive(7));
+    EXPECT_EQ(tracker.AliveCount(), 3);
+  }
+  // Cache destructor destroys all sessions.
+  EXPECT_EQ(tracker.AliveCount(), 0);
+}
+
+}  // namespace
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc_test_init(argc, argv);
+  grpc_init();
+  int ret = RUN_ALL_TESTS();
+  grpc_shutdown();
+  return ret;
+}
diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc
index d9eb747..0878c57 100644
--- a/test/core/tsi/ssl_transport_security_test.cc
+++ b/test/core/tsi/ssl_transport_security_test.cc
@@ -52,8 +52,8 @@
 
 typedef struct ssl_alpn_lib {
   AlpnMode alpn_mode;
-  char** server_alpn_protocols;
-  char** client_alpn_protocols;
+  const char** server_alpn_protocols;
+  const char** client_alpn_protocols;
   uint16_t num_server_alpn_protocols;
   uint16_t num_client_alpn_protocols;
 } ssl_alpn_lib;
@@ -76,6 +76,10 @@
   ssl_alpn_lib* alpn_lib;
   bool force_client_auth;
   char* server_name_indication;
+  tsi_ssl_session_cache* session_cache;
+  bool session_reused;
+  const char* session_ticket_key;
+  size_t session_ticket_key_size;
   tsi_ssl_server_handshaker_factory* server_handshaker_factory;
   tsi_ssl_client_handshaker_factory* client_handshaker_factory;
 } ssl_tsi_test_fixture;
@@ -89,47 +93,60 @@
   ssl_key_cert_lib* key_cert_lib = ssl_fixture->key_cert_lib;
   ssl_alpn_lib* alpn_lib = ssl_fixture->alpn_lib;
   /* Create client handshaker factory. */
-  tsi_ssl_pem_key_cert_pair* client_key_cert_pair = nullptr;
+  tsi_ssl_client_handshaker_options client_options;
+  memset(&client_options, 0, sizeof(client_options));
+  client_options.pem_root_certs = key_cert_lib->root_cert;
   if (ssl_fixture->force_client_auth) {
-    client_key_cert_pair = key_cert_lib->use_bad_client_cert
-                               ? &key_cert_lib->bad_client_pem_key_cert_pair
-                               : &key_cert_lib->client_pem_key_cert_pair;
+    client_options.pem_key_cert_pair =
+        key_cert_lib->use_bad_client_cert
+            ? &key_cert_lib->bad_client_pem_key_cert_pair
+            : &key_cert_lib->client_pem_key_cert_pair;
   }
-  char** client_alpn_protocols = nullptr;
-  uint16_t num_client_alpn_protocols = 0;
   if (alpn_lib->alpn_mode == ALPN_CLIENT_NO_SERVER ||
       alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ||
       alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
-    client_alpn_protocols = alpn_lib->client_alpn_protocols;
-    num_client_alpn_protocols = alpn_lib->num_client_alpn_protocols;
+    client_options.alpn_protocols = alpn_lib->client_alpn_protocols;
+    client_options.num_alpn_protocols = alpn_lib->num_client_alpn_protocols;
   }
-  GPR_ASSERT(tsi_create_ssl_client_handshaker_factory(
-                 client_key_cert_pair, key_cert_lib->root_cert, nullptr,
-                 (const char**)client_alpn_protocols, num_client_alpn_protocols,
-                 &ssl_fixture->client_handshaker_factory) == TSI_OK);
+  if (ssl_fixture->session_cache != nullptr) {
+    client_options.session_cache = ssl_fixture->session_cache;
+  }
+  GPR_ASSERT(tsi_create_ssl_client_handshaker_factory_with_options(
+                 &client_options, &ssl_fixture->client_handshaker_factory) ==
+             TSI_OK);
   /* Create server handshaker factory. */
-  char** server_alpn_protocols = nullptr;
-  uint16_t num_server_alpn_protocols = 0;
+  tsi_ssl_server_handshaker_options server_options;
+  memset(&server_options, 0, sizeof(server_options));
   if (alpn_lib->alpn_mode == ALPN_SERVER_NO_CLIENT ||
       alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ||
       alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
-    server_alpn_protocols = alpn_lib->server_alpn_protocols;
-    num_server_alpn_protocols = alpn_lib->num_server_alpn_protocols;
+    server_options.alpn_protocols = alpn_lib->server_alpn_protocols;
+    server_options.num_alpn_protocols = alpn_lib->num_server_alpn_protocols;
     if (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
-      num_server_alpn_protocols--;
+      server_options.num_alpn_protocols--;
     }
   }
-  GPR_ASSERT(tsi_create_ssl_server_handshaker_factory(
-                 key_cert_lib->use_bad_server_cert
-                     ? key_cert_lib->bad_server_pem_key_cert_pairs
-                     : key_cert_lib->server_pem_key_cert_pairs,
-                 key_cert_lib->use_bad_server_cert
-                     ? key_cert_lib->bad_server_num_key_cert_pairs
-                     : key_cert_lib->server_num_key_cert_pairs,
-                 key_cert_lib->root_cert, ssl_fixture->force_client_auth,
-                 nullptr, (const char**)server_alpn_protocols,
-                 num_server_alpn_protocols,
-                 &ssl_fixture->server_handshaker_factory) == TSI_OK);
+  server_options.pem_key_cert_pairs =
+      key_cert_lib->use_bad_server_cert
+          ? key_cert_lib->bad_server_pem_key_cert_pairs
+          : key_cert_lib->server_pem_key_cert_pairs;
+  server_options.num_key_cert_pairs =
+      key_cert_lib->use_bad_server_cert
+          ? key_cert_lib->bad_server_num_key_cert_pairs
+          : key_cert_lib->server_num_key_cert_pairs;
+  server_options.pem_client_root_certs = key_cert_lib->root_cert;
+  if (ssl_fixture->force_client_auth) {
+    server_options.client_certificate_request =
+        TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY;
+  } else {
+    server_options.client_certificate_request =
+        TSI_DONT_REQUEST_CLIENT_CERTIFICATE;
+  }
+  server_options.session_ticket_key = ssl_fixture->session_ticket_key;
+  server_options.session_ticket_key_size = ssl_fixture->session_ticket_key_size;
+  GPR_ASSERT(tsi_create_ssl_server_handshaker_factory_with_options(
+                 &server_options, &ssl_fixture->server_handshaker_factory) ==
+             TSI_OK);
   /* Create server and client handshakers. */
   tsi_handshaker* client_handshaker = nullptr;
   GPR_ASSERT(tsi_ssl_client_handshaker_factory_create_handshaker(
@@ -176,6 +193,18 @@
   return property;
 }
 
+static void check_session_reusage(ssl_tsi_test_fixture* ssl_fixture,
+                                  tsi_peer* peer) {
+  const tsi_peer_property* session_reused =
+      tsi_peer_get_property_by_name(peer, TSI_SSL_SESSION_REUSED_PEER_PROPERTY);
+  GPR_ASSERT(session_reused != nullptr);
+  if (ssl_fixture->session_reused) {
+    GPR_ASSERT(strcmp(session_reused->value.data, "true") == 0);
+  } else {
+    GPR_ASSERT(strcmp(session_reused->value.data, "false") == 0);
+  }
+}
+
 void check_server0_peer(tsi_peer* peer) {
   const tsi_peer_property* property =
       check_basic_authenticated_peer_and_get_common_name(peer);
@@ -233,7 +262,7 @@
   ssl_alpn_lib* alpn_lib = ssl_fixture->alpn_lib;
   if (!ssl_fixture->force_client_auth) {
     GPR_ASSERT(peer->property_count ==
-               (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ? 1 : 0));
+               (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ? 2 : 1));
   } else {
     const tsi_peer_property* property =
         check_basic_authenticated_peer_and_get_common_name(peer);
@@ -257,8 +286,8 @@
   if (expect_success) {
     GPR_ASSERT(tsi_handshaker_result_extract_peer(
                    ssl_fixture->base.client_result, &peer) == TSI_OK);
+    check_session_reusage(ssl_fixture, &peer);
     check_alpn(ssl_fixture, &peer);
-
     if (ssl_fixture->server_name_indication != nullptr) {
       check_server1_peer(&peer);
     } else {
@@ -270,6 +299,7 @@
   if (expect_success) {
     GPR_ASSERT(tsi_handshaker_result_extract_peer(
                    ssl_fixture->base.server_result, &peer) == TSI_OK);
+    check_session_reusage(ssl_fixture, &peer);
     check_alpn(ssl_fixture, &peer);
     check_client_peer(ssl_fixture, &peer);
   } else {
@@ -291,11 +321,11 @@
   /* Destroy ssl_alpn_lib. */
   ssl_alpn_lib* alpn_lib = ssl_fixture->alpn_lib;
   for (size_t i = 0; i < alpn_lib->num_server_alpn_protocols; i++) {
-    gpr_free(alpn_lib->server_alpn_protocols[i]);
+    gpr_free(const_cast<char*>(alpn_lib->server_alpn_protocols[i]));
   }
   gpr_free(alpn_lib->server_alpn_protocols);
   for (size_t i = 0; i < alpn_lib->num_client_alpn_protocols; i++) {
-    gpr_free(alpn_lib->client_alpn_protocols[i]);
+    gpr_free(const_cast<char*>(alpn_lib->client_alpn_protocols[i]));
   }
   gpr_free(alpn_lib->client_alpn_protocols);
   gpr_free(alpn_lib);
@@ -316,6 +346,9 @@
       key_cert_lib->bad_client_pem_key_cert_pair);
   gpr_free(key_cert_lib->root_cert);
   gpr_free(key_cert_lib);
+  if (ssl_fixture->session_cache != nullptr) {
+    tsi_ssl_session_cache_unref(ssl_fixture->session_cache);
+  }
   /* Unreference others. */
   tsi_ssl_server_handshaker_factory_unref(
       ssl_fixture->server_handshaker_factory);
@@ -388,10 +421,10 @@
   /* Create ssl_alpn_lib. */
   ssl_alpn_lib* alpn_lib =
       static_cast<ssl_alpn_lib*>(gpr_zalloc(sizeof(*alpn_lib)));
-  alpn_lib->server_alpn_protocols =
-      static_cast<char**>(gpr_zalloc(sizeof(char*) * SSL_TSI_TEST_ALPN_NUM));
-  alpn_lib->client_alpn_protocols =
-      static_cast<char**>(gpr_zalloc(sizeof(char*) * SSL_TSI_TEST_ALPN_NUM));
+  alpn_lib->server_alpn_protocols = static_cast<const char**>(
+      gpr_zalloc(sizeof(char*) * SSL_TSI_TEST_ALPN_NUM));
+  alpn_lib->client_alpn_protocols = static_cast<const char**>(
+      gpr_zalloc(sizeof(char*) * SSL_TSI_TEST_ALPN_NUM));
   alpn_lib->server_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN1);
   alpn_lib->server_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3);
   alpn_lib->client_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN2);
@@ -402,6 +435,9 @@
   ssl_fixture->alpn_lib = alpn_lib;
   ssl_fixture->base.vtable = &vtable;
   ssl_fixture->server_name_indication = nullptr;
+  ssl_fixture->session_reused = false;
+  ssl_fixture->session_ticket_key = nullptr;
+  ssl_fixture->session_ticket_key_size = 0;
   ssl_fixture->force_client_auth = false;
   return &ssl_fixture->base;
 }
@@ -558,6 +594,38 @@
   }
 }
 
+void ssl_tsi_test_do_handshake_session_cache() {
+  tsi_ssl_session_cache* session_cache = tsi_ssl_session_cache_create_lru(16);
+  char session_ticket_key[48];
+  auto do_handshake = [&session_ticket_key,
+                       &session_cache](bool session_reused) {
+    tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
+    ssl_tsi_test_fixture* ssl_fixture =
+        reinterpret_cast<ssl_tsi_test_fixture*>(fixture);
+    ssl_fixture->server_name_indication =
+        const_cast<char*>("waterzooi.test.google.be");
+    ssl_fixture->session_ticket_key = session_ticket_key;
+    ssl_fixture->session_ticket_key_size = 48;
+    tsi_ssl_session_cache_ref(session_cache);
+    ssl_fixture->session_cache = session_cache;
+    ssl_fixture->session_reused = session_reused;
+    tsi_test_do_round_trip(&ssl_fixture->base);
+    tsi_test_fixture_destroy(fixture);
+  };
+  memset(session_ticket_key, 'a', 48);
+  do_handshake(false);
+  do_handshake(true);
+  do_handshake(true);
+  // Changing session_ticket_key on server invalidates ticket.
+  memset(session_ticket_key, 'b', 48);
+  do_handshake(false);
+  do_handshake(true);
+  memset(session_ticket_key, 'c', 48);
+  do_handshake(false);
+  do_handshake(true);
+  tsi_ssl_session_cache_unref(session_cache);
+}
+
 static const tsi_ssl_handshaker_factory_vtable* original_vtable;
 static bool handshaker_factory_destructor_called;
 
@@ -575,13 +643,14 @@
 
 void test_tsi_ssl_client_handshaker_factory_refcounting() {
   int i;
-  const char* cert_chain =
-      load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.pem");
+  char* cert_chain = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.pem");
 
+  tsi_ssl_client_handshaker_options options;
+  memset(&options, 0, sizeof(options));
+  options.pem_root_certs = cert_chain;
   tsi_ssl_client_handshaker_factory* client_handshaker_factory;
-  GPR_ASSERT(tsi_create_ssl_client_handshaker_factory(
-                 nullptr, cert_chain, nullptr, nullptr, 0,
-                 &client_handshaker_factory) == TSI_OK);
+  GPR_ASSERT(tsi_create_ssl_client_handshaker_factory_with_options(
+                 &options, &client_handshaker_factory) == TSI_OK);
 
   handshaker_factory_destructor_called = false;
   original_vtable = tsi_ssl_handshaker_factory_swap_vtable(
@@ -608,7 +677,7 @@
   tsi_handshaker_destroy(handshaker[2]);
   GPR_ASSERT(handshaker_factory_destructor_called);
 
-  gpr_free((void*)cert_chain);
+  gpr_free(cert_chain);
 }
 
 void test_tsi_ssl_server_handshaker_factory_refcounting() {
@@ -673,6 +742,7 @@
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
   grpc_init();
+
   ssl_tsi_test_do_handshake_tiny_handshake_buffer();
   ssl_tsi_test_do_handshake_small_handshake_buffer();
   ssl_tsi_test_do_handshake();
@@ -688,6 +758,7 @@
 #endif
   ssl_tsi_test_do_handshake_alpn_server_no_client();
   ssl_tsi_test_do_handshake_alpn_client_server_ok();
+  ssl_tsi_test_do_handshake_session_cache();
   ssl_tsi_test_do_round_trip_for_all_configs();
   ssl_tsi_test_do_round_trip_odd_buffer_size();
   ssl_tsi_test_handshaker_factory_internals();
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index dd777d1..e8d2325 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -319,12 +319,13 @@
       service_->RequestEcho(&srv_ctx, &recv_request, &response_writer,
                             cq_.get(), cq_.get(), tag(2));
 
+      response_reader->Finish(&recv_response, &recv_status, tag(4));
+
       Verifier().Expect(2, true).Verify(cq_.get());
       EXPECT_EQ(send_request.message(), recv_request.message());
 
       send_response.set_message(recv_request.message());
       response_writer.Finish(send_response, Status::OK, tag(3));
-      response_reader->Finish(&recv_response, &recv_status, tag(4));
       Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get());
 
       EXPECT_EQ(send_response.message(), recv_response.message());
@@ -434,13 +435,13 @@
 
   service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
                         cq_.get(), tag(2));
+  response_reader->Finish(&recv_response, &recv_status, tag(4));
 
   Verifier().Expect(2, true).Verify(cq_.get(), time_limit);
   EXPECT_EQ(send_request.message(), recv_request.message());
 
   send_response.set_message(recv_request.message());
   response_writer.Finish(send_response, Status::OK, tag(3));
-  response_reader->Finish(&recv_response, &recv_status, tag(4));
   Verifier().Expect(3, true).Expect(4, true).Verify(
       cq_.get(), std::chrono::system_clock::time_point::max());
 
@@ -475,21 +476,18 @@
 
   auto resp_writer_ptr = &response_writer;
   auto lambda_2 = [&, this, resp_writer_ptr]() {
-    gpr_log(GPR_ERROR, "CALLED");
     service_->RequestEcho(&srv_ctx, &recv_request, resp_writer_ptr, cq_.get(),
                           cq_.get(), tag(2));
   };
+  response_reader->Finish(&recv_response, &recv_status, tag(4));
 
   Verifier().Expect(2, true).Verify(cq_.get(), time_limit, lambda_2);
   EXPECT_EQ(send_request.message(), recv_request.message());
 
-  auto recv_resp_ptr = &recv_response;
-  auto status_ptr = &recv_status;
   send_response.set_message(recv_request.message());
-  auto lambda_3 = [&, this, resp_writer_ptr, send_response]() {
+  auto lambda_3 = [resp_writer_ptr, send_response]() {
     resp_writer_ptr->Finish(send_response, Status::OK, tag(3));
   };
-  response_reader->Finish(recv_resp_ptr, status_ptr, tag(4));
   Verifier().Expect(3, true).Expect(4, true).Verify(
       cq_.get(), std::chrono::system_clock::time_point::max(), lambda_3);
 
@@ -887,6 +885,7 @@
 
   std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
       stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
+  response_reader->Finish(&recv_response, &recv_status, tag(4));
 
   service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
                         cq_.get(), tag(2));
@@ -903,7 +902,6 @@
 
   send_response.set_message(recv_request.message());
   response_writer.Finish(send_response, Status::OK, tag(3));
-  response_reader->Finish(&recv_response, &recv_status, tag(4));
   Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get());
 
   EXPECT_EQ(send_response.message(), recv_response.message());
@@ -929,6 +927,7 @@
 
   std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
       stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
+  response_reader->ReadInitialMetadata(tag(4));
 
   service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
                         cq_.get(), tag(2));
@@ -937,10 +936,7 @@
   srv_ctx.AddInitialMetadata(meta1.first, meta1.second);
   srv_ctx.AddInitialMetadata(meta2.first, meta2.second);
   response_writer.SendInitialMetadata(tag(3));
-  Verifier().Expect(3, true).Verify(cq_.get());
-
-  response_reader->ReadInitialMetadata(tag(4));
-  Verifier().Expect(4, true).Verify(cq_.get());
+  Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get());
   auto server_initial_metadata = cli_ctx.GetServerInitialMetadata();
   EXPECT_EQ(meta1.second,
             ToString(server_initial_metadata.find(meta1.first)->second));
@@ -976,6 +972,7 @@
 
   std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
       stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
+  response_reader->Finish(&recv_response, &recv_status, tag(5));
 
   service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
                         cq_.get(), tag(2));
@@ -988,7 +985,6 @@
   srv_ctx.AddTrailingMetadata(meta1.first, meta1.second);
   srv_ctx.AddTrailingMetadata(meta2.first, meta2.second);
   response_writer.Finish(send_response, Status::OK, tag(4));
-  response_reader->Finish(&recv_response, &recv_status, tag(5));
 
   Verifier().Expect(4, true).Expect(5, true).Verify(cq_.get());
 
@@ -1036,6 +1032,7 @@
 
   std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
       stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
+  response_reader->ReadInitialMetadata(tag(4));
 
   service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
                         cq_.get(), tag(2));
@@ -1051,9 +1048,7 @@
   srv_ctx.AddInitialMetadata(meta3.first, meta3.second);
   srv_ctx.AddInitialMetadata(meta4.first, meta4.second);
   response_writer.SendInitialMetadata(tag(3));
-  Verifier().Expect(3, true).Verify(cq_.get());
-  response_reader->ReadInitialMetadata(tag(4));
-  Verifier().Expect(4, true).Verify(cq_.get());
+  Verifier().Expect(3, true).Expect(4, true).Verify(cq_.get());
   auto server_initial_metadata = cli_ctx.GetServerInitialMetadata();
   EXPECT_EQ(meta3.second,
             ToString(server_initial_metadata.find(meta3.first)->second));
@@ -1096,6 +1091,7 @@
   send_request.set_message(GetParam().message_content);
   std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
       stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
+  response_reader->Finish(&recv_response, &recv_status, tag(4));
 
   srv_ctx.AsyncNotifyWhenDone(tag(5));
   service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
@@ -1105,12 +1101,9 @@
   EXPECT_EQ(send_request.message(), recv_request.message());
 
   cli_ctx.TryCancel();
-  Verifier().Expect(5, true).Verify(cq_.get());
+  Verifier().Expect(5, true).Expect(4, true).Verify(cq_.get());
   EXPECT_TRUE(srv_ctx.IsCancelled());
 
-  response_reader->Finish(&recv_response, &recv_status, tag(4));
-  Verifier().Expect(4, true).Verify(cq_.get());
-
   EXPECT_EQ(StatusCode::CANCELLED, recv_status.error_code());
 }
 
@@ -1131,6 +1124,7 @@
   send_request.set_message(GetParam().message_content);
   std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
       stub_->AsyncEcho(&cli_ctx, send_request, cq_.get()));
+  response_reader->Finish(&recv_response, &recv_status, tag(4));
 
   srv_ctx.AsyncNotifyWhenDone(tag(5));
   service_->RequestEcho(&srv_ctx, &recv_request, &response_writer, cq_.get(),
@@ -1141,7 +1135,6 @@
 
   send_response.set_message(recv_request.message());
   response_writer.Finish(send_response, Status::OK, tag(3));
-  response_reader->Finish(&recv_response, &recv_status, tag(4));
   Verifier().Expect(3, true).Expect(4, true).Expect(5, true).Verify(cq_.get());
   EXPECT_FALSE(srv_ctx.IsCancelled());
 
@@ -1223,8 +1216,7 @@
     srv_ctx.AsyncNotifyWhenDone(tag(11));
     service_->RequestRequestStream(&srv_ctx, &srv_stream, cq_.get(), cq_.get(),
                                    tag(2));
-    std::thread t1(
-        [this, &cli_cq] { Verifier().Expect(1, true).Verify(&cli_cq); });
+    std::thread t1([&cli_cq] { Verifier().Expect(1, true).Verify(&cli_cq); });
     Verifier().Expect(2, true).Verify(cq_.get());
     t1.join();
 
@@ -1248,7 +1240,7 @@
         (server_try_cancel == CANCEL_BEFORE_PROCESSING);
 
     std::thread cli_thread([&cli_cq, &cli_stream, &expected_client_cq_result,
-                            &ignore_client_cq_result, this] {
+                            &ignore_client_cq_result] {
       EchoRequest send_request;
       // Client sends 3 messages (tags 3, 4 and 5)
       for (int tag_idx = 3; tag_idx <= 5; tag_idx++) {
@@ -1379,8 +1371,7 @@
     service_->RequestResponseStream(&srv_ctx, &recv_request, &srv_stream,
                                     cq_.get(), cq_.get(), tag(2));
 
-    std::thread t1(
-        [this, &cli_cq] { Verifier().Expect(1, true).Verify(&cli_cq); });
+    std::thread t1([&cli_cq] { Verifier().Expect(1, true).Verify(&cli_cq); });
     Verifier().Expect(2, true).Verify(cq_.get());
     t1.join();
 
@@ -1405,7 +1396,7 @@
     }
 
     std::thread cli_thread([&cli_cq, &cli_stream, &expected_client_cq_result,
-                            &ignore_client_cq_result, this] {
+                            &ignore_client_cq_result] {
       // Client attempts to read the three messages from the server
       for (int tag_idx = 6; tag_idx <= 8; tag_idx++) {
         EchoResponse recv_response;
diff --git a/test/cpp/end2end/nonblocking_test.cc b/test/cpp/end2end/nonblocking_test.cc
index cb75848..d8337ba 100644
--- a/test/cpp/end2end/nonblocking_test.cc
+++ b/test/cpp/end2end/nonblocking_test.cc
@@ -128,6 +128,7 @@
           stub_->PrepareAsyncEcho(&cli_ctx, send_request, cq_.get()));
 
       response_reader->StartCall();
+      response_reader->Finish(&recv_response, &recv_status, tag(4));
 
       service_->RequestEcho(&srv_ctx, &recv_request, &response_writer,
                             cq_.get(), cq_.get(), tag(2));
@@ -141,7 +142,6 @@
 
       send_response.set_message(recv_request.message());
       response_writer.Finish(send_response, Status::OK, tag(3));
-      response_reader->Finish(&recv_response, &recv_status, tag(4));
 
       int tagsum = 0;
       int tagprod = 1;
diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
index 294f1fe..3b21c4c 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
@@ -394,13 +394,13 @@
         stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
     void* t;
     bool ok;
+    response_reader->Finish(&recv_response, &recv_status, tag(4));
     TrickleCQNext(fixture.get(), &t, &ok, in_warmup ? -1 : state.iterations());
     GPR_ASSERT(ok);
     GPR_ASSERT(t == tag(0) || t == tag(1));
     intptr_t slot = reinterpret_cast<intptr_t>(t);
     ServerEnv* senv = server_env[slot];
     senv->response_writer.Finish(send_response, Status::OK, tag(3));
-    response_reader->Finish(&recv_response, &recv_status, tag(4));
     for (int i = (1 << 3) | (1 << 4); i != 0;) {
       TrickleCQNext(fixture.get(), &t, &ok,
                     in_warmup ? -1 : state.iterations());
diff --git a/test/cpp/microbenchmarks/fullstack_unary_ping_pong.h b/test/cpp/microbenchmarks/fullstack_unary_ping_pong.h
index a85c33c..843c8e1 100644
--- a/test/cpp/microbenchmarks/fullstack_unary_ping_pong.h
+++ b/test/cpp/microbenchmarks/fullstack_unary_ping_pong.h
@@ -78,6 +78,7 @@
     ClientContextMutator cli_ctx_mut(&cli_ctx);
     std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
         stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
+    response_reader->Finish(&recv_response, &recv_status, tag(4));
     void* t;
     bool ok;
     GPR_ASSERT(fixture->cq()->Next(&t, &ok));
@@ -87,7 +88,6 @@
     ServerEnv* senv = server_env[slot];
     ServerContextMutator svr_ctx_mut(&senv->ctx);
     senv->response_writer.Finish(send_response, Status::OK, tag(3));
-    response_reader->Finish(&recv_response, &recv_status, tag(4));
     for (int i = (1 << 3) | (1 << 4); i != 0;) {
       GPR_ASSERT(fixture->cq()->Next(&t, &ok));
       GPR_ASSERT(ok);
diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc
index f4be064..bfdcd96 100644
--- a/test/cpp/naming/resolver_component_test.cc
+++ b/test/cpp/naming/resolver_component_test.cc
@@ -65,6 +65,11 @@
               "List of expected backend or balancer addresses in the form "
               "'<ip0:port0>,<is_balancer0>;<ip1:port1>,<is_balancer1>;...'. "
               "'is_balancer' should be bool, i.e. true or false.");
+DEFINE_bool(allow_extra_addrs, false,
+            "Permit extra resolved addresses in the final list of "
+            "resolved addresses. This is useful in certain integration "
+            "test environments in which DNS responses are not fully "
+            "deterministic.");
 DEFINE_string(expected_chosen_service_config, "",
               "Expected service config json string that gets chosen (no "
               "whitespace). Empty for none.");
@@ -240,9 +245,11 @@
   GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
   grpc_lb_addresses* addresses =
       (grpc_lb_addresses*)channel_arg->value.pointer.p;
-  gpr_log(GPR_INFO, "num addrs found: %" PRIdPTR ". expected %" PRIdPTR,
-          addresses->num_addresses, args->expected_addrs.size());
-  GPR_ASSERT(addresses->num_addresses == args->expected_addrs.size());
+  gpr_log(GPR_INFO,
+          "num addrs found: %" PRIdPTR ". expected %" PRIdPTR
+          ". Allow extra addresses:%d.",
+          addresses->num_addresses, args->expected_addrs.size(),
+          FLAGS_allow_extra_addrs);
   std::vector<GrpcLBAddress> found_lb_addrs;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     grpc_lb_address addr = addresses->addresses[i];
@@ -254,13 +261,20 @@
     gpr_free(str);
   }
   if (args->expected_addrs.size() != found_lb_addrs.size()) {
-    gpr_log(GPR_DEBUG,
-            "found lb addrs size is: %" PRIdPTR
-            ". expected addrs size is %" PRIdPTR,
-            found_lb_addrs.size(), args->expected_addrs.size());
-    abort();
+    // Permit extra resolved addresses if "--allow_extra_addrs" was set.
+    if (!(FLAGS_allow_extra_addrs &&
+          found_lb_addrs.size() > args->expected_addrs.size())) {
+      gpr_log(GPR_DEBUG,
+              "found lb addrs size is: %" PRIdPTR
+              ". expected addrs size is %" PRIdPTR ". --allow_extra_addrs=%d.",
+              found_lb_addrs.size(), args->expected_addrs.size(),
+              FLAGS_allow_extra_addrs);
+      abort();
+    }
   }
-  EXPECT_THAT(args->expected_addrs, UnorderedElementsAreArray(found_lb_addrs));
+  for (size_t i = 0; i < args->expected_addrs.size(); i++) {
+    EXPECT_THAT(found_lb_addrs, ::testing::Contains(args->expected_addrs[i]));
+  }
   CheckServiceConfigResultLocked(channel_args, args);
   if (args->expected_service_config_string == "") {
     CheckLBPolicyResultLocked(channel_args, args);
diff --git a/test/cpp/performance/writes_per_rpc_test.cc b/test/cpp/performance/writes_per_rpc_test.cc
index 5faa7ba..0ea3181 100644
--- a/test/cpp/performance/writes_per_rpc_test.cc
+++ b/test/cpp/performance/writes_per_rpc_test.cc
@@ -207,13 +207,13 @@
         stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
     void* t;
     bool ok;
+    response_reader->Finish(&recv_response, &recv_status, tag(4));
     GPR_ASSERT(fixture->cq()->Next(&t, &ok));
     GPR_ASSERT(ok);
     GPR_ASSERT(t == tag(0) || t == tag(1));
     intptr_t slot = reinterpret_cast<intptr_t>(t);
     ServerEnv* senv = server_env[slot];
     senv->response_writer.Finish(send_response, Status::OK, tag(3));
-    response_reader->Finish(&recv_response, &recv_status, tag(4));
     for (int i = (1 << 3) | (1 << 4); i != 0;) {
       GPR_ASSERT(fixture->cq()->Next(&t, &ok));
       GPR_ASSERT(ok);
diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py
index bd40d0a..1ef8f65 100755
--- a/test/cpp/qps/gen_build_yaml.py
+++ b/test/cpp/qps/gen_build_yaml.py
@@ -101,26 +101,24 @@
     }
     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)],
+      'ci_platforms': ['linux'],
+      'platforms': ['linux'],
+      'flaky': False,
+      'language': 'c++',
+      'boringssl': True,
+      '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': 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', [])
   ]
-  # Disabled until https://github.com/grpc/grpc/issues/13122 is resolved.
-  # + [
-  #   {
-  #     'name': 'json_run_localhost',
-  #     'shortname': 'json_run_localhost:%s_low_thread_count' % scenario_json['name'],
-  #     'args': ['--scenarios_json', _scenario_json_string(scenario_json, True)],
-  #     'ci_platforms': ['linux'],
-  #     'platforms': ['linux'],
-  #     'flaky': False,
-  #     'language': 'c++',
-  #     'boringssl': True,
-  #     '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': 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/util/BUILD b/test/cpp/util/BUILD
index 4ac8572..f53bc7e 100644
--- a/test/cpp/util/BUILD
+++ b/test/cpp/util/BUILD
@@ -86,6 +86,7 @@
 
 grpc_cc_library(
     name = "channel_trace_proto_helper",
+    testonly = 1,
     srcs = [
         "channel_trace_proto_helper.cc",
     ],
diff --git a/tools/dockerfile/test/cxx_alpine_x64/Dockerfile b/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
index 8e5403f..c68a5dd 100644
--- a/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
@@ -39,23 +39,27 @@
 # Install Python packages from PyPI
 RUN pip install --upgrade pip==9.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
 
 # Google Cloud platform API libraries
 RUN pip install --upgrade google-api-python-client
 
-# Prepare ccache
-RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
-RUN ln -s /usr/bin/ccache /usr/local/bin/g++
-RUN ln -s /usr/bin/ccache /usr/local/bin/cc 
-RUN ln -s /usr/bin/ccache /usr/local/bin/c++
-
 # Install gflags
 RUN git clone https://github.com/gflags/gflags.git && cd gflags && git checkout v2.2.0
 RUN cd gflags && cmake . && make && make install
 RUN ln -s /usr/local/include/gflags /usr/include/gflags
 
-RUN mkdir -p /var/local/jenkins
+# Prepare ccache
+RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
+RUN ln -s /usr/bin/ccache /usr/local/bin/g++
+RUN ln -s /usr/bin/ccache /usr/local/bin/cc
+RUN ln -s /usr/bin/ccache /usr/local/bin/c++
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
+
+
+RUN mkdir /var/local/jenkins
+
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 2757114..85675e9 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1482,6 +1482,11 @@
 src/core/tsi/alts_transport_security.h \
 src/core/tsi/fake_transport_security.cc \
 src/core/tsi/fake_transport_security.h \
+src/core/tsi/ssl/session_cache/ssl_session.h \
+src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc \
+src/core/tsi/ssl/session_cache/ssl_session_cache.cc \
+src/core/tsi/ssl/session_cache/ssl_session_cache.h \
+src/core/tsi/ssl/session_cache/ssl_session_openssl.cc \
 src/core/tsi/ssl_transport_security.cc \
 src/core/tsi/ssl_transport_security.h \
 src/core/tsi/ssl_types.h \
diff --git a/tools/internal_ci/linux/grpc_android.cfg b/tools/internal_ci/linux/grpc_android.cfg
new file mode 100644
index 0000000..fb60777
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_android.cfg
@@ -0,0 +1,19 @@
+# Copyright 2018 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_android.sh"
+timeout_mins: 60
diff --git a/tools/internal_ci/linux/grpc_android.sh b/tools/internal_ci/linux/grpc_android.sh
new file mode 100755
index 0000000..1417b96
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_android.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+# Copyright 2018 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
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+git submodule update --init
+
+# TODO(ericgribkoff) Remove when this commit (already in master) is included in
+# next protobuf release
+cd third_party/protobuf
+git fetch
+git cherry-pick 7daa320065f3bea2b54bf983337d1724f153422d -m 1
+
+cd ../../examples/android/helloworld
+./gradlew build
diff --git a/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg b/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg
new file mode 100644
index 0000000..619e3ea
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg
@@ -0,0 +1,26 @@
+# 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_build_artifacts_extra.sh"
+timeout_mins: 240
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.xml"
+    regex: "github/grpc/reports/**"
+    regex: "github/grpc/artifacts/**"
+  }
+}
diff --git a/tools/internal_ci/linux/grpc_build_artifacts_extra.sh b/tools/internal_ci/linux/grpc_build_artifacts_extra.sh
new file mode 100755
index 0000000..718123d
--- /dev/null
+++ b/tools/internal_ci/linux/grpc_build_artifacts_extra.sh
@@ -0,0 +1,29 @@
+#!/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.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+set +ex
+[[ -s /etc/profile.d/rvm.sh ]] && . /etc/profile.d/rvm.sh
+set -e  # rvm commands are very verbose
+rvm --default use ruby-2.4.1
+set -ex
+
+tools/run_tests/task_runner.py -f artifact linux_extra armv7 -j 6
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
index 83d75ec..aa45f7f 100644
--- a/tools/interop_matrix/client_matrix.py
+++ b/tools/interop_matrix/client_matrix.py
@@ -84,6 +84,9 @@
         {
             'v1.9.1': None
         },
+        {
+            'v1.10.0': None
+        },
     ],
     'go': [
         {
@@ -149,7 +152,7 @@
             'v1.9.1': None
         },
         {
-            'v1.10.0': None
+            'v1.10.1': None
         },
     ],
     'python': [
@@ -180,6 +183,9 @@
         {
             'v1.9.1': None
         },
+        {
+            'v1.10.0': None
+        },
     ],
     'node': [
         {
@@ -200,7 +206,19 @@
         {
             'v1.6.6': None
         },
-        #{'v1.7.1': None}, Failing tests
+        # TODO: https://github.com/grpc/grpc-node/issues/235.
+        #{
+        #    'v1.7.2': None
+        #},
+        {
+            'v1.8.4': None
+        },
+        {
+            'v1.9.1': None
+        },
+        {
+            'v1.10.0': None
+        },
     ],
     'ruby': [
         {
@@ -235,6 +253,9 @@
         {
             'v1.9.1': None
         },
+        {
+            'v1.10.0': None
+        },
     ],
     'php': [
         {
@@ -264,6 +285,9 @@
         {
             'v1.9.1': None
         },
+        {
+            'v1.10.0': None
+        },
     ],
     'csharp': [
         #{'v1.0.1': None},
@@ -291,5 +315,26 @@
         {
             'v1.9.1': None
         },
+        {
+            'v1.10.0': None
+        },
     ],
 }
+
+# This matrix lists the version of testcases to use for a release. As new
+# releases come out, some older docker commands for running tests need to be
+# changed, hence the need for specifying which commands to use for a
+# particular version in some cases. If not specified, xxx__master file will be
+# used. For example, all java versions will run the commands in java__master.
+# The testcases files exist under the testcases directory.
+TESTCASES_VERSION_MATRIX = {
+    'node_v1.0.1': 'node__v1.0.1',
+    'node_v1.1.4': 'node__v1.1.4',
+    'node_v1.2.5': 'node__v1.1.4',
+    'node_v1.3.9': 'node__v1.1.4',
+    'node_v1.4.2': 'node__v1.1.4',
+    'node_v1.6.6': 'node__v1.1.4',
+    'ruby_v1.0.1': 'ruby__v1.0.1',
+    'csharp_v1.1.4': 'csharp__v1.1.4',
+    'csharp_v1.2.5': 'csharp__v1.1.4',
+}
diff --git a/tools/interop_matrix/run_interop_matrix_tests.py b/tools/interop_matrix/run_interop_matrix_tests.py
index eb1e021..57120d0 100755
--- a/tools/interop_matrix/run_interop_matrix_tests.py
+++ b/tools/interop_matrix/run_interop_matrix_tests.py
@@ -66,15 +66,12 @@
     nargs='+',
     default=['all'],
     help='Languages to test')
-
 argp.add_argument(
     '--keep',
     action='store_true',
     help='keep the created local images after finishing the tests.')
-
 argp.add_argument(
     '--report_file', default='report.xml', help='The result file to create.')
-
 argp.add_argument(
     '--allow_flakes',
     default=False,
@@ -150,14 +147,17 @@
 # caches test cases (list of JobSpec) loaded from file.  Keyed by lang and runtime.
 def find_test_cases(lang, runtime, 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')
-    testcase_release = release
+    testcase_dir = os.path.join(os.path.dirname(__file__), 'testcases')
     filename_prefix = lang
     if lang == 'csharp':
         filename_prefix = runtime
-    if not os.path.exists(file_tmpl % (filename_prefix, release)):
-        testcase_release = 'master'
-    testcases = file_tmpl % (filename_prefix, testcase_release)
+    # Check to see if we need to use a particular version of test cases.
+    lang_version = '%s_%s' % (filename_prefix, release)
+    if lang_version in client_matrix.TESTCASES_VERSION_MATRIX:
+        testcases = os.path.join(
+            testcase_dir, client_matrix.TESTCASES_VERSION_MATRIX[lang_version])
+    else:
+        testcases = os.path.join(testcase_dir, '%s__master' % filename_prefix)
 
     job_spec_list = []
     try:
diff --git a/tools/interop_matrix/testcases/csharp__v1.2.5 b/tools/interop_matrix/testcases/csharp__v1.2.5
deleted file mode 100644
index f4a6fb1..0000000
--- a/tools/interop_matrix/testcases/csharp__v1.2.5
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-echo "Testing ${docker_image:=grpc_interop_csharp:a95229ca-d387-4127-ad48-69a7464e23b8}"
-docker run -i --rm=true -w /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
-docker run -i --rm=true -w /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream"
-docker run -i --rm=true -w /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming"
-docker run -i --rm=true -w /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming"
-docker run -i --rm=true -w /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug --net=host $docker_image bash -c "mono Grpc.IntegrationTesting.Client.exe --server_host=grpc-test4.sandbox.googleapis.com --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/node__master b/tools/interop_matrix/testcases/node__master
index 9e31fbf..588ca95 100755
--- a/tools/interop_matrix/testcases/node__master
+++ b/tools/interop_matrix/testcases/node__master
@@ -1,20 +1,20 @@
 #!/bin/bash
 echo "Testing ${docker_image:=grpc_interop_node:1415ecbf-5d0f-423e-8c2c-e0cb6d154e73}"
-docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
+docker run -i --rm=true -w /var/local/git/grpc-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream"
+docker run -i --rm=true -w /var/local/git/grpc-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming"
+docker run -i --rm=true -w /var/local/git/grpc-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming"
+docker run -i --rm=true -w /var/local/git/grpc-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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-node --net=host $docker_image bash -c "packages/grpc-native-core/deps/grpc/tools/run_tests/interop/with_nvm.sh node --require ./test/fixtures/native_native test/interop/interop_client.js --server_host=grpc-test4.sandbox.googleapis.com --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/node__v1.1.4 b/tools/interop_matrix/testcases/node__v1.1.4
new file mode 100644
index 0000000..99ea2f0
--- /dev/null
+++ b/tools/interop_matrix/testcases/node__v1.1.4
@@ -0,0 +1,20 @@
+#!/bin/bash
+echo "Testing ${docker_image:=grpc_interop_node:1415ecbf-5d0f-423e-8c2c-e0cb6d154e73}"
+docker run -i --rm=true -w /var/local/git/grpc --net=host $docker_image bash -c "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=216.239.32.254 --server_host_override=grpc-test.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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=216.239.32.254 --server_host_override=grpc-test.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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=216.239.32.254 --server_host_override=grpc-test.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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --server_host=216.239.32.254 --server_host_override=grpc-test.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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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 "tools/run_tests/interop/with_nvm.sh node src/node/interop/interop_client.js --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/latency_profile/profile_analyzer.py b/tools/profiling/latency_profile/profile_analyzer.py
index d4d14ef..cdc2f1c 100755
--- a/tools/profiling/latency_profile/profile_analyzer.py
+++ b/tools/profiling/latency_profile/profile_analyzer.py
@@ -184,24 +184,23 @@
 
 def percentile(N, percent, key=lambda x: x):
     """
-    Find the percentile of a list of values.
+    Find the percentile of an already sorted list of values.
 
-    @parameter N - is a list of values. Note N MUST BE already sorted.
-    @parameter percent - a float value from 0.0 to 1.0.
+    @parameter N - is a list of values. MUST be already sorted.
+    @parameter percent - a float value from [0.0,1.0].
     @parameter key - optional key function to compute value from each element of N.
 
     @return - the percentile of the values
     """
     if not N:
         return None
-    k = (len(N) - 1) * percent
-    f = math.floor(k)
-    c = math.ceil(k)
-    if f == c:
-        return key(N[int(k)])
-    d0 = key(N[int(f)]) * (c - k)
-    d1 = key(N[int(c)]) * (k - f)
-    return d0 + d1
+    float_idx = (len(N) - 1) * percent
+    idx = int(float_idx)
+    result = key(N[idx])
+    if idx < len(N) - 1:
+        # interpolate with the next element's value
+        result += (float_idx - idx) * (key(N[idx + 1]) - key(N[idx]))
+    return result
 
 
 def tidy_tag(tag):
diff --git a/tools/run_tests/artifacts/artifact_targets.py b/tools/run_tests/artifacts/artifact_targets.py
index 53c7e17..ca25c2a 100644
--- a/tools/run_tests/artifacts/artifact_targets.py
+++ b/tools/run_tests/artifacts/artifact_targets.py
@@ -317,6 +317,7 @@
                     self.name,
                     ['tools/run_tests/artifacts/build_artifact_protoc.sh'],
                     environ=environ,
+                    timeout_seconds=60 * 60,
                     use_workspace=True)
         else:
             generator = 'Visual Studio 14 2015 Win64' if self.arch == 'x64' else 'Visual Studio 14 2015'
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 08dc3fa..3ebd8c1 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -3704,6 +3704,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_session_reuse_test", 
+    "src": [
+      "test/core/end2end/end2end_tests.h", 
+      "test/core/end2end/h2_ssl_session_reuse_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
       "grpc++_test_util", 
       "grpc_test_util"
     ], 
@@ -6664,8 +6686,12 @@
     "deps": [
       "gpr", 
       "grpc_base", 
+      "grpc_base_headers", 
+      "grpc_deadline_filter", 
+      "grpc_message_size_filter", 
       "grpc_server_load_reporting", 
       "grpc_transport_chttp2_client_secure", 
+      "grpc_transport_chttp2_server_secure", 
       "grpc_transport_cronet_client_secure"
     ], 
     "headers": [], 
@@ -10426,6 +10452,8 @@
     "headers": [
       "src/core/tsi/alts_transport_security.h", 
       "src/core/tsi/fake_transport_security.h", 
+      "src/core/tsi/ssl/session_cache/ssl_session.h", 
+      "src/core/tsi/ssl/session_cache/ssl_session_cache.h", 
       "src/core/tsi/ssl_transport_security.h", 
       "src/core/tsi/ssl_types.h", 
       "src/core/tsi/transport_security_grpc.h"
@@ -10438,6 +10466,11 @@
       "src/core/tsi/alts_transport_security.h", 
       "src/core/tsi/fake_transport_security.cc", 
       "src/core/tsi/fake_transport_security.h", 
+      "src/core/tsi/ssl/session_cache/ssl_session.h", 
+      "src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc", 
+      "src/core/tsi/ssl/session_cache/ssl_session_cache.cc", 
+      "src/core/tsi/ssl/session_cache/ssl_session_cache.h", 
+      "src/core/tsi/ssl/session_cache/ssl_session_openssl.cc", 
       "src/core/tsi/ssl_transport_security.cc", 
       "src/core/tsi/ssl_transport_security.h", 
       "src/core/tsi/ssl_types.h", 
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 8a99792..2770992 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -4288,6 +4288,30 @@
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
+    "name": "h2_ssl_session_reuse_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": "health_service_end2end_test", 
     "platforms": [
       "linux", 
@@ -59684,6 +59708,3094 @@
   }, 
   {
     "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", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_1channel_100rpcs_1MB_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_1channel_1MB_low_thread_count", 
+    "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", 
+      "noexcept", 
+      "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_1mps_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_10mps_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_1channel_1MBmsg_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_64KBmsg_secure_low_thread_count", 
+    "timeout_seconds": 600
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1cq_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\": 1000000}, \"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\": 1000000, \"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", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_1cq_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_secure_low_thread_count", 
+    "timeout_seconds": 600
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1cq_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\": 1000000, \"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\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 1000000, \"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", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_1cq_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_secure_low_thread_count", 
+    "timeout_seconds": 600
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_1cq_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\": 1000000, \"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\": 13, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 1000000, \"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", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_1cq_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_secure_1MB_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_1mps_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_10mps_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_1mps_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_10mps_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_client_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_client_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_server_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_server_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_ping_pong_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_qps_unconstrained_secure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_1mps_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_10mps_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_1channel_1MBmsg_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_64KBmsg_insecure_low_thread_count", 
+    "timeout_seconds": 600
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_1cq_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\": 1000000}, \"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\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 1000000, \"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", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_1cq_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_2waysharedcq_insecure_low_thread_count", 
+    "timeout_seconds": 600
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_1cq_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\": 1000000, \"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\": 13, \"rpc_type\": \"STREAMING\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 1000000, \"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", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_1cq_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_2waysharedcq_insecure_low_thread_count", 
+    "timeout_seconds": 600
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_1cq_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\": 1000000, \"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\": 13, \"rpc_type\": \"UNARY\", \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"threads_per_cq\": 1000000, \"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", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_1cq_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_2waysharedcq_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_client_unary_1channel_64wide_128Breq_8MBresp_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [
+      "poll-cv"
+    ], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_insecure_1MB_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_1mps_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_10mps_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_1mps_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_10mps_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_client_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_client_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_server_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 64, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_from_server_qps_unconstrained_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": 2, 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_ping_pong_insecure_low_thread_count", 
+    "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"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "noexcept", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure_low_thread_count", 
+    "timeout_seconds": 600
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/00.bin"
     ], 
     "ci_platforms": [
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 5a1c0f5..ba4ab3b 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -406,11 +406,7 @@
         return {}
 
     def unimplemented_test_cases(self):
-        return (
-            _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _AUTH_TEST_CASES + [
-                'cancel_after_begin', 'cancel_after_first_response',
-                'timeout_on_sleeping_server'
-            ])
+        return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING
 
     def unimplemented_test_cases_server(self):
         return []