diff --git a/Makefile b/Makefile
index 53d0696a20feba02c2252931a9cade765513f6ce..419715c28256fbeef67c604279b8518d5fd49798 100644
--- a/Makefile
+++ b/Makefile
@@ -312,7 +312,7 @@ E = @echo
 Q = @
 endif
 
-VERSION = 0.11.0.0
+VERSION = 0.12.0.0
 
 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
 CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -879,6 +879,7 @@ grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
 interop_client: $(BINDIR)/$(CONFIG)/interop_client
 interop_server: $(BINDIR)/$(CONFIG)/interop_server
 interop_test: $(BINDIR)/$(CONFIG)/interop_test
+metrics_client: $(BINDIR)/$(CONFIG)/metrics_client
 mock_test: $(BINDIR)/$(CONFIG)/mock_test
 qps_driver: $(BINDIR)/$(CONFIG)/qps_driver
 qps_interarrival_test: $(BINDIR)/$(CONFIG)/qps_interarrival_test
@@ -916,6 +917,7 @@ h2_compress_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_compress_disappeari
 h2_compress_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_compress_empty_batch_test
 h2_compress_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_compress_graceful_server_shutdown_test
 h2_compress_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_test
+h2_compress_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_compress_hpack_size_test
 h2_compress_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_test
 h2_compress_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_compress_large_metadata_test
 h2_compress_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_compress_max_concurrent_streams_test
@@ -951,6 +953,7 @@ h2_fakesec_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_fakesec_disappearing
 h2_fakesec_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_fakesec_empty_batch_test
 h2_fakesec_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_fakesec_graceful_server_shutdown_test
 h2_fakesec_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_fakesec_high_initial_seqno_test
+h2_fakesec_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_fakesec_hpack_size_test
 h2_fakesec_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_fakesec_invoke_large_request_test
 h2_fakesec_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_fakesec_large_metadata_test
 h2_fakesec_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_fakesec_max_concurrent_streams_test
@@ -986,6 +989,7 @@ h2_full_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_full_disappearing_serve
 h2_full_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_full_empty_batch_test
 h2_full_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_full_graceful_server_shutdown_test
 h2_full_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_test
+h2_full_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_full_hpack_size_test
 h2_full_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_test
 h2_full_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_full_large_metadata_test
 h2_full_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_full_max_concurrent_streams_test
@@ -1021,6 +1025,7 @@ h2_full+poll_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_full+poll_disappea
 h2_full+poll_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_full+poll_empty_batch_test
 h2_full+poll_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_full+poll_graceful_server_shutdown_test
 h2_full+poll_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_test
+h2_full+poll_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_test
 h2_full+poll_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_test
 h2_full+poll_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_full+poll_large_metadata_test
 h2_full+poll_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_full+poll_max_concurrent_streams_test
@@ -1056,6 +1061,7 @@ h2_oauth2_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_oauth2_disappearing_s
 h2_oauth2_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_oauth2_empty_batch_test
 h2_oauth2_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_oauth2_graceful_server_shutdown_test
 h2_oauth2_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_oauth2_high_initial_seqno_test
+h2_oauth2_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_oauth2_hpack_size_test
 h2_oauth2_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_oauth2_invoke_large_request_test
 h2_oauth2_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_oauth2_large_metadata_test
 h2_oauth2_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_oauth2_max_concurrent_streams_test
@@ -1119,6 +1125,7 @@ h2_sockpair_compressed_payload_test: $(BINDIR)/$(CONFIG)/h2_sockpair_compressed_
 h2_sockpair_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_sockpair_empty_batch_test
 h2_sockpair_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_sockpair_graceful_server_shutdown_test
 h2_sockpair_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_test
+h2_sockpair_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_test
 h2_sockpair_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_test
 h2_sockpair_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_sockpair_large_metadata_test
 h2_sockpair_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_sockpair_max_concurrent_streams_test
@@ -1181,6 +1188,7 @@ h2_sockpair_1byte_compressed_payload_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte
 h2_sockpair_1byte_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_empty_batch_test
 h2_sockpair_1byte_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_graceful_server_shutdown_test
 h2_sockpair_1byte_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_test
+h2_sockpair_1byte_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_test
 h2_sockpair_1byte_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_test
 h2_sockpair_1byte_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_large_metadata_test
 h2_sockpair_1byte_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_concurrent_streams_test
@@ -1215,6 +1223,7 @@ h2_ssl_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_ssl_disappearing_server_
 h2_ssl_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_ssl_empty_batch_test
 h2_ssl_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_ssl_graceful_server_shutdown_test
 h2_ssl_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_ssl_high_initial_seqno_test
+h2_ssl_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_ssl_hpack_size_test
 h2_ssl_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_ssl_invoke_large_request_test
 h2_ssl_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_ssl_large_metadata_test
 h2_ssl_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_ssl_max_concurrent_streams_test
@@ -1250,6 +1259,7 @@ h2_ssl+poll_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_disappeari
 h2_ssl+poll_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_empty_batch_test
 h2_ssl+poll_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_graceful_server_shutdown_test
 h2_ssl+poll_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_high_initial_seqno_test
+h2_ssl+poll_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_hpack_size_test
 h2_ssl+poll_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_invoke_large_request_test
 h2_ssl+poll_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_large_metadata_test
 h2_ssl+poll_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_ssl+poll_max_concurrent_streams_test
@@ -1316,6 +1326,7 @@ h2_uchannel_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_uchannel_disappeari
 h2_uchannel_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_uchannel_empty_batch_test
 h2_uchannel_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_uchannel_graceful_server_shutdown_test
 h2_uchannel_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_test
+h2_uchannel_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_test
 h2_uchannel_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_test
 h2_uchannel_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_uchannel_large_metadata_test
 h2_uchannel_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_uchannel_max_concurrent_streams_test
@@ -1350,6 +1361,7 @@ h2_uds_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_uds_disappearing_server_
 h2_uds_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_uds_empty_batch_test
 h2_uds_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_uds_graceful_server_shutdown_test
 h2_uds_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_test
+h2_uds_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_uds_hpack_size_test
 h2_uds_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_test
 h2_uds_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_uds_large_metadata_test
 h2_uds_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_uds_max_concurrent_streams_test
@@ -1384,6 +1396,7 @@ h2_uds+poll_disappearing_server_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_disappeari
 h2_uds+poll_empty_batch_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_empty_batch_test
 h2_uds+poll_graceful_server_shutdown_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_graceful_server_shutdown_test
 h2_uds+poll_high_initial_seqno_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_test
+h2_uds+poll_hpack_size_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_test
 h2_uds+poll_invoke_large_request_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_test
 h2_uds+poll_large_metadata_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_large_metadata_test
 h2_uds+poll_max_concurrent_streams_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_max_concurrent_streams_test
@@ -1418,6 +1431,7 @@ h2_compress_disappearing_server_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_disa
 h2_compress_empty_batch_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_empty_batch_nosec_test
 h2_compress_graceful_server_shutdown_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_graceful_server_shutdown_nosec_test
 h2_compress_high_initial_seqno_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_nosec_test
+h2_compress_hpack_size_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_hpack_size_nosec_test
 h2_compress_invoke_large_request_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_nosec_test
 h2_compress_large_metadata_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_large_metadata_nosec_test
 h2_compress_max_concurrent_streams_nosec_test: $(BINDIR)/$(CONFIG)/h2_compress_max_concurrent_streams_nosec_test
@@ -1452,6 +1466,7 @@ h2_full_disappearing_server_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_disappearing
 h2_full_empty_batch_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_empty_batch_nosec_test
 h2_full_graceful_server_shutdown_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_graceful_server_shutdown_nosec_test
 h2_full_high_initial_seqno_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_nosec_test
+h2_full_hpack_size_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_hpack_size_nosec_test
 h2_full_invoke_large_request_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_nosec_test
 h2_full_large_metadata_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_large_metadata_nosec_test
 h2_full_max_concurrent_streams_nosec_test: $(BINDIR)/$(CONFIG)/h2_full_max_concurrent_streams_nosec_test
@@ -1486,6 +1501,7 @@ h2_full+poll_disappearing_server_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_di
 h2_full+poll_empty_batch_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_empty_batch_nosec_test
 h2_full+poll_graceful_server_shutdown_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_graceful_server_shutdown_nosec_test
 h2_full+poll_high_initial_seqno_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_nosec_test
+h2_full+poll_hpack_size_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_nosec_test
 h2_full+poll_invoke_large_request_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_nosec_test
 h2_full+poll_large_metadata_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_large_metadata_nosec_test
 h2_full+poll_max_concurrent_streams_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+poll_max_concurrent_streams_nosec_test
@@ -1547,6 +1563,7 @@ h2_sockpair_compressed_payload_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_compr
 h2_sockpair_empty_batch_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_empty_batch_nosec_test
 h2_sockpair_graceful_server_shutdown_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_graceful_server_shutdown_nosec_test
 h2_sockpair_high_initial_seqno_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_nosec_test
+h2_sockpair_hpack_size_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_nosec_test
 h2_sockpair_invoke_large_request_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_nosec_test
 h2_sockpair_large_metadata_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_large_metadata_nosec_test
 h2_sockpair_max_concurrent_streams_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_max_concurrent_streams_nosec_test
@@ -1607,6 +1624,7 @@ h2_sockpair_1byte_compressed_payload_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair
 h2_sockpair_1byte_empty_batch_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_empty_batch_nosec_test
 h2_sockpair_1byte_graceful_server_shutdown_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_graceful_server_shutdown_nosec_test
 h2_sockpair_1byte_high_initial_seqno_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_nosec_test
+h2_sockpair_1byte_hpack_size_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_nosec_test
 h2_sockpair_1byte_invoke_large_request_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_nosec_test
 h2_sockpair_1byte_large_metadata_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_large_metadata_nosec_test
 h2_sockpair_1byte_max_concurrent_streams_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_concurrent_streams_nosec_test
@@ -1640,6 +1658,7 @@ h2_uchannel_disappearing_server_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_disa
 h2_uchannel_empty_batch_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_empty_batch_nosec_test
 h2_uchannel_graceful_server_shutdown_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_graceful_server_shutdown_nosec_test
 h2_uchannel_high_initial_seqno_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_nosec_test
+h2_uchannel_hpack_size_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_nosec_test
 h2_uchannel_invoke_large_request_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_nosec_test
 h2_uchannel_large_metadata_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_large_metadata_nosec_test
 h2_uchannel_max_concurrent_streams_nosec_test: $(BINDIR)/$(CONFIG)/h2_uchannel_max_concurrent_streams_nosec_test
@@ -1673,6 +1692,7 @@ h2_uds_disappearing_server_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_disappearing_s
 h2_uds_empty_batch_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_empty_batch_nosec_test
 h2_uds_graceful_server_shutdown_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_graceful_server_shutdown_nosec_test
 h2_uds_high_initial_seqno_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_nosec_test
+h2_uds_hpack_size_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_hpack_size_nosec_test
 h2_uds_invoke_large_request_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_nosec_test
 h2_uds_large_metadata_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_large_metadata_nosec_test
 h2_uds_max_concurrent_streams_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_max_concurrent_streams_nosec_test
@@ -1706,6 +1726,7 @@ h2_uds+poll_disappearing_server_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_disa
 h2_uds+poll_empty_batch_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_empty_batch_nosec_test
 h2_uds+poll_graceful_server_shutdown_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_graceful_server_shutdown_nosec_test
 h2_uds+poll_high_initial_seqno_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_nosec_test
+h2_uds+poll_hpack_size_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_nosec_test
 h2_uds+poll_invoke_large_request_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_nosec_test
 h2_uds+poll_large_metadata_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_large_metadata_nosec_test
 h2_uds+poll_max_concurrent_streams_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds+poll_max_concurrent_streams_nosec_test
@@ -1822,7 +1843,7 @@ plugins: $(PROTOC_PLUGINS)
 
 privatelibs: privatelibs_c privatelibs_cxx
 
-privatelibs_c:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_compress.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_fakesec.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full+poll.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_oauth2.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_proxy.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair+trace.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair_1byte.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl+poll.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl_proxy.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uchannel.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_test_binary_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_call_creds.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_client_done.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_with_status.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_channel_connectivity.a $(LIBDIR)/$(CONFIG)/libend2end_test_compressed_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_default_host.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server.a $(LIBDIR)/$(CONFIG)/libend2end_test_empty_batch.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown.a $(LIBDIR)/$(CONFIG)/libend2end_test_high_initial_seqno.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_large_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_message_length.a $(LIBDIR)/$(CONFIG)/libend2end_test_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_negative_deadline.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op.a $(LIBDIR)/$(CONFIG)/libend2end_test_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming.a $(LIBDIR)/$(CONFIG)/libend2end_test_registered_call.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_flags.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_server_finishes_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_shutdown_finishes_calls.a $(LIBDIR)/$(CONFIG)/libend2end_test_shutdown_finishes_tags.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_trailing_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a
+privatelibs_c:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_compress.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_fakesec.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full+poll.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_oauth2.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_proxy.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair+trace.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair_1byte.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl+poll.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl_proxy.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uchannel.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_test_binary_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_call_creds.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_client_done.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_with_status.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_channel_connectivity.a $(LIBDIR)/$(CONFIG)/libend2end_test_compressed_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_default_host.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server.a $(LIBDIR)/$(CONFIG)/libend2end_test_empty_batch.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown.a $(LIBDIR)/$(CONFIG)/libend2end_test_high_initial_seqno.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_large_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_message_length.a $(LIBDIR)/$(CONFIG)/libend2end_test_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_negative_deadline.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op.a $(LIBDIR)/$(CONFIG)/libend2end_test_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming.a $(LIBDIR)/$(CONFIG)/libend2end_test_registered_call.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_flags.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_server_finishes_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_shutdown_finishes_calls.a $(LIBDIR)/$(CONFIG)/libend2end_test_shutdown_finishes_tags.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_trailing_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a
 pc_gpr: $(LIBDIR)/$(CONFIG)/pkgconfig/gpr.pc
 
 pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc
@@ -1850,9 +1871,9 @@ endif
 
 buildtests: buildtests_c buildtests_cxx buildtests_zookeeper
 
-buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/compression_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/endpoint_pair_test $(BINDIR)/$(CONFIG)/fd_conservation_posix_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_cpu_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_tls_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_auth_context_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_args_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test $(BINDIR)/$(CONFIG)/grpc_security_connector_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/lb_policies_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/multiple_server_queues_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/timer_heap_test $(BINDIR)/$(CONFIG)/timer_list_test $(BINDIR)/$(CONFIG)/timers_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/udp_server_test $(BINDIR)/$(CONFIG)/uri_parser_test $(BINDIR)/$(CONFIG)/workqueue_test $(BINDIR)/$(CONFIG)/h2_compress_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_compress_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_compress_call_creds_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_compress_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_compress_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_compress_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_compress_default_host_test $(BINDIR)/$(CONFIG)/h2_compress_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_compress_empty_batch_test $(BINDIR)/$(CONFIG)/h2_compress_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_compress_large_metadata_test $(BINDIR)/$(CONFIG)/h2_compress_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_compress_max_message_length_test $(BINDIR)/$(CONFIG)/h2_compress_metadata_test $(BINDIR)/$(CONFIG)/h2_compress_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_compress_no_op_test $(BINDIR)/$(CONFIG)/h2_compress_payload_test $(BINDIR)/$(CONFIG)/h2_compress_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_compress_registered_call_test $(BINDIR)/$(CONFIG)/h2_compress_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_compress_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_compress_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_compress_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_compress_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_compress_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_compress_simple_request_test $(BINDIR)/$(CONFIG)/h2_compress_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_fakesec_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_fakesec_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_fakesec_call_creds_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_fakesec_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_fakesec_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_fakesec_default_host_test $(BINDIR)/$(CONFIG)/h2_fakesec_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_fakesec_empty_batch_test $(BINDIR)/$(CONFIG)/h2_fakesec_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_fakesec_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_fakesec_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_large_metadata_test $(BINDIR)/$(CONFIG)/h2_fakesec_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_fakesec_max_message_length_test $(BINDIR)/$(CONFIG)/h2_fakesec_metadata_test $(BINDIR)/$(CONFIG)/h2_fakesec_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_fakesec_no_op_test $(BINDIR)/$(CONFIG)/h2_fakesec_payload_test $(BINDIR)/$(CONFIG)/h2_fakesec_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_fakesec_registered_call_test $(BINDIR)/$(CONFIG)/h2_fakesec_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_fakesec_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_fakesec_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_fakesec_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_fakesec_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_simple_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_full_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_full_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_full_call_creds_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_full_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_full_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_full_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_full_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_full_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_full_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_full_default_host_test $(BINDIR)/$(CONFIG)/h2_full_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_full_empty_batch_test $(BINDIR)/$(CONFIG)/h2_full_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_full_large_metadata_test $(BINDIR)/$(CONFIG)/h2_full_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_full_max_message_length_test $(BINDIR)/$(CONFIG)/h2_full_metadata_test $(BINDIR)/$(CONFIG)/h2_full_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_full_no_op_test $(BINDIR)/$(CONFIG)/h2_full_payload_test $(BINDIR)/$(CONFIG)/h2_full_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_full_registered_call_test $(BINDIR)/$(CONFIG)/h2_full_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_full_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_full_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_full_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_full_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_full_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_full_simple_request_test $(BINDIR)/$(CONFIG)/h2_full_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_full+poll_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_full+poll_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_full+poll_call_creds_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_full+poll_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_full+poll_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_full+poll_default_host_test $(BINDIR)/$(CONFIG)/h2_full+poll_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_full+poll_empty_batch_test $(BINDIR)/$(CONFIG)/h2_full+poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_large_metadata_test $(BINDIR)/$(CONFIG)/h2_full+poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_full+poll_max_message_length_test $(BINDIR)/$(CONFIG)/h2_full+poll_metadata_test $(BINDIR)/$(CONFIG)/h2_full+poll_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_full+poll_no_op_test $(BINDIR)/$(CONFIG)/h2_full+poll_payload_test $(BINDIR)/$(CONFIG)/h2_full+poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_full+poll_registered_call_test $(BINDIR)/$(CONFIG)/h2_full+poll_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_full+poll_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_full+poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_full+poll_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_full+poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_simple_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_oauth2_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_oauth2_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_oauth2_call_creds_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_oauth2_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_oauth2_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_oauth2_default_host_test $(BINDIR)/$(CONFIG)/h2_oauth2_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_oauth2_empty_batch_test $(BINDIR)/$(CONFIG)/h2_oauth2_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_oauth2_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_oauth2_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_large_metadata_test $(BINDIR)/$(CONFIG)/h2_oauth2_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_oauth2_max_message_length_test $(BINDIR)/$(CONFIG)/h2_oauth2_metadata_test $(BINDIR)/$(CONFIG)/h2_oauth2_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_oauth2_no_op_test $(BINDIR)/$(CONFIG)/h2_oauth2_payload_test $(BINDIR)/$(CONFIG)/h2_oauth2_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_oauth2_registered_call_test $(BINDIR)/$(CONFIG)/h2_oauth2_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_oauth2_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_oauth2_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_oauth2_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_oauth2_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_simple_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_proxy_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_proxy_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_proxy_call_creds_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_proxy_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_proxy_default_host_test $(BINDIR)/$(CONFIG)/h2_proxy_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_proxy_empty_batch_test $(BINDIR)/$(CONFIG)/h2_proxy_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_proxy_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_proxy_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_proxy_large_metadata_test $(BINDIR)/$(CONFIG)/h2_proxy_max_message_length_test $(BINDIR)/$(CONFIG)/h2_proxy_metadata_test $(BINDIR)/$(CONFIG)/h2_proxy_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_proxy_no_op_test $(BINDIR)/$(CONFIG)/h2_proxy_payload_test $(BINDIR)/$(CONFIG)/h2_proxy_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_proxy_registered_call_test $(BINDIR)/$(CONFIG)/h2_proxy_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_proxy_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_proxy_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_proxy_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_proxy_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_proxy_simple_request_test $(BINDIR)/$(CONFIG)/h2_proxy_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_sockpair_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_call_creds_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_sockpair_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_empty_batch_test $(BINDIR)/$(CONFIG)/h2_sockpair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_large_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_sockpair_max_message_length_test $(BINDIR)/$(CONFIG)/h2_sockpair_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_sockpair_no_op_test $(BINDIR)/$(CONFIG)/h2_sockpair_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_sockpair_registered_call_test $(BINDIR)/$(CONFIG)/h2_sockpair_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_sockpair_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_sockpair_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_sockpair_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_call_creds_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_empty_batch_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_large_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_max_message_length_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_no_op_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_registered_call_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_call_creds_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_empty_batch_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_large_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_message_length_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_no_op_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_registered_call_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_ssl_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_call_creds_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_ssl_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_ssl_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_default_host_test $(BINDIR)/$(CONFIG)/h2_ssl_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_ssl_empty_batch_test $(BINDIR)/$(CONFIG)/h2_ssl_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_ssl_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_ssl_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_ssl_large_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_ssl_max_message_length_test $(BINDIR)/$(CONFIG)/h2_ssl_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_ssl_no_op_test $(BINDIR)/$(CONFIG)/h2_ssl_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_ssl_registered_call_test $(BINDIR)/$(CONFIG)/h2_ssl_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_ssl_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_ssl_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_ssl_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_ssl_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_ssl_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_call_creds_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_default_host_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_empty_batch_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_large_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_max_message_length_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_no_op_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_payload_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_registered_call_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_call_creds_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_default_host_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_empty_batch_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_large_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_max_message_length_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_no_op_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_registered_call_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_uchannel_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_uchannel_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_uchannel_call_creds_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_uchannel_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_uchannel_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_uchannel_default_host_test $(BINDIR)/$(CONFIG)/h2_uchannel_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_uchannel_empty_batch_test $(BINDIR)/$(CONFIG)/h2_uchannel_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_large_metadata_test $(BINDIR)/$(CONFIG)/h2_uchannel_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_uchannel_max_message_length_test $(BINDIR)/$(CONFIG)/h2_uchannel_metadata_test $(BINDIR)/$(CONFIG)/h2_uchannel_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_uchannel_no_op_test $(BINDIR)/$(CONFIG)/h2_uchannel_payload_test $(BINDIR)/$(CONFIG)/h2_uchannel_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_uchannel_registered_call_test $(BINDIR)/$(CONFIG)/h2_uchannel_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_uchannel_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_uchannel_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_uchannel_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_uchannel_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_simple_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_uds_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_uds_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_uds_call_creds_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_uds_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_uds_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_uds_empty_batch_test $(BINDIR)/$(CONFIG)/h2_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_uds_large_metadata_test $(BINDIR)/$(CONFIG)/h2_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_uds_max_message_length_test $(BINDIR)/$(CONFIG)/h2_uds_metadata_test $(BINDIR)/$(CONFIG)/h2_uds_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_uds_no_op_test $(BINDIR)/$(CONFIG)/h2_uds_payload_test $(BINDIR)/$(CONFIG)/h2_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_uds_registered_call_test $(BINDIR)/$(CONFIG)/h2_uds_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_uds_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_uds_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_uds_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_uds_simple_request_test $(BINDIR)/$(CONFIG)/h2_uds_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_uds+poll_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_uds+poll_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_uds+poll_call_creds_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_uds+poll_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_uds+poll_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_uds+poll_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_uds+poll_empty_batch_test $(BINDIR)/$(CONFIG)/h2_uds+poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_large_metadata_test $(BINDIR)/$(CONFIG)/h2_uds+poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_uds+poll_max_message_length_test $(BINDIR)/$(CONFIG)/h2_uds+poll_metadata_test $(BINDIR)/$(CONFIG)/h2_uds+poll_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_uds+poll_no_op_test $(BINDIR)/$(CONFIG)/h2_uds+poll_payload_test $(BINDIR)/$(CONFIG)/h2_uds+poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_uds+poll_registered_call_test $(BINDIR)/$(CONFIG)/h2_uds+poll_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_uds+poll_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_uds+poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_uds+poll_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_uds+poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_simple_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_compress_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_full_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_full_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_full_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_full_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_full_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_full_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_full_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_full_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_full_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_full_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_full_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_full_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_full_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_full_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_full_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
+buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/compression_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/endpoint_pair_test $(BINDIR)/$(CONFIG)/fd_conservation_posix_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_cpu_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_tls_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_auth_context_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_args_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test $(BINDIR)/$(CONFIG)/grpc_security_connector_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/lb_policies_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/multiple_server_queues_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/timer_heap_test $(BINDIR)/$(CONFIG)/timer_list_test $(BINDIR)/$(CONFIG)/timers_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/udp_server_test $(BINDIR)/$(CONFIG)/uri_parser_test $(BINDIR)/$(CONFIG)/workqueue_test $(BINDIR)/$(CONFIG)/h2_compress_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_compress_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_compress_call_creds_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_compress_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_compress_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_compress_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_compress_default_host_test $(BINDIR)/$(CONFIG)/h2_compress_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_compress_empty_batch_test $(BINDIR)/$(CONFIG)/h2_compress_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_compress_hpack_size_test $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_compress_large_metadata_test $(BINDIR)/$(CONFIG)/h2_compress_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_compress_max_message_length_test $(BINDIR)/$(CONFIG)/h2_compress_metadata_test $(BINDIR)/$(CONFIG)/h2_compress_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_compress_no_op_test $(BINDIR)/$(CONFIG)/h2_compress_payload_test $(BINDIR)/$(CONFIG)/h2_compress_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_compress_registered_call_test $(BINDIR)/$(CONFIG)/h2_compress_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_compress_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_compress_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_compress_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_compress_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_compress_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_compress_simple_request_test $(BINDIR)/$(CONFIG)/h2_compress_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_fakesec_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_fakesec_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_fakesec_call_creds_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_fakesec_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_fakesec_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_fakesec_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_fakesec_default_host_test $(BINDIR)/$(CONFIG)/h2_fakesec_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_fakesec_empty_batch_test $(BINDIR)/$(CONFIG)/h2_fakesec_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_fakesec_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_fakesec_hpack_size_test $(BINDIR)/$(CONFIG)/h2_fakesec_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_large_metadata_test $(BINDIR)/$(CONFIG)/h2_fakesec_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_fakesec_max_message_length_test $(BINDIR)/$(CONFIG)/h2_fakesec_metadata_test $(BINDIR)/$(CONFIG)/h2_fakesec_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_fakesec_no_op_test $(BINDIR)/$(CONFIG)/h2_fakesec_payload_test $(BINDIR)/$(CONFIG)/h2_fakesec_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_fakesec_registered_call_test $(BINDIR)/$(CONFIG)/h2_fakesec_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_fakesec_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_fakesec_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_fakesec_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_fakesec_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_simple_request_test $(BINDIR)/$(CONFIG)/h2_fakesec_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_full_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_full_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_full_call_creds_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_full_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_full_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_full_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_full_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_full_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_full_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_full_default_host_test $(BINDIR)/$(CONFIG)/h2_full_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_full_empty_batch_test $(BINDIR)/$(CONFIG)/h2_full_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_full_hpack_size_test $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_full_large_metadata_test $(BINDIR)/$(CONFIG)/h2_full_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_full_max_message_length_test $(BINDIR)/$(CONFIG)/h2_full_metadata_test $(BINDIR)/$(CONFIG)/h2_full_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_full_no_op_test $(BINDIR)/$(CONFIG)/h2_full_payload_test $(BINDIR)/$(CONFIG)/h2_full_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_full_registered_call_test $(BINDIR)/$(CONFIG)/h2_full_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_full_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_full_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_full_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_full_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_full_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_full_simple_request_test $(BINDIR)/$(CONFIG)/h2_full_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_full+poll_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_full+poll_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_full+poll_call_creds_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_full+poll_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_full+poll_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_full+poll_default_host_test $(BINDIR)/$(CONFIG)/h2_full+poll_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_full+poll_empty_batch_test $(BINDIR)/$(CONFIG)/h2_full+poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_test $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_large_metadata_test $(BINDIR)/$(CONFIG)/h2_full+poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_full+poll_max_message_length_test $(BINDIR)/$(CONFIG)/h2_full+poll_metadata_test $(BINDIR)/$(CONFIG)/h2_full+poll_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_full+poll_no_op_test $(BINDIR)/$(CONFIG)/h2_full+poll_payload_test $(BINDIR)/$(CONFIG)/h2_full+poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_full+poll_registered_call_test $(BINDIR)/$(CONFIG)/h2_full+poll_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_full+poll_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_full+poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_full+poll_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_full+poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_simple_request_test $(BINDIR)/$(CONFIG)/h2_full+poll_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_oauth2_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_oauth2_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_oauth2_call_creds_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_oauth2_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_oauth2_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_oauth2_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_oauth2_default_host_test $(BINDIR)/$(CONFIG)/h2_oauth2_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_oauth2_empty_batch_test $(BINDIR)/$(CONFIG)/h2_oauth2_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_oauth2_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_oauth2_hpack_size_test $(BINDIR)/$(CONFIG)/h2_oauth2_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_large_metadata_test $(BINDIR)/$(CONFIG)/h2_oauth2_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_oauth2_max_message_length_test $(BINDIR)/$(CONFIG)/h2_oauth2_metadata_test $(BINDIR)/$(CONFIG)/h2_oauth2_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_oauth2_no_op_test $(BINDIR)/$(CONFIG)/h2_oauth2_payload_test $(BINDIR)/$(CONFIG)/h2_oauth2_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_oauth2_registered_call_test $(BINDIR)/$(CONFIG)/h2_oauth2_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_oauth2_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_oauth2_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_oauth2_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_oauth2_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_simple_request_test $(BINDIR)/$(CONFIG)/h2_oauth2_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_proxy_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_proxy_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_proxy_call_creds_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_proxy_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_proxy_default_host_test $(BINDIR)/$(CONFIG)/h2_proxy_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_proxy_empty_batch_test $(BINDIR)/$(CONFIG)/h2_proxy_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_proxy_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_proxy_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_proxy_large_metadata_test $(BINDIR)/$(CONFIG)/h2_proxy_max_message_length_test $(BINDIR)/$(CONFIG)/h2_proxy_metadata_test $(BINDIR)/$(CONFIG)/h2_proxy_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_proxy_no_op_test $(BINDIR)/$(CONFIG)/h2_proxy_payload_test $(BINDIR)/$(CONFIG)/h2_proxy_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_proxy_registered_call_test $(BINDIR)/$(CONFIG)/h2_proxy_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_proxy_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_proxy_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_proxy_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_proxy_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_proxy_simple_request_test $(BINDIR)/$(CONFIG)/h2_proxy_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_sockpair_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_call_creds_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_sockpair_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_empty_batch_test $(BINDIR)/$(CONFIG)/h2_sockpair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_test $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_large_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_sockpair_max_message_length_test $(BINDIR)/$(CONFIG)/h2_sockpair_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_sockpair_no_op_test $(BINDIR)/$(CONFIG)/h2_sockpair_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_sockpair_registered_call_test $(BINDIR)/$(CONFIG)/h2_sockpair_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_sockpair_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_sockpair_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_sockpair_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_call_creds_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_empty_batch_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_large_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_max_message_length_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_no_op_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_registered_call_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_call_creds_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_empty_batch_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_large_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_message_length_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_metadata_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_no_op_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_registered_call_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_simple_request_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_ssl_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_call_creds_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_ssl_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_ssl_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_ssl_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_default_host_test $(BINDIR)/$(CONFIG)/h2_ssl_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_ssl_empty_batch_test $(BINDIR)/$(CONFIG)/h2_ssl_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_ssl_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_ssl_hpack_size_test $(BINDIR)/$(CONFIG)/h2_ssl_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_ssl_large_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_ssl_max_message_length_test $(BINDIR)/$(CONFIG)/h2_ssl_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_ssl_no_op_test $(BINDIR)/$(CONFIG)/h2_ssl_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_ssl_registered_call_test $(BINDIR)/$(CONFIG)/h2_ssl_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_ssl_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_ssl_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_ssl_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_ssl_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_ssl_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_call_creds_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_default_host_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_empty_batch_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_hpack_size_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_large_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_max_message_length_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_no_op_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_payload_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_registered_call_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl+poll_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_call_creds_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_default_host_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_empty_batch_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_large_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_max_message_length_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_metadata_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_no_op_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_registered_call_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_simple_request_test $(BINDIR)/$(CONFIG)/h2_ssl_proxy_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_uchannel_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_uchannel_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_uchannel_call_creds_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_uchannel_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_uchannel_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_uchannel_default_host_test $(BINDIR)/$(CONFIG)/h2_uchannel_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_uchannel_empty_batch_test $(BINDIR)/$(CONFIG)/h2_uchannel_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_test $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_large_metadata_test $(BINDIR)/$(CONFIG)/h2_uchannel_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_uchannel_max_message_length_test $(BINDIR)/$(CONFIG)/h2_uchannel_metadata_test $(BINDIR)/$(CONFIG)/h2_uchannel_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_uchannel_no_op_test $(BINDIR)/$(CONFIG)/h2_uchannel_payload_test $(BINDIR)/$(CONFIG)/h2_uchannel_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_uchannel_registered_call_test $(BINDIR)/$(CONFIG)/h2_uchannel_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_uchannel_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_uchannel_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_uchannel_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_uchannel_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_simple_request_test $(BINDIR)/$(CONFIG)/h2_uchannel_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_uds_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_uds_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_uds_call_creds_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_uds_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_uds_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_uds_empty_batch_test $(BINDIR)/$(CONFIG)/h2_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_uds_hpack_size_test $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_uds_large_metadata_test $(BINDIR)/$(CONFIG)/h2_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_uds_max_message_length_test $(BINDIR)/$(CONFIG)/h2_uds_metadata_test $(BINDIR)/$(CONFIG)/h2_uds_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_uds_no_op_test $(BINDIR)/$(CONFIG)/h2_uds_payload_test $(BINDIR)/$(CONFIG)/h2_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_uds_registered_call_test $(BINDIR)/$(CONFIG)/h2_uds_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_uds_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_uds_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_uds_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_uds_simple_request_test $(BINDIR)/$(CONFIG)/h2_uds_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_uds+poll_bad_hostname_test $(BINDIR)/$(CONFIG)/h2_uds+poll_binary_metadata_test $(BINDIR)/$(CONFIG)/h2_uds+poll_call_creds_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_accept_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_client_done_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_with_status_test $(BINDIR)/$(CONFIG)/h2_uds+poll_census_simple_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_channel_connectivity_test $(BINDIR)/$(CONFIG)/h2_uds+poll_compressed_payload_test $(BINDIR)/$(CONFIG)/h2_uds+poll_disappearing_server_test $(BINDIR)/$(CONFIG)/h2_uds+poll_empty_batch_test $(BINDIR)/$(CONFIG)/h2_uds+poll_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_test $(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_test $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_large_metadata_test $(BINDIR)/$(CONFIG)/h2_uds+poll_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/h2_uds+poll_max_message_length_test $(BINDIR)/$(CONFIG)/h2_uds+poll_metadata_test $(BINDIR)/$(CONFIG)/h2_uds+poll_negative_deadline_test $(BINDIR)/$(CONFIG)/h2_uds+poll_no_op_test $(BINDIR)/$(CONFIG)/h2_uds+poll_payload_test $(BINDIR)/$(CONFIG)/h2_uds+poll_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/h2_uds+poll_registered_call_test $(BINDIR)/$(CONFIG)/h2_uds+poll_request_with_flags_test $(BINDIR)/$(CONFIG)/h2_uds+poll_request_with_payload_test $(BINDIR)/$(CONFIG)/h2_uds+poll_server_finishes_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_shutdown_finishes_calls_test $(BINDIR)/$(CONFIG)/h2_uds+poll_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/h2_uds+poll_simple_delayed_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_simple_request_test $(BINDIR)/$(CONFIG)/h2_uds+poll_trailing_metadata_test $(BINDIR)/$(CONFIG)/h2_compress_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_hpack_size_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_compress_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_full_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_full_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_full_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_full_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_full_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_full_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_full_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_full_hpack_size_nosec_test $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_full_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_full_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_full_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_full_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_full_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_full_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_full_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_full_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_full_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_full+poll_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_proxy_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair+trace_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_default_host_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uchannel_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_hpack_size_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_bad_hostname_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_binary_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_accept_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_client_done_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_after_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_before_invoke_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_in_a_vacuum_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_cancel_with_status_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_census_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_channel_connectivity_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_compressed_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_disappearing_server_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_empty_batch_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_graceful_server_shutdown_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_large_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_max_concurrent_streams_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_max_message_length_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_metadata_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_negative_deadline_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_no_op_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_ping_pong_streaming_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_registered_call_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_request_with_flags_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_request_with_payload_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_server_finishes_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_shutdown_finishes_calls_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_shutdown_finishes_tags_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_simple_delayed_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_simple_request_nosec_test $(BINDIR)/$(CONFIG)/h2_uds+poll_trailing_metadata_nosec_test $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
 
-buildtests_cxx: buildtests_zookeeper privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test $(BINDIR)/$(CONFIG)/auth_property_iterator_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/cli_call_test $(BINDIR)/$(CONFIG)/client_crash_test $(BINDIR)/$(CONFIG)/client_crash_test_server $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test $(BINDIR)/$(CONFIG)/cxx_slice_test $(BINDIR)/$(CONFIG)/cxx_string_ref_test $(BINDIR)/$(CONFIG)/cxx_time_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/generic_end2end_test $(BINDIR)/$(CONFIG)/grpc_cli $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/mock_test $(BINDIR)/$(CONFIG)/qps_interarrival_test $(BINDIR)/$(CONFIG)/qps_openloop_test $(BINDIR)/$(CONFIG)/qps_test $(BINDIR)/$(CONFIG)/reconnect_interop_client $(BINDIR)/$(CONFIG)/reconnect_interop_server $(BINDIR)/$(CONFIG)/secure_auth_context_test $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test $(BINDIR)/$(CONFIG)/server_crash_test $(BINDIR)/$(CONFIG)/server_crash_test_client $(BINDIR)/$(CONFIG)/shutdown_test $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/streaming_throughput_test $(BINDIR)/$(CONFIG)/stress_test $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test $(BINDIR)/$(CONFIG)/thread_stress_test
+buildtests_cxx: buildtests_zookeeper privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test $(BINDIR)/$(CONFIG)/auth_property_iterator_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/cli_call_test $(BINDIR)/$(CONFIG)/client_crash_test $(BINDIR)/$(CONFIG)/client_crash_test_server $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test $(BINDIR)/$(CONFIG)/cxx_slice_test $(BINDIR)/$(CONFIG)/cxx_string_ref_test $(BINDIR)/$(CONFIG)/cxx_time_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/generic_end2end_test $(BINDIR)/$(CONFIG)/grpc_cli $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/metrics_client $(BINDIR)/$(CONFIG)/mock_test $(BINDIR)/$(CONFIG)/qps_interarrival_test $(BINDIR)/$(CONFIG)/qps_openloop_test $(BINDIR)/$(CONFIG)/qps_test $(BINDIR)/$(CONFIG)/reconnect_interop_client $(BINDIR)/$(CONFIG)/reconnect_interop_server $(BINDIR)/$(CONFIG)/secure_auth_context_test $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test $(BINDIR)/$(CONFIG)/server_crash_test $(BINDIR)/$(CONFIG)/server_crash_test_client $(BINDIR)/$(CONFIG)/shutdown_test $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/streaming_throughput_test $(BINDIR)/$(CONFIG)/stress_test $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test $(BINDIR)/$(CONFIG)/thread_stress_test
 
 ifeq ($(HAS_ZOOKEEPER),true)
 buildtests_zookeeper: privatelibs_zookeeper $(BINDIR)/$(CONFIG)/zookeeper_test
@@ -2036,6 +2057,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_compress_graceful_server_shutdown_test || ( echo test h2_compress_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_compress_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_test || ( echo test h2_compress_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_compress_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_compress_hpack_size_test || ( echo test h2_compress_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_compress_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_test || ( echo test h2_compress_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_compress_large_metadata_test"
@@ -2106,6 +2129,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_fakesec_graceful_server_shutdown_test || ( echo test h2_fakesec_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_fakesec_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_fakesec_high_initial_seqno_test || ( echo test h2_fakesec_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_fakesec_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_fakesec_hpack_size_test || ( echo test h2_fakesec_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_fakesec_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_fakesec_invoke_large_request_test || ( echo test h2_fakesec_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_fakesec_large_metadata_test"
@@ -2176,6 +2201,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full_graceful_server_shutdown_test || ( echo test h2_full_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_test || ( echo test h2_full_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_full_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_full_hpack_size_test || ( echo test h2_full_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_test || ( echo test h2_full_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full_large_metadata_test"
@@ -2246,6 +2273,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full+poll_graceful_server_shutdown_test || ( echo test h2_full+poll_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full+poll_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_test || ( echo test h2_full+poll_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_full+poll_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_test || ( echo test h2_full+poll_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full+poll_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_test || ( echo test h2_full+poll_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full+poll_large_metadata_test"
@@ -2316,6 +2345,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_oauth2_graceful_server_shutdown_test || ( echo test h2_oauth2_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_oauth2_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_oauth2_high_initial_seqno_test || ( echo test h2_oauth2_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_oauth2_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_oauth2_hpack_size_test || ( echo test h2_oauth2_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_oauth2_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_oauth2_invoke_large_request_test || ( echo test h2_oauth2_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_oauth2_large_metadata_test"
@@ -2442,6 +2473,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_graceful_server_shutdown_test || ( echo test h2_sockpair_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_test || ( echo test h2_sockpair_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_sockpair_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_test || ( echo test h2_sockpair_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_test || ( echo test h2_sockpair_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_large_metadata_test"
@@ -2566,6 +2599,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_graceful_server_shutdown_test || ( echo test h2_sockpair_1byte_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_1byte_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_test || ( echo test h2_sockpair_1byte_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_sockpair_1byte_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_test || ( echo test h2_sockpair_1byte_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_1byte_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_test || ( echo test h2_sockpair_1byte_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_1byte_large_metadata_test"
@@ -2634,6 +2669,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl_graceful_server_shutdown_test || ( echo test h2_ssl_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_ssl_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl_high_initial_seqno_test || ( echo test h2_ssl_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_ssl_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl_hpack_size_test || ( echo test h2_ssl_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_ssl_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl_invoke_large_request_test || ( echo test h2_ssl_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_ssl_large_metadata_test"
@@ -2704,6 +2741,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl+poll_graceful_server_shutdown_test || ( echo test h2_ssl+poll_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_ssl+poll_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl+poll_high_initial_seqno_test || ( echo test h2_ssl+poll_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_ssl+poll_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl+poll_hpack_size_test || ( echo test h2_ssl+poll_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_ssl+poll_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_ssl+poll_invoke_large_request_test || ( echo test h2_ssl+poll_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_ssl+poll_large_metadata_test"
@@ -2836,6 +2875,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uchannel_graceful_server_shutdown_test || ( echo test h2_uchannel_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uchannel_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_test || ( echo test h2_uchannel_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_uchannel_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_test || ( echo test h2_uchannel_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uchannel_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_test || ( echo test h2_uchannel_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uchannel_large_metadata_test"
@@ -2904,6 +2945,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds_graceful_server_shutdown_test || ( echo test h2_uds_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_test || ( echo test h2_uds_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_uds_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_uds_hpack_size_test || ( echo test h2_uds_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_test || ( echo test h2_uds_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds_large_metadata_test"
@@ -2972,6 +3015,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds+poll_graceful_server_shutdown_test || ( echo test h2_uds+poll_graceful_server_shutdown_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds+poll_high_initial_seqno_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_test || ( echo test h2_uds+poll_high_initial_seqno_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_uds+poll_hpack_size_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_test || ( echo test h2_uds+poll_hpack_size_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds+poll_invoke_large_request_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_test || ( echo test h2_uds+poll_invoke_large_request_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds+poll_large_metadata_test"
@@ -3040,6 +3085,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_compress_graceful_server_shutdown_nosec_test || ( echo test h2_compress_graceful_server_shutdown_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_compress_high_initial_seqno_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_nosec_test || ( echo test h2_compress_high_initial_seqno_nosec_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_compress_hpack_size_nosec_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_compress_hpack_size_nosec_test || ( echo test h2_compress_hpack_size_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_compress_invoke_large_request_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_nosec_test || ( echo test h2_compress_invoke_large_request_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_compress_large_metadata_nosec_test"
@@ -3108,6 +3155,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full_graceful_server_shutdown_nosec_test || ( echo test h2_full_graceful_server_shutdown_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full_high_initial_seqno_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_nosec_test || ( echo test h2_full_high_initial_seqno_nosec_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_full_hpack_size_nosec_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_full_hpack_size_nosec_test || ( echo test h2_full_hpack_size_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full_invoke_large_request_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_nosec_test || ( echo test h2_full_invoke_large_request_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full_large_metadata_nosec_test"
@@ -3176,6 +3225,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full+poll_graceful_server_shutdown_nosec_test || ( echo test h2_full+poll_graceful_server_shutdown_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full+poll_high_initial_seqno_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_nosec_test || ( echo test h2_full+poll_high_initial_seqno_nosec_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_full+poll_hpack_size_nosec_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_nosec_test || ( echo test h2_full+poll_hpack_size_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full+poll_invoke_large_request_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_nosec_test || ( echo test h2_full+poll_invoke_large_request_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_full+poll_large_metadata_nosec_test"
@@ -3298,6 +3349,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_graceful_server_shutdown_nosec_test || ( echo test h2_sockpair_graceful_server_shutdown_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_high_initial_seqno_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_nosec_test || ( echo test h2_sockpair_high_initial_seqno_nosec_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_sockpair_hpack_size_nosec_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_nosec_test || ( echo test h2_sockpair_hpack_size_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_invoke_large_request_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_nosec_test || ( echo test h2_sockpair_invoke_large_request_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_large_metadata_nosec_test"
@@ -3418,6 +3471,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_graceful_server_shutdown_nosec_test || ( echo test h2_sockpair_1byte_graceful_server_shutdown_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_1byte_high_initial_seqno_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_nosec_test || ( echo test h2_sockpair_1byte_high_initial_seqno_nosec_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_sockpair_1byte_hpack_size_nosec_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_nosec_test || ( echo test h2_sockpair_1byte_hpack_size_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_1byte_invoke_large_request_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_nosec_test || ( echo test h2_sockpair_1byte_invoke_large_request_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_sockpair_1byte_large_metadata_nosec_test"
@@ -3484,6 +3539,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uchannel_graceful_server_shutdown_nosec_test || ( echo test h2_uchannel_graceful_server_shutdown_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uchannel_high_initial_seqno_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_nosec_test || ( echo test h2_uchannel_high_initial_seqno_nosec_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_uchannel_hpack_size_nosec_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_nosec_test || ( echo test h2_uchannel_hpack_size_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uchannel_invoke_large_request_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_nosec_test || ( echo test h2_uchannel_invoke_large_request_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uchannel_large_metadata_nosec_test"
@@ -3550,6 +3607,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds_graceful_server_shutdown_nosec_test || ( echo test h2_uds_graceful_server_shutdown_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds_high_initial_seqno_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_nosec_test || ( echo test h2_uds_high_initial_seqno_nosec_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_uds_hpack_size_nosec_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_uds_hpack_size_nosec_test || ( echo test h2_uds_hpack_size_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds_invoke_large_request_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_nosec_test || ( echo test h2_uds_invoke_large_request_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds_large_metadata_nosec_test"
@@ -3616,6 +3675,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds+poll_graceful_server_shutdown_nosec_test || ( echo test h2_uds+poll_graceful_server_shutdown_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds+poll_high_initial_seqno_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_nosec_test || ( echo test h2_uds+poll_high_initial_seqno_nosec_test failed ; exit 1 )
+	$(E) "[RUN]     Testing h2_uds+poll_hpack_size_nosec_test"
+	$(Q) $(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_nosec_test || ( echo test h2_uds+poll_hpack_size_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds+poll_invoke_large_request_nosec_test"
 	$(Q) $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_nosec_test || ( echo test h2_uds+poll_invoke_large_request_nosec_test failed ; exit 1 )
 	$(E) "[RUN]     Testing h2_uds+poll_large_metadata_nosec_test"
@@ -3992,6 +4053,21 @@ $(GENDIR)/test/proto/messages.grpc.pb.cc: test/proto/messages.proto $(PROTOBUF_D
 	$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
 endif
 
+ifeq ($(NO_PROTOC),true)
+$(GENDIR)/test/proto/metrics.pb.cc: protoc_dep_error
+$(GENDIR)/test/proto/metrics.grpc.pb.cc: protoc_dep_error
+else
+$(GENDIR)/test/proto/metrics.pb.cc: test/proto/metrics.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
+	$(E) "[PROTOC]  Generating protobuf CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
+
+$(GENDIR)/test/proto/metrics.grpc.pb.cc: test/proto/metrics.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
+	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
+endif
+
 ifeq ($(NO_PROTOC),true)
 $(GENDIR)/test/proto/test.pb.cc: protoc_dep_error
 $(GENDIR)/test/proto/test.grpc.pb.cc: protoc_dep_error
@@ -6535,6 +6611,29 @@ ifneq ($(NO_DEPS),true)
 endif
 
 
+LIBEND2END_TEST_HPACK_SIZE_SRC = \
+    test/core/end2end/tests/hpack_size.c \
+
+
+LIBEND2END_TEST_HPACK_SIZE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBEND2END_TEST_HPACK_SIZE_SRC))))
+
+$(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a: $(ZLIB_DEP) $(LIBEND2END_TEST_HPACK_SIZE_OBJS)
+	$(E) "[AR]      Creating $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) rm -f $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a
+	$(Q) $(AR) rcs $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBEND2END_TEST_HPACK_SIZE_OBJS)
+ifeq ($(SYSTEM),Darwin)
+	$(Q) ranlib $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a
+endif
+
+
+
+
+ifneq ($(NO_DEPS),true)
+-include $(LIBEND2END_TEST_HPACK_SIZE_OBJS:.o=.dep)
+endif
+
+
 LIBEND2END_TEST_INVOKE_LARGE_REQUEST_SRC = \
     test/core/end2end/tests/invoke_large_request.c \
 
@@ -10169,6 +10268,49 @@ endif
 endif
 
 
+METRICS_CLIENT_SRC = \
+    $(GENDIR)/test/proto/metrics.pb.cc $(GENDIR)/test/proto/metrics.grpc.pb.cc \
+    test/cpp/interop/metrics_client.cc \
+
+METRICS_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(METRICS_CLIENT_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/metrics_client: 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)/metrics_client: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/metrics_client: $(PROTOBUF_DEP) $(METRICS_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(METRICS_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/metrics_client
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/proto/metrics.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(OBJDIR)/$(CONFIG)/test/cpp/interop/metrics_client.o:  $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+deps_metrics_client: $(METRICS_CLIENT_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(METRICS_CLIENT_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/interop/metrics_client.o: $(GENDIR)/test/proto/metrics.pb.cc $(GENDIR)/test/proto/metrics.grpc.pb.cc
+
+
 MOCK_TEST_SRC = \
     test/cpp/end2end/mock_test.cc \
 
@@ -10786,10 +10928,12 @@ endif
 STRESS_TEST_SRC = \
     $(GENDIR)/test/proto/empty.pb.cc $(GENDIR)/test/proto/empty.grpc.pb.cc \
     $(GENDIR)/test/proto/messages.pb.cc $(GENDIR)/test/proto/messages.grpc.pb.cc \
+    $(GENDIR)/test/proto/metrics.pb.cc $(GENDIR)/test/proto/metrics.grpc.pb.cc \
     $(GENDIR)/test/proto/test.pb.cc $(GENDIR)/test/proto/test.grpc.pb.cc \
     test/cpp/interop/interop_client.cc \
     test/cpp/interop/stress_interop_client.cc \
     test/cpp/interop/stress_test.cc \
+    test/cpp/util/metrics_server.cc \
 
 STRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STRESS_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
@@ -10820,10 +10964,12 @@ endif
 
 $(OBJDIR)/$(CONFIG)/test/proto/empty.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 $(OBJDIR)/$(CONFIG)/test/proto/messages.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(OBJDIR)/$(CONFIG)/test/proto/metrics.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 $(OBJDIR)/$(CONFIG)/test/proto/test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 $(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_client.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 $(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_interop_client.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 $(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(OBJDIR)/$(CONFIG)/test/cpp/util/metrics_server.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 deps_stress_test: $(STRESS_TEST_OBJS:.o=.dep)
 
 ifneq ($(NO_SECURE),true)
@@ -10831,9 +10977,10 @@ ifneq ($(NO_DEPS),true)
 -include $(STRESS_TEST_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_client.o: $(GENDIR)/test/proto/empty.pb.cc $(GENDIR)/test/proto/empty.grpc.pb.cc $(GENDIR)/test/proto/messages.pb.cc $(GENDIR)/test/proto/messages.grpc.pb.cc $(GENDIR)/test/proto/test.pb.cc $(GENDIR)/test/proto/test.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_interop_client.o: $(GENDIR)/test/proto/empty.pb.cc $(GENDIR)/test/proto/empty.grpc.pb.cc $(GENDIR)/test/proto/messages.pb.cc $(GENDIR)/test/proto/messages.grpc.pb.cc $(GENDIR)/test/proto/test.pb.cc $(GENDIR)/test/proto/test.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_test.o: $(GENDIR)/test/proto/empty.pb.cc $(GENDIR)/test/proto/empty.grpc.pb.cc $(GENDIR)/test/proto/messages.pb.cc $(GENDIR)/test/proto/messages.grpc.pb.cc $(GENDIR)/test/proto/test.pb.cc $(GENDIR)/test/proto/test.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_client.o: $(GENDIR)/test/proto/empty.pb.cc $(GENDIR)/test/proto/empty.grpc.pb.cc $(GENDIR)/test/proto/messages.pb.cc $(GENDIR)/test/proto/messages.grpc.pb.cc $(GENDIR)/test/proto/metrics.pb.cc $(GENDIR)/test/proto/metrics.grpc.pb.cc $(GENDIR)/test/proto/test.pb.cc $(GENDIR)/test/proto/test.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_interop_client.o: $(GENDIR)/test/proto/empty.pb.cc $(GENDIR)/test/proto/empty.grpc.pb.cc $(GENDIR)/test/proto/messages.pb.cc $(GENDIR)/test/proto/messages.grpc.pb.cc $(GENDIR)/test/proto/metrics.pb.cc $(GENDIR)/test/proto/metrics.grpc.pb.cc $(GENDIR)/test/proto/test.pb.cc $(GENDIR)/test/proto/test.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_test.o: $(GENDIR)/test/proto/empty.pb.cc $(GENDIR)/test/proto/empty.grpc.pb.cc $(GENDIR)/test/proto/messages.pb.cc $(GENDIR)/test/proto/messages.grpc.pb.cc $(GENDIR)/test/proto/metrics.pb.cc $(GENDIR)/test/proto/metrics.grpc.pb.cc $(GENDIR)/test/proto/test.pb.cc $(GENDIR)/test/proto/test.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/metrics_server.o: $(GENDIR)/test/proto/empty.pb.cc $(GENDIR)/test/proto/empty.grpc.pb.cc $(GENDIR)/test/proto/messages.pb.cc $(GENDIR)/test/proto/messages.grpc.pb.cc $(GENDIR)/test/proto/metrics.pb.cc $(GENDIR)/test/proto/metrics.grpc.pb.cc $(GENDIR)/test/proto/test.pb.cc $(GENDIR)/test/proto/test.grpc.pb.cc
 
 
 SYNC_STREAMING_PING_PONG_TEST_SRC = \
@@ -11302,6 +11449,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_compress_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_compress_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_compress.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_compress.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_compress_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -11932,6 +12097,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_fakesec_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_fakesec_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_fakesec.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_fakesec.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_fakesec_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -12562,6 +12745,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_full_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_full_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_full_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -13192,6 +13393,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -13822,6 +14041,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_oauth2_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_oauth2_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_oauth2.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_oauth2.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_oauth2_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -14956,6 +15193,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -16072,6 +16327,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair_1byte.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair_1byte.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -16684,6 +16957,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_ssl_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_ssl_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_ssl_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -17314,6 +17605,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_ssl+poll_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_ssl+poll_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_ssl+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_ssl+poll_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -18502,6 +18811,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uchannel.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uchannel.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -19114,6 +19441,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_uds_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_uds_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uds_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -19726,6 +20071,24 @@ endif
 
 
 
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_test: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_test
+
+endif
+
+
+
+
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
@@ -20178,6 +20541,14 @@ $(BINDIR)/$(CONFIG)/h2_compress_high_initial_seqno_nosec_test:  $(LIBDIR)/$(CONF
 
 
 
+$(BINDIR)/$(CONFIG)/h2_compress_hpack_size_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_compress.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_compress.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_compress_hpack_size_nosec_test
+
+
+
+
 $(BINDIR)/$(CONFIG)/h2_compress_invoke_large_request_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_compress.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
@@ -20450,6 +20821,14 @@ $(BINDIR)/$(CONFIG)/h2_full_high_initial_seqno_nosec_test:  $(LIBDIR)/$(CONFIG)/
 
 
 
+$(BINDIR)/$(CONFIG)/h2_full_hpack_size_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_full_hpack_size_nosec_test
+
+
+
+
 $(BINDIR)/$(CONFIG)/h2_full_invoke_large_request_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
@@ -20722,6 +21101,14 @@ $(BINDIR)/$(CONFIG)/h2_full+poll_high_initial_seqno_nosec_test:  $(LIBDIR)/$(CON
 
 
 
+$(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_full+poll_hpack_size_nosec_test
+
+
+
+
 $(BINDIR)/$(CONFIG)/h2_full+poll_invoke_large_request_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_full+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
@@ -21210,6 +21597,14 @@ $(BINDIR)/$(CONFIG)/h2_sockpair_high_initial_seqno_nosec_test:  $(LIBDIR)/$(CONF
 
 
 
+$(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_sockpair_hpack_size_nosec_test
+
+
+
+
 $(BINDIR)/$(CONFIG)/h2_sockpair_invoke_large_request_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
@@ -21690,6 +22085,14 @@ $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_high_initial_seqno_nosec_test:  $(LIBDIR)/
 
 
 
+$(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair_1byte.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair_1byte.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_hpack_size_nosec_test
+
+
+
+
 $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_invoke_large_request_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_sockpair_1byte.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
@@ -21954,6 +22357,14 @@ $(BINDIR)/$(CONFIG)/h2_uchannel_high_initial_seqno_nosec_test:  $(LIBDIR)/$(CONF
 
 
 
+$(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uchannel.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uchannel.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_uchannel_hpack_size_nosec_test
+
+
+
+
 $(BINDIR)/$(CONFIG)/h2_uchannel_invoke_large_request_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uchannel.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
@@ -22218,6 +22629,14 @@ $(BINDIR)/$(CONFIG)/h2_uds_high_initial_seqno_nosec_test:  $(LIBDIR)/$(CONFIG)/l
 
 
 
+$(BINDIR)/$(CONFIG)/h2_uds_hpack_size_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_uds_hpack_size_nosec_test
+
+
+
+
 $(BINDIR)/$(CONFIG)/h2_uds_invoke_large_request_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
@@ -22482,6 +22901,14 @@ $(BINDIR)/$(CONFIG)/h2_uds+poll_high_initial_seqno_nosec_test:  $(LIBDIR)/$(CONF
 
 
 
+$(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS)  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_hpack_size.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_uds+poll_hpack_size_nosec_test
+
+
+
+
 $(BINDIR)/$(CONFIG)/h2_uds+poll_invoke_large_request_nosec_test:  $(LIBDIR)/$(CONFIG)/libend2end_fixture_h2_uds+poll.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
diff --git a/binding.gyp b/binding.gyp
index 502b9d7a73c7099f942db3a322b242367a2dc5f9..1883f730fc80b67f9d8795eccd09ab997a1c8419 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -347,11 +347,12 @@
         "src/node/ext/node_grpc.cc",
         "src/node/ext/server.cc",
         "src/node/ext/server_credentials.cc",
-        "src/node/ext/timeval.cc"
+        "src/node/ext/timeval.cc",
       ],
       "dependencies": [
-        "grpc"
+        "grpc",
+        "gpr",
       ]
-    }
+    },
   ]
 }
diff --git a/build.yaml b/build.yaml
index bd93a16bcb37d77b2ef5c406dec506a7dd9b5cac..2af2c1e24dc1135dccd05a612246650ffe3b5f37 100644
--- a/build.yaml
+++ b/build.yaml
@@ -5,7 +5,7 @@ settings:
   '#': The public version number of the library.
   version:
     major: 0
-    minor: 11
+    minor: 12
     micro: 0
     build: 0
 filegroups:
@@ -1887,6 +1887,20 @@ targets:
   - mac
   - linux
   - posix
+- name: metrics_client
+  build: test
+  run: false
+  language: c++
+  headers:
+  - test/cpp/util/metrics_server.h
+  src:
+  - test/proto/metrics.proto
+  - test/cpp/interop/metrics_client.cc
+  deps:
+  - grpc++
+  - grpc
+  - gpr
+  - grpc++_test_config
 - name: mock_test
   build: test
   language: c++
@@ -2127,13 +2141,16 @@ targets:
   - test/cpp/interop/client_helper.h
   - test/cpp/interop/interop_client.h
   - test/cpp/interop/stress_interop_client.h
+  - test/cpp/util/metrics_server.h
   src:
   - test/proto/empty.proto
   - test/proto/messages.proto
+  - test/proto/metrics.proto
   - test/proto/test.proto
   - test/cpp/interop/interop_client.cc
   - test/cpp/interop/stress_interop_client.cc
   - test/cpp/interop/stress_test.cc
+  - test/cpp/util/metrics_server.cc
   deps:
   - grpc++_test_util
   - grpc_test_util
@@ -2224,3 +2241,36 @@ vspackages:
   props: false
   redist: false
   version: 1.7.0.1
+node_modules:
+- deps:
+  - grpc
+  - gpr
+  headers:
+  - src/node/ext/byte_buffer.h
+  - src/node/ext/call.h
+  - src/node/ext/call_credentials.h
+  - src/node/ext/channel.h
+  - src/node/ext/channel_credentials.h
+  - src/node/ext/completion_queue_async_worker.h
+  - src/node/ext/server.h
+  - src/node/ext/server_credentials.h
+  - src/node/ext/timeval.h
+  js:
+  - src/node/index.js
+  - src/node/src/client.js
+  - src/node/src/common.js
+  - src/node/src/credentials.js
+  - src/node/src/metadata.js
+  - src/node/src/server.js
+  name: grpc_node
+  src:
+  - src/node/ext/byte_buffer.cc
+  - src/node/ext/call.cc
+  - src/node/ext/call_credentials.cc
+  - src/node/ext/channel.cc
+  - src/node/ext/channel_credentials.cc
+  - src/node/ext/completion_queue_async_worker.cc
+  - src/node/ext/node_grpc.cc
+  - src/node/ext/server.cc
+  - src/node/ext/server_credentials.cc
+  - src/node/ext/timeval.cc
diff --git a/doc/PROTOCOL-HTTP2.md b/doc/PROTOCOL-HTTP2.md
index 7f7055bb4df7b35391a7f25761ab1c28bfe6708f..7a26724c85ded4b28214845a5e5a3e84a882ab3f 100644
--- a/doc/PROTOCOL-HTTP2.md
+++ b/doc/PROTOCOL-HTTP2.md
@@ -44,8 +44,9 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
 * **Message-Type** → "grpc-message-type" {_type name for message schema_}
 * **Custom-Metadata** → Binary-Header / ASCII-Header
 * **Binary-Header** → {Header-Name "-bin" } {_base64 encoded value_}
-* **ASCII-Header** → Header-Name {_value_}
+* **ASCII-Header** → Header-Name ASCII-Value
 * **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-") ; 0-9 a-z \_ -
+* **ASCII-Value** → 1\*( %x20-%x7E ) ; space and printable ASCII
 
 
 HTTP2 requires that reserved headers, ones starting with ":" appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**.
@@ -56,6 +57,23 @@ If **Timeout** is omitted a server should assume an infinite timeout. Client imp
 
 Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. Applications define binary headers by having their names end with "-bin". Runtime libraries use this suffix to detect binary headers and properly apply base64 encoding & decoding as headers are sent and received.
 
+**Custom-Metadata** header order is not guaranteed to be preserved except for
+values with duplicate header names. Duplicate header names may have their values
+joined with "," as the delimiter and be considered semantically equivalent.
+Implementations must split **Binary-Header**s on "," before decoding the
+Base64-encoded values.
+
+**ASCII-Value** should not have leading or trailing whitespace. If it contains
+leading or trailing whitespace, it may be stripped. The **ASCII-Value**
+character range defined is more strict than HTTP. Implementations must not error
+due to receiving an invalid **ASCII-Value** that's a valid **field-value** in
+HTTP, but the precise behavior is not strictly defined: they may throw the value
+away or accept the value. If accepted, care must be taken to make sure that the
+application is permitted to echo the value back as metadata. For example, if the
+metadata is provided to the application as a list in a request, the application
+should not trigger an error by providing that same list as the metadata in the
+response.
+
 Servers may limit the size of **Request-Headers**, with a default of 8 KiB
 suggested.  Implementations are encouraged to compute total header size like
 HTTP/2's `SETTINGS_MAX_HEADER_LIST_SIZE`: the sum of all header fields, for each
diff --git a/doc/grpc-auth-support.md b/doc/grpc-auth-support.md
index 800fbedd80c63307d58aaba759731b06a96515cd..b210ff15333a4ee0c68e5ee35e8d72cc045fcf1e 100644
--- a/doc/grpc-auth-support.md
+++ b/doc/grpc-auth-support.md
@@ -36,9 +36,9 @@ authenticate the server and encrypt all data.
 ```cpp
 SslCredentialsOptions ssl_opts;  // Options to override SSL params, empty by default
 // Create the credentials object by providing service account key in constructor
-std::unique_ptr<Credentials> creds = CredentialsFactory::SslCredentials(ssl_opts);
+std::shared_ptr<ChannelCredentials> creds = SslCredentials(ssl_opts);
 // Create a channel using the credentials created in the previous step
-std::shared_ptr<ChannelInterface> channel = CreateChannel(server_name, creds, channel_args);
+std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
 // Create a stub on the channel
 std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
 // Make actual RPC calls on the stub.
@@ -55,9 +55,9 @@ passed to the factory method.
 gRPC applications can use a simple API to create a credential that works in various deployment scenarios.
 
 ```cpp
-std::unique_ptr<Credentials> creds = CredentialsFactory::GoogleDefaultCredentials();
+std::shared_ptr<ChannelCredentials> creds = GoogleDefaultCredentials();
 // Create a channel, stub and make RPC calls (same as in the previous example)
-std::shared_ptr<ChannelInterface> channel = CreateChannel(server_name, creds, channel_args);
+std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
 std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
 grpc::Status s = stub->sayHello(&context, *request, response);
 ```
diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index 8649213bc6ad4c6d3b957b3f70441555f3ec1943..53cc47b1f8379677f0ed89811915f03b2983cd77 100644
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -4,7 +4,7 @@ Interoperability Test Case Descriptions
 Client and server use
 [test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto)
 and the [gRPC over HTTP/2 v2
-protocol](doc/PROTOCOL-HTTP2.md).
+protocol](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md).
 
 Client
 ------
diff --git a/examples/cpp/cpptutorial.md b/examples/cpp/cpptutorial.md
index 78de014f97d1978b4195dca5b84306fc66a8375c..cd1cddb11157be6f1bd48d07955a15f5bd4898a0 100644
--- a/examples/cpp/cpptutorial.md
+++ b/examples/cpp/cpptutorial.md
@@ -245,7 +245,7 @@ To call service methods, we first need to create a *stub*.
 First we need to create a gRPC *channel* for our stub, specifying the server address and port we want to connect to without SSL:
 
 ```cpp
-grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials());
+grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials());
 ```
 
 Now we can use the channel to create our stub using the `NewStub` method provided in the `RouteGuide` class we generated from our .proto.
diff --git a/examples/cpp/helloworld/README.md b/examples/cpp/helloworld/README.md
index b16c084583dc97abad2fa1a4ffae0991f1531d96..7a7194d11186a6134aff2c494d9f9f2854dead4b 100644
--- a/examples/cpp/helloworld/README.md
+++ b/examples/cpp/helloworld/README.md
@@ -94,7 +94,7 @@ $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
   arguments as follows
 
     ```
-    auto channel = CreateChannel("localhost:50051", InsecureCredentials());
+    auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials());
     ```
 
 - Create a stub. A stub implements the rpc methods of a service and in the
diff --git a/examples/cpp/helloworld/greeter_async_client.cc b/examples/cpp/helloworld/greeter_async_client.cc
index 923c8ffa743dba81cbe8740492ace7a2772b6e96..35014267febe9ccd1bab506de49e38ccf18af987 100644
--- a/examples/cpp/helloworld/greeter_async_client.cc
+++ b/examples/cpp/helloworld/greeter_async_client.cc
@@ -114,9 +114,9 @@ int main(int argc, char** argv) {
   // Instantiate the client. It requires a channel, out of which the actual RPCs
   // are created. This channel models a connection to an endpoint (in this case,
   // localhost at port 50051). We indicate that the channel isn't authenticated
-  // (use of InsecureCredentials()).
-  GreeterClient greeter(
-      grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()));
+  // (use of InsecureChannelCredentials()).
+  GreeterClient greeter(grpc::CreateChannel(
+      "localhost:50051", grpc::InsecureChannelCredentials()));
   std::string user("world");
   std::string reply = greeter.SayHello(user);  // The actual RPC call!
   std::cout << "Greeter received: " << reply << std::endl;
diff --git a/examples/cpp/helloworld/greeter_client.cc b/examples/cpp/helloworld/greeter_client.cc
index 6cd8353a9fb21498d04d5a6bff1a0b9ce40a10d9..bf3b63cb5774752914d28e4662973db549c11466 100644
--- a/examples/cpp/helloworld/greeter_client.cc
+++ b/examples/cpp/helloworld/greeter_client.cc
@@ -84,9 +84,9 @@ int main(int argc, char** argv) {
   // Instantiate the client. It requires a channel, out of which the actual RPCs
   // are created. This channel models a connection to an endpoint (in this case,
   // localhost at port 50051). We indicate that the channel isn't authenticated
-  // (use of InsecureCredentials()).
-  GreeterClient greeter(
-      grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()));
+  // (use of InsecureChannelCredentials()).
+  GreeterClient greeter(grpc::CreateChannel(
+      "localhost:50051", grpc::InsecureChannelCredentials()));
   std::string user("world");
   std::string reply = greeter.SayHello(user);
   std::cout << "Greeter received: " << reply << std::endl;
diff --git a/examples/cpp/route_guide/route_guide_client.cc b/examples/cpp/route_guide/route_guide_client.cc
index 85173a393256832369a2ad701eed2e50c80b0a52..b9abe72a5bd7a8d453f1405d50f3b9426a16717e 100644
--- a/examples/cpp/route_guide/route_guide_client.cc
+++ b/examples/cpp/route_guide/route_guide_client.cc
@@ -234,7 +234,8 @@ int main(int argc, char** argv) {
   // Expect only arg: --db_path=path/to/route_guide_db.json.
   std::string db = routeguide::GetDbFileContent(argc, argv);
   RouteGuideClient guide(
-      grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()),
+      grpc::CreateChannel("localhost:50051",
+                          grpc::InsecureChannelCredentials()),
       db);
 
   std::cout << "-------------- GetFeature --------------" << std::endl;
diff --git a/examples/node/README.md b/examples/node/README.md
index df681e85dd7ed0f6a094ed75fdf8d6d18ba0f794..09c56f7fa6f402cce6e1df6205ecdd1c17ebedee 100644
--- a/examples/node/README.md
+++ b/examples/node/README.md
@@ -4,7 +4,7 @@ gRPC in 3 minutes (Node.js)
 PREREQUISITES
 -------------
 
-- `node`: This requires Node 10.x or greater.
+- `node`: This requires Node 0.10.x or greater.
 - [homebrew][] on Mac OS X.  This simplifies the installation of the gRPC C core.
 
 INSTALL
diff --git a/examples/python/helloworld/greeter_server.py b/examples/python/helloworld/greeter_server.py
index 1514d8f270bef2eca2e1aac16a367172b73daf35..2cde5add435d6ebd204637a2217c98a89e87c00d 100644
--- a/examples/python/helloworld/greeter_server.py
+++ b/examples/python/helloworld/greeter_server.py
@@ -50,7 +50,7 @@ def serve():
     while True:
       time.sleep(_ONE_DAY_IN_SECONDS)
   except KeyboardInterrupt:
-    server.stop()
+    server.stop(0)
 
 if __name__ == '__main__':
   serve()
diff --git a/include/grpc++/channel.h b/include/grpc++/channel.h
index 60c816d58ac942a210cbb5291002afea7744e7b3..d6d72a9cf981fb3178a6dc2090ce30d1d093fea2 100644
--- a/include/grpc++/channel.h
+++ b/include/grpc++/channel.h
@@ -47,8 +47,8 @@ namespace grpc {
 class CallOpSetInterface;
 class ChannelArguments;
 class CompletionQueue;
-class Credentials;
-class SecureCredentials;
+class ChannelCredentials;
+class SecureChannelCredentials;
 
 template <class R>
 class ClientReader;
diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h
index 7046f939e5e57298434c9d5fb9eeb8dd83eae307..5c6f432c9a70bd0ae220bc27bd4cb70a3fd921b2 100644
--- a/include/grpc++/client_context.h
+++ b/include/grpc++/client_context.h
@@ -53,15 +53,16 @@
 #include <memory>
 #include <string>
 
-#include <grpc/compression.h>
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
+#include <grpc++/impl/sync.h>
 #include <grpc++/security/auth_context.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/status.h>
 #include <grpc++/support/string_ref.h>
 #include <grpc++/support/time.h>
+#include <grpc/compression.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
 
 struct census_context;
 
@@ -69,7 +70,7 @@ namespace grpc {
 
 class Channel;
 class CompletionQueue;
-class Credentials;
+class CallCredentials;
 class RpcMethod;
 template <class R>
 class ClientReader;
@@ -244,7 +245,7 @@ class ClientContext {
   /// call.
   ///
   /// \see  https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md
-  void set_credentials(const std::shared_ptr<Credentials>& creds) {
+  void set_credentials(const std::shared_ptr<CallCredentials>& creds) {
     creds_ = creds;
   }
 
@@ -315,10 +316,12 @@ class ClientContext {
 
   bool initial_metadata_received_;
   std::shared_ptr<Channel> channel_;
+  grpc::mutex mu_;
   grpc_call* call_;
+  bool call_canceled_;
   gpr_timespec deadline_;
   grpc::string authority_;
-  std::shared_ptr<Credentials> creds_;
+  std::shared_ptr<CallCredentials> creds_;
   mutable std::shared_ptr<const AuthContext> auth_context_;
   struct census_context* census_context_;
   std::multimap<grpc::string, grpc::string> send_initial_metadata_;
diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h
index 196d2927a9a3c2b7faecf51905d1b49b75dc85d3..aff9c291c26d397e9b14c62186f7ca5b4eb43bf9 100644
--- a/include/grpc++/create_channel.h
+++ b/include/grpc++/create_channel.h
@@ -49,7 +49,8 @@ namespace grpc {
 /// an object or is invalid, a lame channel is returned.
 /// \param args Options for channel creation.
 std::shared_ptr<Channel> CreateChannel(
-    const grpc::string& target, const std::shared_ptr<Credentials>& creds);
+    const grpc::string& target,
+    const std::shared_ptr<ChannelCredentials>& creds);
 
 /// Create a new \em custom \a Channel pointing to \a target
 ///
@@ -61,7 +62,8 @@ std::shared_ptr<Channel> CreateChannel(
 /// an object or is invalid, a lame channel is returned.
 /// \param args Options for channel creation.
 std::shared_ptr<Channel> CreateCustomChannel(
-    const grpc::string& target, const std::shared_ptr<Credentials>& creds,
+    const grpc::string& target,
+    const std::shared_ptr<ChannelCredentials>& creds,
     const ChannelArguments& args);
 
 }  // namespace grpc
diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h
index ff41bc597eb368544da896b1889d086af070cfbc..cc827f09b0adb134882faaa5ef7fb77a8db96890 100644
--- a/include/grpc++/security/credentials.h
+++ b/include/grpc++/security/credentials.h
@@ -45,37 +45,60 @@
 namespace grpc {
 class ChannelArguments;
 class Channel;
-class SecureCredentials;
-
-/// A credentials object encapsulates all the state needed by a client to
-/// authenticate with a server and make various assertions, e.g., about the
-/// client’s identity, role, or whether it is authorized to make a particular
-/// call.
+class SecureChannelCredentials;
+class CallCredentials;
+class SecureCallCredentials;
+
+/// A channel credentials object encapsulates all the state needed by a client
+/// to authenticate with a server for a given channel.
+/// It can make various assertions, e.g., about the client’s identity, role
+/// for all the calls on that channel.
 ///
 /// \see https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md
-class Credentials : public GrpcLibrary {
+class ChannelCredentials : public GrpcLibrary {
  public:
-  ~Credentials() GRPC_OVERRIDE;
-
-  /// Apply this instance's credentials to \a call.
-  virtual bool ApplyToCall(grpc_call* call) = 0;
+  ~ChannelCredentials() GRPC_OVERRIDE;
 
  protected:
-  friend std::shared_ptr<Credentials> CompositeCredentials(
-      const std::shared_ptr<Credentials>& creds1,
-      const std::shared_ptr<Credentials>& creds2);
+  friend std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
+      const std::shared_ptr<ChannelCredentials>& channel_creds,
+      const std::shared_ptr<CallCredentials>& call_creds);
 
-  virtual SecureCredentials* AsSecureCredentials() = 0;
+  virtual SecureChannelCredentials* AsSecureCredentials() = 0;
 
  private:
   friend std::shared_ptr<Channel> CreateCustomChannel(
-      const grpc::string& target, const std::shared_ptr<Credentials>& creds,
+      const grpc::string& target,
+      const std::shared_ptr<ChannelCredentials>& creds,
       const ChannelArguments& args);
 
   virtual std::shared_ptr<Channel> CreateChannel(
       const grpc::string& target, const ChannelArguments& args) = 0;
 };
 
+/// A call credentials object encapsulates the state needed by a client to
+/// authenticate with a server for a given call on a channel.
+///
+/// \see https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md
+class CallCredentials : public GrpcLibrary {
+ public:
+  ~CallCredentials() GRPC_OVERRIDE;
+
+  /// Apply this instance's credentials to \a call.
+  virtual bool ApplyToCall(grpc_call* call) = 0;
+
+ protected:
+  friend std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
+      const std::shared_ptr<ChannelCredentials>& channel_creds,
+      const std::shared_ptr<CallCredentials>& call_creds);
+
+  friend std::shared_ptr<CallCredentials> CompositeCallCredentials(
+      const std::shared_ptr<CallCredentials>& creds1,
+      const std::shared_ptr<CallCredentials>& creds2);
+
+  virtual SecureCallCredentials* AsSecureCredentials() = 0;
+};
+
 /// Options used to build SslCredentials.
 struct SslCredentialsOptions {
   /// The buffer containing the PEM encoding of the server root certificates. If
@@ -106,10 +129,10 @@ struct SslCredentialsOptions {
 /// Using these credentials to connect to any other service may result in this
 /// service being able to impersonate your client for requests to Google
 /// services.
-std::shared_ptr<Credentials> GoogleDefaultCredentials();
+std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials();
 
 /// Builds SSL Credentials given SSL specific options
-std::shared_ptr<Credentials> SslCredentials(
+std::shared_ptr<ChannelCredentials> SslCredentials(
     const SslCredentialsOptions& options);
 
 /// Builds credentials for use when running in GCE
@@ -118,14 +141,14 @@ std::shared_ptr<Credentials> SslCredentials(
 /// Using these credentials to connect to any other service may result in this
 /// service being able to impersonate your client for requests to Google
 /// services.
-std::shared_ptr<Credentials> GoogleComputeEngineCredentials();
+std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials();
 
 /// Builds Service Account JWT Access credentials.
 /// json_key is the JSON key string containing the client's private key.
 /// token_lifetime_seconds is the lifetime in seconds of each Json Web Token
 /// (JWT) created with this credentials. It should not exceed
 /// grpc_max_auth_token_lifetime or will be cropped to this value.
-std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
+std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
     const grpc::string& json_key, long token_lifetime_seconds);
 
 /// Builds refresh token credentials.
@@ -136,7 +159,7 @@ std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
 /// Using these credentials to connect to any other service may result in this
 /// service being able to impersonate your client for requests to Google
 /// services.
-std::shared_ptr<Credentials> GoogleRefreshTokenCredentials(
+std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
     const grpc::string& json_refresh_token);
 
 /// Builds access token credentials.
@@ -147,7 +170,7 @@ std::shared_ptr<Credentials> GoogleRefreshTokenCredentials(
 /// Using these credentials to connect to any other service may result in this
 /// service being able to impersonate your client for requests to Google
 /// services.
-std::shared_ptr<Credentials> AccessTokenCredentials(
+std::shared_ptr<CallCredentials> AccessTokenCredentials(
     const grpc::string& access_token);
 
 /// Builds IAM credentials.
@@ -156,17 +179,23 @@ std::shared_ptr<Credentials> AccessTokenCredentials(
 /// Using these credentials to connect to any other service may result in this
 /// service being able to impersonate your client for requests to Google
 /// services.
-std::shared_ptr<Credentials> GoogleIAMCredentials(
+std::shared_ptr<CallCredentials> GoogleIAMCredentials(
     const grpc::string& authorization_token,
     const grpc::string& authority_selector);
 
-/// Combines two credentials objects into a composite credentials
-std::shared_ptr<Credentials> CompositeCredentials(
-    const std::shared_ptr<Credentials>& creds1,
-    const std::shared_ptr<Credentials>& creds2);
+/// Combines a channel credentials and a call credentials into a composite
+/// channel credentials.
+std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
+    const std::shared_ptr<ChannelCredentials>& channel_creds,
+    const std::shared_ptr<CallCredentials>& call_creds);
+
+/// Combines two call credentials objects into a composite call credentials.
+std::shared_ptr<CallCredentials> CompositeCallCredentials(
+    const std::shared_ptr<CallCredentials>& creds1,
+    const std::shared_ptr<CallCredentials>& creds2);
 
 /// Credentials for an unencrypted, unauthenticated channel
-std::shared_ptr<Credentials> InsecureCredentials();
+std::shared_ptr<ChannelCredentials> InsecureChannelCredentials();
 
 // User defined metadata credentials.
 class MetadataCredentialsPlugin {
@@ -183,7 +212,7 @@ class MetadataCredentialsPlugin {
       std::multimap<grpc::string, grpc::string>* metadata) = 0;
 };
 
-std::shared_ptr<Credentials> MetadataCredentialsFromPlugin(
+std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
     std::unique_ptr<MetadataCredentialsPlugin> plugin);
 
 }  // namespace grpc
diff --git a/include/grpc++/support/channel_arguments.h b/include/grpc++/support/channel_arguments.h
index 9957712a9652c744b91a8f5b274bc4025959518e..cf8eab3b47286d89181a9e7a3cbadc483e189766 100644
--- a/include/grpc++/support/channel_arguments.h
+++ b/include/grpc++/support/channel_arguments.h
@@ -70,7 +70,8 @@ class ChannelArguments {
   void SetChannelArgs(grpc_channel_args* channel_args) const;
 
   // gRPC specific channel argument setters
-  /// Set target name override for SSL host name checking.
+  /// Set target name override for SSL host name checking. This option is for
+  /// testing only and should never be used in production.
   void SetSslTargetNameOverride(const grpc::string& name);
   // TODO(yangg) add flow control options
   /// Set the compression algorithm for the channel.
@@ -83,7 +84,7 @@ class ChannelArguments {
   void SetString(const grpc::string& key, const grpc::string& value);
 
  private:
-  friend class SecureCredentials;
+  friend class SecureChannelCredentials;
   friend class testing::ChannelArgumentsTest;
 
   // Returns empty string when it is not set.
diff --git a/include/grpc++/support/time.h b/include/grpc++/support/time.h
index 2d4196b93b7a3afb6d362d5629c6553bf7bec67d..e00e0d8e9172240d9f9e992e0065cdbfe0bd9658 100644
--- a/include/grpc++/support/time.h
+++ b/include/grpc++/support/time.h
@@ -35,6 +35,7 @@
 #define GRPCXX_SUPPORT_TIME_H
 
 #include <grpc++/support/config.h>
+#include <grpc/support/time.h>
 
 namespace grpc {
 
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 191ad5db1ec08c31e20bdbfe8961db226af59b0f..f07f584ef2c2a5bc66f3095bfb9585b152c5deee 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -127,6 +127,12 @@ typedef struct {
 /** Initial sequence number for http2 transports */
 #define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
   "grpc.http2.initial_sequence_number"
+/** How much memory to use for hpack decoding */
+#define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER \
+  "grpc.http2.hpack_table_size.decoder"
+/** How much memory to use for hpack encoding */
+#define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER \
+  "grpc.http2.hpack_table_size.encoder"
 /** Default authority to pass if none specified on call construction */
 #define GRPC_ARG_DEFAULT_AUTHORITY "grpc.default_authority"
 /** Primary user agent: goes at the start of the user-agent metadata
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 7a442e2ace2e3ff6eb8a1a815b6d1fc597b51c22..c8da59331dbd8a4e126b87b580ba3d49026bd96f 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -41,15 +41,16 @@
 extern "C" {
 #endif
 
-/* --- grpc_credentials object. ---
+/* --- grpc_channel_credentials object. ---
 
-   A credentials object represents a way to authenticate a client.  */
+   A channel credentials object represents a way to authenticate a client on a
+   channel.  */
 
-typedef struct grpc_credentials grpc_credentials;
+typedef struct grpc_channel_credentials grpc_channel_credentials;
 
-/* Releases a credentials object.
+/* Releases a channel credentials object.
    The creator of the credentials object is responsible for its release. */
-void grpc_credentials_release(grpc_credentials *creds);
+void grpc_channel_credentials_release(grpc_channel_credentials *creds);
 
 /* Environment variable that points to the google default application
    credentials json key or refresh token. Used in the
@@ -59,7 +60,7 @@ void grpc_credentials_release(grpc_credentials *creds);
 /* Creates default credentials to connect to a google gRPC service.
    WARNING: Do NOT use this credentials to connect to a non-google service as
    this could result in an oauth2 token leak. */
-grpc_credentials *grpc_google_default_credentials_create(void);
+grpc_channel_credentials *grpc_google_default_credentials_create(void);
 
 /* 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
@@ -88,19 +89,37 @@ typedef struct {
    - pem_key_cert_pair is a pointer on 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. */
-grpc_credentials *grpc_ssl_credentials_create(
+grpc_channel_credentials *grpc_ssl_credentials_create(
     const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
     void *reserved);
 
-/* Creates a composite credentials object. */
-grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
-                                                    grpc_credentials *creds2,
-                                                    void *reserved);
+/* --- grpc_call_credentials object.
+
+   A call credentials object represents a way to authenticate on a particular
+   call. These credentials can be composed with a channel credentials object
+   so that they are sent with every call on this channel.  */
+
+typedef struct grpc_call_credentials grpc_call_credentials;
+
+/* Releases a call credentials object.
+   The creator of the credentials object is responsible for its release. */
+void grpc_call_credentials_release(grpc_call_credentials *creds);
+
+/* Creates a composite channel credentials object. */
+grpc_channel_credentials *grpc_composite_channel_credentials_create(
+    grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
+    void *reserved);
+
+/* Creates a composite call credentials object. */
+grpc_call_credentials *grpc_composite_call_credentials_create(
+    grpc_call_credentials *creds1, grpc_call_credentials *creds2,
+    void *reserved);
 
 /* Creates a compute engine credentials object for connecting to Google.
    WARNING: Do NOT use this credentials to connect to a non-google service as
    this could result in an oauth2 token leak. */
-grpc_credentials *grpc_google_compute_engine_credentials_create(void *reserved);
+grpc_call_credentials *grpc_google_compute_engine_credentials_create(
+    void *reserved);
 
 extern const gpr_timespec grpc_max_auth_token_lifetime;
 
@@ -109,7 +128,7 @@ extern const gpr_timespec grpc_max_auth_token_lifetime;
    - token_lifetime is the lifetime of each Json Web Token (JWT) created with
      this credentials.  It should not exceed grpc_max_auth_token_lifetime or
      will be cropped to this value.  */
-grpc_credentials *grpc_service_account_jwt_access_credentials_create(
+grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
     const char *json_key, gpr_timespec token_lifetime, void *reserved);
 
 /* Creates an Oauth2 Refresh Token credentials object for connecting to Google.
@@ -118,16 +137,16 @@ grpc_credentials *grpc_service_account_jwt_access_credentials_create(
    this could result in an oauth2 token leak.
    - json_refresh_token is the JSON string containing the refresh token itself
      along with a client_id and client_secret. */
-grpc_credentials *grpc_google_refresh_token_credentials_create(
+grpc_call_credentials *grpc_google_refresh_token_credentials_create(
     const char *json_refresh_token, void *reserved);
 
 /* Creates an Oauth2 Access Token credentials with an access token that was
    aquired by an out of band mechanism. */
-grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
-                                                       void *reserved);
+grpc_call_credentials *grpc_access_token_credentials_create(
+    const char *access_token, void *reserved);
 
 /* Creates an IAM credentials object for connecting to Google. */
-grpc_credentials *grpc_google_iam_credentials_create(
+grpc_call_credentials *grpc_google_iam_credentials_create(
     const char *authorization_token, const char *authority_selector,
     void *reserved);
 
@@ -168,13 +187,13 @@ typedef struct {
 } grpc_metadata_credentials_plugin;
 
 /* Creates a credentials object from a plugin. */
-grpc_credentials *grpc_metadata_credentials_create_from_plugin(
+grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
     grpc_metadata_credentials_plugin plugin, void *reserved);
 
 /* --- Secure channel creation. --- */
 
 /* Creates a secure channel using the passed-in credentials. */
-grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
+grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
                                          const char *target,
                                          const grpc_channel_args *args,
                                          void *reserved);
@@ -218,7 +237,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
 /* Sets a credentials to a call. Can only be called on the client side before
    grpc_call_start_batch. */
 grpc_call_error grpc_call_set_credentials(grpc_call *call,
-                                          grpc_credentials *creds);
+                                          grpc_call_credentials *creds);
 
 /* --- Authentication Context. --- */
 
diff --git a/reports/interop_html_report.template b/reports/interop_html_report.template
new file mode 100644
index 0000000000000000000000000000000000000000..1ba2e6cfc22f484142d45d4bf1b3a0a83bf065f1
--- /dev/null
+++ b/reports/interop_html_report.template
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<html lang="en">
+<head><title>Interop Test Result</title></head>
+<body>
+
+<%def name="fill_one_test_result(shortname, resultset)">
+  % if shortname in resultset:
+    ## Because interop tests does not have runs_per_test flag, each test is 
+    ## run once. So there should only be one element for each result.
+    <% result = resultset[shortname][0] %>
+    % if result.state == 'PASSED':      
+        <td bgcolor="green">PASS</td>
+    % else:
+      <% 
+        tooltip = ''
+        if result.returncode > 0 or result.message:
+          if result.returncode > 0:
+            tooltip = 'returncode: %d ' % result.returncode
+          if result.message:
+            tooltip = '%smessage: %s' % (tooltip, result.message)  
+      %>     
+      % if result.state == 'FAILED':
+        <td bgcolor="red">
+        % if tooltip:  
+          <a href="#" data-toggle="tooltip" data-placement="auto" title="${tooltip | h}">FAIL</a></td>
+        % else:
+          FAIL</td>
+        % endif
+      % elif result.state == 'TIMEOUT':
+        <td bgcolor="yellow">
+        % if tooltip:
+          <a href="#" data-toggle="tooltip" data-placement="auto" title="${tooltip | h}">TIMEOUT</a></td> 
+        % else:
+          TIMEOUT</td>
+        % endif
+      % endif
+    % endif
+  % else:
+     <td bgcolor="magenta">Not implemented</td>
+  % endif
+</%def>
+
+% if num_failures > 1:
+  <p><h2><font color="red">${num_failures} tests failed!</font></h2></p>
+% elif num_failures:
+  <p><h2><font color="red">${num_failures} test failed!</font></h2></p>
+% else:
+  <p><h2><font color="green">All tests passed!</font></h2></p>
+% endif
+
+% if cloud_to_prod:
+  ## Each column header is the client language.
+  <h2>Cloud to Prod</h2>
+  <table style="width:100%" border="1">
+  <tr bgcolor="#00BFFF">
+  <th>Client languages &#9658;<br/>Test Cases &#9660;</th>
+  % for client_lang in client_langs:
+    <th>${client_lang}</th>
+  % endfor
+  </tr>
+  % for test_case in test_cases + auth_test_cases:
+    <tr><td><b>${test_case}</b></td>
+    % for client_lang in client_langs:
+      <% 
+        if test_case in auth_test_cases:
+          shortname = 'cloud_to_prod_auth:%s:%s' % (client_lang, test_case)
+        else:
+          shortname = 'cloud_to_prod:%s:%s' % (client_lang, test_case)
+      %>
+      ${fill_one_test_result(shortname, resultset)}
+    % endfor
+    </tr> 
+  % endfor
+  </table>
+% endif
+
+% if http2_interop:
+  ## Each column header is the server language.
+  <h2>HTTP/2 Interop</h2> 
+  <table style="width:100%" border="1">
+  <tr bgcolor="#00BFFF">
+  <th>Servers &#9658;<br/>Test Cases &#9660;</th>
+  % for server_lang in server_langs:
+    <th>${server_lang}</th>
+  % endfor
+  % if cloud_to_prod:
+    <th>prod</th>
+  % endif
+  </tr>
+  % for test_case in http2_cases:
+    <tr><td><b>${test_case}</b></td>
+    ## Fill up the cells with test result.
+    % for server_lang in server_langs:
+      <% 
+        shortname = 'cloud_to_cloud:http2:%s_server:%s' % (
+            server_lang, test_case)
+      %>
+      ${fill_one_test_result(shortname, resultset)}
+    % endfor
+    % if cloud_to_prod:
+      <% shortname = 'cloud_to_prod:http2:%s' % test_case %>
+      ${fill_one_test_result(shortname, resultset)}
+    % endif
+    </tr>
+  % endfor
+  </table>
+% endif
+
+% if server_langs:
+  % for test_case in test_cases:
+    ## Each column header is the client language.
+    <h2>${test_case}</h2> 
+    <table style="width:100%" border="1">
+    <tr bgcolor="#00BFFF">
+    <th>Client languages &#9658;<br/>Server languages &#9660;</th>
+    % for client_lang in client_langs:
+      <th>${client_lang}</th>
+    % endfor
+    </tr>
+    ## Each row head is the server language.
+    % for server_lang in server_langs:
+      <tr>
+      <td><b>${server_lang}</b></td>
+      % for client_lang in client_langs:
+        <% 
+          shortname = 'cloud_to_cloud:%s:%s_server:%s' % (
+              client_lang, server_lang, test_case)
+        %>
+        ${fill_one_test_result(shortname, resultset)}
+      % endfor
+      </tr>
+    % endfor
+    </table>
+  % endfor
+% endif
+
+<script>
+  $(document).ready(function(){$('[data-toggle="tooltip"]').tooltip();});
+</script>
+</body>
+</html>
diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c
index 49c2cf9a19ee3d9597e30e95409dc4ca3b71eaa4..b15a9033af803bd1261fbb083ddf5fea2fe19ede 100644
--- a/src/core/client_config/subchannel.c
+++ b/src/core/client_config/subchannel.c
@@ -697,10 +697,25 @@ static double generate_uniform_random_number(grpc_subchannel *c) {
 
 /* Update backoff_delta and next_attempt in subchannel */
 static void update_reconnect_parameters(grpc_subchannel *c) {
+  size_t i;
   gpr_int32 backoff_delta_millis, jitter;
   gpr_int32 max_backoff_millis =
       GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000;
   double jitter_range;
+
+  if (c->args) {
+    for (i = 0; i < c->args->num_args; i++) {
+      if (0 == strcmp(c->args->args[i].key,
+                      "grpc.testing.fixed_reconnect_backoff")) {
+        GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
+        c->next_attempt = gpr_time_add(
+            gpr_now(GPR_CLOCK_MONOTONIC),
+            gpr_time_from_millis(c->args->args[i].value.integer, GPR_TIMESPAN));
+        return;
+      }
+    }
+  }
+
   backoff_delta_millis =
       (gpr_int32)(gpr_time_to_millis(c->backoff_delta) *
                   GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER);
diff --git a/src/core/client_config/subchannel.h b/src/core/client_config/subchannel.h
index 1fefa1888a7d279b6c12c18fd826e3641c365744..381b7689b891d62a40125b055ccb5e8527158e3a 100644
--- a/src/core/client_config/subchannel.h
+++ b/src/core/client_config/subchannel.h
@@ -77,10 +77,10 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
 
 /** construct a subchannel call (possibly asynchronously).
  *
- * If the returned status is 1, the call will return immediately and \a target 
- * will point to a connected \a subchannel_call instance. Note that \a notify 
+ * If the returned status is 1, the call will return immediately and \a target
+ * will point to a connected \a subchannel_call instance. Note that \a notify
  * will \em not be invoked in this case.
- * Otherwise, if the returned status is 0, the subchannel call will be created 
+ * Otherwise, if the returned status is 0, the subchannel call will be created
  * asynchronously, invoking the \a notify callback upon completion. */
 int grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx,
                                 grpc_subchannel *subchannel,
diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c
index c3f310ee27f518d9fc6b0b71901228174cd7c0bd..deb661548d291a34b0f2123ca75e86544dfa543e 100644
--- a/src/core/iomgr/pollset_windows.c
+++ b/src/core/iomgr/pollset_windows.c
@@ -126,7 +126,8 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {}
 
 void grpc_pollset_reset(grpc_pollset *pollset) {
   GPR_ASSERT(pollset->shutting_down);
-  GPR_ASSERT(!has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
+  GPR_ASSERT(
+      !has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
   pollset->shutting_down = 0;
   pollset->is_iocp_worker = 0;
   pollset->kicked_without_pollers = 0;
diff --git a/src/core/iomgr/tcp_server.h b/src/core/iomgr/tcp_server.h
index 882635f6388b9afe4c78a67714533094a5153c6d..3df36174e7bbb02b2eac50dc5c2d1d6ed79731ce 100644
--- a/src/core/iomgr/tcp_server.h
+++ b/src/core/iomgr/tcp_server.h
@@ -39,6 +39,9 @@
 /* Forward decl of grpc_tcp_server */
 typedef struct grpc_tcp_server grpc_tcp_server;
 
+/* Forward decl of grpc_tcp_listener */
+typedef struct grpc_tcp_listener grpc_tcp_listener;
+
 /* Called for newly connected TCP connections. */
 typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg,
                                    grpc_endpoint *ep);
@@ -51,19 +54,18 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
                            grpc_pollset **pollsets, size_t pollset_count,
                            grpc_tcp_server_cb on_accept_cb, void *cb_arg);
 
-/* Add a port to the server, returning port number on success, or negative
-   on failure.
+/* Add a port to the server, returning the newly created listener on success,
+   or a null pointer on failure.
 
    The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
    both IPv4 and IPv6 connections, but :: is the preferred style.  This usually
    creates one socket, but possibly two on systems which support IPv6,
-   but not dualstack sockets.
-
-   For raw access to the underlying sockets, see grpc_tcp_server_get_fd(). */
+   but not dualstack sockets. */
 /* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle
                   all of the multiple socket port matching logic in one place */
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len);
+grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
+                                            const void *addr,
+                                            size_t addr_len);
 
 /* Returns the file descriptor of the Nth listening socket on this server,
    or -1 if the index is out of bounds.
@@ -75,4 +77,8 @@ int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index);
 void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
                              grpc_closure *closure);
 
+int grpc_tcp_listener_get_port(grpc_tcp_listener *listener);
+void grpc_tcp_listener_ref(grpc_tcp_listener *listener);
+void grpc_tcp_listener_unref(grpc_tcp_listener *listener);
+
 #endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */
diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c
index 99c76dcbe9aeddfd7d303e994fba5526e9057bea..1439dfcd6edb0b6b773a19344ba0540a3d84ab08 100644
--- a/src/core/iomgr/tcp_server_posix.c
+++ b/src/core/iomgr/tcp_server_posix.c
@@ -67,14 +67,13 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 
-#define INIT_PORT_CAP 2
 #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
 
 static gpr_once s_init_max_accept_queue_size;
 static int s_max_accept_queue_size;
 
 /* one listening port */
-typedef struct {
+struct grpc_tcp_listener {
   int fd;
   grpc_fd *emfd;
   grpc_tcp_server *server;
@@ -84,9 +83,18 @@ typedef struct {
     struct sockaddr_un un;
   } addr;
   size_t addr_len;
+  int port;
   grpc_closure read_closure;
   grpc_closure destroyed_closure;
-} server_port;
+  gpr_refcount refs;
+  struct grpc_tcp_listener *next;
+  /* When we add a listener, more than one can be created, mainly because of
+     IPv6. A sibling will still be in the normal list, but will be flagged
+     as such. Any action, such as ref or unref, will affect all of the
+     siblings in the list. */
+  struct grpc_tcp_listener *sibling;
+  int is_sibling;
+};
 
 static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) {
   struct stat st;
@@ -112,10 +120,9 @@ struct grpc_tcp_server {
   /* is this server shutting down? (boolean) */
   int shutdown;
 
-  /* all listening ports */
-  server_port *ports;
-  size_t nports;
-  size_t port_capacity;
+  /* linked list of server ports */
+  grpc_tcp_listener *head;
+  unsigned nports;
 
   /* shutdown callback */
   grpc_closure *shutdown_complete;
@@ -134,9 +141,8 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
   s->shutdown = 0;
   s->on_accept_cb = NULL;
   s->on_accept_cb_arg = NULL;
-  s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
+  s->head = NULL;
   s->nports = 0;
-  s->port_capacity = INIT_PORT_CAP;
   return s;
 }
 
@@ -145,7 +151,12 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
 
   gpr_mu_destroy(&s->mu);
 
-  gpr_free(s->ports);
+  while (s->head) {
+    grpc_tcp_listener *sp = s->head;
+    s->head = sp->next;
+    grpc_tcp_listener_unref(sp);
+  }
+
   gpr_free(s);
 }
 
@@ -166,8 +177,6 @@ static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, int success) {
    events will be received on them - at this point it's safe to destroy
    things */
 static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  size_t i;
-
   /* delete ALL the things */
   gpr_mu_lock(&s->mu);
 
@@ -176,9 +185,9 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
     return;
   }
 
-  if (s->nports) {
-    for (i = 0; i < s->nports; i++) {
-      server_port *sp = &s->ports[i];
+  if (s->head) {
+    grpc_tcp_listener *sp;
+    for (sp = s->head; sp; sp = sp->next) {
       if (sp->addr.sockaddr.sa_family == AF_UNIX) {
         unlink_if_unix_domain_socket(&sp->addr.un);
       }
@@ -196,7 +205,6 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
 
 void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
                              grpc_closure *closure) {
-  size_t i;
   gpr_mu_lock(&s->mu);
 
   GPR_ASSERT(!s->shutdown);
@@ -206,8 +214,9 @@ void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
 
   /* shutdown all fd's */
   if (s->active_ports) {
-    for (i = 0; i < s->nports; i++) {
-      grpc_fd_shutdown(exec_ctx, s->ports[i].emfd);
+    grpc_tcp_listener *sp;
+    for (sp = s->head; sp; sp = sp->next) {
+      grpc_fd_shutdown(exec_ctx, sp->emfd);
     }
     gpr_mu_unlock(&s->mu);
   } else {
@@ -298,7 +307,7 @@ error:
 
 /* event manager callback when reads are ready */
 static void on_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
-  server_port *sp = arg;
+  grpc_tcp_listener *sp = arg;
   grpc_fd *fdobj;
   size_t i;
 
@@ -364,9 +373,10 @@ error:
   }
 }
 
-static int add_socket_to_server(grpc_tcp_server *s, int fd,
-                                const struct sockaddr *addr, size_t addr_len) {
-  server_port *sp;
+static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
+                                         const struct sockaddr *addr,
+                                         size_t addr_len) {
+  grpc_tcp_listener *sp = NULL;
   int port;
   char *addr_str;
   char *name;
@@ -376,32 +386,35 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd,
     grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
     gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
     gpr_mu_lock(&s->mu);
+    s->nports++;
     GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
-    /* append it to the list under a lock */
-    if (s->nports == s->port_capacity) {
-      s->port_capacity *= 2;
-      s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
-    }
-    sp = &s->ports[s->nports++];
+    sp = gpr_malloc(sizeof(grpc_tcp_listener));
+    sp->next = s->head;
+    s->head = sp;
     sp->server = s;
     sp->fd = fd;
     sp->emfd = grpc_fd_create(fd, name);
     memcpy(sp->addr.untyped, addr, addr_len);
     sp->addr_len = addr_len;
+    sp->port = port;
+    sp->is_sibling = 0;
+    sp->sibling = NULL;
+    gpr_ref_init(&sp->refs, 1);
     GPR_ASSERT(sp->emfd);
     gpr_mu_unlock(&s->mu);
     gpr_free(addr_str);
     gpr_free(name);
   }
 
-  return port;
+  return sp;
 }
 
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len) {
-  int allocated_port1 = -1;
-  int allocated_port2 = -1;
-  unsigned i;
+grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
+                                            const void *addr,
+                                            size_t addr_len) {
+  int allocated_port = -1;
+  grpc_tcp_listener *sp;
+  grpc_tcp_listener *sp2 = NULL;
   int fd;
   grpc_dualstack_mode dsmode;
   struct sockaddr_in6 addr6_v4mapped;
@@ -420,9 +433,9 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
   /* Check if this is a wildcard port, and if so, try to keep the port the same
      as some previously created listener. */
   if (grpc_sockaddr_get_port(addr) == 0) {
-    for (i = 0; i < s->nports; i++) {
+    for (sp = s->head; sp; sp = sp->next) {
       sockname_len = sizeof(sockname_temp);
-      if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp,
+      if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
                            &sockname_len)) {
         port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
         if (port > 0) {
@@ -436,6 +449,8 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
     }
   }
 
+  sp = NULL;
+
   if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
     addr = (const struct sockaddr *)&addr6_v4mapped;
     addr_len = sizeof(addr6_v4mapped);
@@ -449,14 +464,16 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
     addr = (struct sockaddr *)&wild6;
     addr_len = sizeof(wild6);
     fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
-    allocated_port1 = add_socket_to_server(s, fd, addr, addr_len);
+    sp = add_socket_to_server(s, fd, addr, addr_len);
+    allocated_port = sp->port;
     if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
       goto done;
     }
 
     /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
-    if (port == 0 && allocated_port1 > 0) {
-      grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1);
+    if (port == 0 && allocated_port > 0) {
+      grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port);
+      sp2 = sp;
     }
     addr = (struct sockaddr *)&wild4;
     addr_len = sizeof(wild4);
@@ -471,22 +488,31 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
     addr = (struct sockaddr *)&addr4_copy;
     addr_len = sizeof(addr4_copy);
   }
-  allocated_port2 = add_socket_to_server(s, fd, addr, addr_len);
+  sp = add_socket_to_server(s, fd, addr, addr_len);
+  sp->sibling = sp2;
+  if (sp2) sp2->is_sibling = 1;
 
 done:
   gpr_free(allocated_addr);
-  return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
+  return sp;
 }
 
 int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) {
-  return (port_index < s->nports) ? s->ports[port_index].fd : -1;
+  grpc_tcp_listener *sp;
+  for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--);
+  if (port_index == 0 && sp) {
+    return sp->fd;
+  } else {
+    return -1;
+  }
 }
 
 void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
                            grpc_pollset **pollsets, size_t pollset_count,
                            grpc_tcp_server_cb on_accept_cb,
                            void *on_accept_cb_arg) {
-  size_t i, j;
+  size_t i;
+  grpc_tcp_listener *sp;
   GPR_ASSERT(on_accept_cb);
   gpr_mu_lock(&s->mu);
   GPR_ASSERT(!s->on_accept_cb);
@@ -495,17 +521,41 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
   s->on_accept_cb_arg = on_accept_cb_arg;
   s->pollsets = pollsets;
   s->pollset_count = pollset_count;
-  for (i = 0; i < s->nports; i++) {
-    for (j = 0; j < pollset_count; j++) {
-      grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd);
+  for (sp = s->head; sp; sp = sp->next) {
+    for (i = 0; i < pollset_count; i++) {
+      grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
     }
-    s->ports[i].read_closure.cb = on_read;
-    s->ports[i].read_closure.cb_arg = &s->ports[i];
-    grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd,
-                           &s->ports[i].read_closure);
+    sp->read_closure.cb = on_read;
+    sp->read_closure.cb_arg = sp;
+    grpc_fd_notify_on_read(exec_ctx, sp->emfd,
+                           &sp->read_closure);
     s->active_ports++;
   }
   gpr_mu_unlock(&s->mu);
 }
 
+int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
+  grpc_tcp_listener *sp = listener;
+  return sp->port;
+}
+
+void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {
+  grpc_tcp_listener *sp = listener;
+  gpr_ref(&sp->refs);
+}
+
+void grpc_tcp_listener_unref(grpc_tcp_listener *listener) {
+  grpc_tcp_listener *sp = listener;
+  if (sp->is_sibling) return;
+  if (gpr_unref(&sp->refs)) {
+    grpc_tcp_listener *sibling = sp->sibling;
+    while (sibling) {
+      sp = sibling;
+      sibling = sp->sibling;
+      gpr_free(sp);
+    }
+    gpr_free(listener);
+  }
+}
+
 #endif
diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c
index 3fea8b5b35059cebda7c044de874415662f2844f..e4a1d7f498cef01f4529c0e6271d50b0b5248d7d 100644
--- a/src/core/iomgr/tcp_server_windows.c
+++ b/src/core/iomgr/tcp_server_windows.c
@@ -35,7 +35,8 @@
 
 #ifdef GPR_WINSOCK_SOCKET
 
-#define _GNU_SOURCE
+#include <io.h>
+
 #include "src/core/iomgr/sockaddr_utils.h"
 
 #include <grpc/support/alloc.h>
@@ -51,25 +52,29 @@
 #include "src/core/iomgr/tcp_server.h"
 #include "src/core/iomgr/tcp_windows.h"
 
-#define INIT_PORT_CAP 2
 #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
 
 /* one listening port */
-typedef struct server_port {
+struct grpc_tcp_listener {
   /* This seemingly magic number comes from AcceptEx's documentation. each
      address buffer needs to have at least 16 more bytes at their end. */
   gpr_uint8 addresses[(sizeof(struct sockaddr_in6) + 16) * 2];
   /* This will hold the socket for the next accept. */
   SOCKET new_socket;
-  /* The listener winsocked. */
+  /* The listener winsocket. */
   grpc_winsocket *socket;
+  /* The actual TCP port number. */
+  int port;
   grpc_tcp_server *server;
   /* The cached AcceptEx for that port. */
   LPFN_ACCEPTEX AcceptEx;
   int shutting_down;
   /* closure for socket notification of accept being ready */
   grpc_closure on_accept;
-} server_port;
+  gpr_refcount refs;
+  /* linked list */
+  struct grpc_tcp_listener *next;
+};
 
 /* the overall server */
 struct grpc_tcp_server {
@@ -82,10 +87,8 @@ struct grpc_tcp_server {
   /* active port count: how many ports are actually still listening */
   int active_ports;
 
-  /* all listening ports */
-  server_port *ports;
-  size_t nports;
-  size_t port_capacity;
+  /* linked list of server ports */
+  grpc_tcp_listener *head;
 
   /* shutdown callback */
   grpc_closure *shutdown_complete;
@@ -99,9 +102,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
   s->active_ports = 0;
   s->on_accept_cb = NULL;
   s->on_accept_cb_arg = NULL;
-  s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
-  s->nports = 0;
-  s->port_capacity = INIT_PORT_CAP;
+  s->head = NULL;
   s->shutdown_complete = NULL;
   return s;
 }
@@ -109,26 +110,26 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
 static void dont_care_about_shutdown_completion(void *arg) {}
 
 static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
-  size_t i;
-
   grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1);
 
   /* Now that the accepts have been aborted, we can destroy the sockets.
      The IOCP won't get notified on these, so we can flag them as already
      closed by the system. */
-  for (i = 0; i < s->nports; i++) {
-    server_port *sp = &s->ports[i];
+  while (s->head) {
+    grpc_tcp_listener *sp = s->head;
+    s->head = sp->next;
+    sp->next = NULL;
     grpc_winsocket_destroy(sp->socket);
+    grpc_tcp_listener_unref(sp);
   }
-  gpr_free(s->ports);
   gpr_free(s);
 }
 
 /* Public function. Stops and destroys a grpc_tcp_server. */
 void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
                              grpc_closure *shutdown_complete) {
-  size_t i;
   int immediately_done = 0;
+  grpc_tcp_listener *sp;
   gpr_mu_lock(&s->mu);
 
   s->shutdown_complete = shutdown_complete;
@@ -138,8 +139,7 @@ void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
   if (s->active_ports == 0) {
     immediately_done = 1;
   }
-  for (i = 0; i < s->nports; i++) {
-    server_port *sp = &s->ports[i];
+  for (sp = s->head; sp; sp = sp->next) {
     sp->shutting_down = 1;
     grpc_winsocket_shutdown(sp->socket);
   }
@@ -199,7 +199,7 @@ error:
 }
 
 static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
-                                              server_port *sp) {
+                                              grpc_tcp_listener *sp) {
   int notify = 0;
   sp->shutting_down = 0;
   gpr_mu_lock(&sp->server->mu);
@@ -216,7 +216,7 @@ static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
 
 /* In order to do an async accept, we need to create a socket first which
    will be the one assigned to the new incoming connection. */
-static void start_accept(grpc_exec_ctx *exec_ctx, server_port *port) {
+static void start_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) {
   SOCKET sock = INVALID_SOCKET;
   char *message;
   char *utf8_message;
@@ -276,7 +276,7 @@ failure:
 
 /* Event manager callback when reads are ready. */
 static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, int from_iocp) {
-  server_port *sp = arg;
+  grpc_tcp_listener *sp = arg;
   SOCKET sock = sp->new_socket;
   grpc_winsocket_callback_info *info = &sp->socket->read_info;
   grpc_endpoint *ep = NULL;
@@ -351,16 +351,17 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, int from_iocp) {
   start_accept(exec_ctx, sp);
 }
 
-static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
-                                const struct sockaddr *addr, size_t addr_len) {
-  server_port *sp;
+static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
+                                         const struct sockaddr *addr,
+                                         size_t addr_len) {
+  grpc_tcp_listener *sp = NULL;
   int port;
   int status;
   GUID guid = WSAID_ACCEPTEX;
   DWORD ioctl_num_bytes;
   LPFN_ACCEPTEX AcceptEx;
 
-  if (sock == INVALID_SOCKET) return -1;
+  if (sock == INVALID_SOCKET) return NULL;
 
   /* We need to grab the AcceptEx pointer for that port, as it may be
      interface-dependent. We'll cache it to avoid doing that again. */
@@ -373,37 +374,35 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
     gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
     gpr_free(utf8_message);
     closesocket(sock);
-    return -1;
+    return NULL;
   }
 
   port = prepare_socket(sock, addr, addr_len);
   if (port >= 0) {
     gpr_mu_lock(&s->mu);
     GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
-    /* append it to the list under a lock */
-    if (s->nports == s->port_capacity) {
-      /* too many ports, and we need to store their address in a closure */
-      /* TODO(ctiller): make server_port a linked list */
-      abort();
-    }
-    sp = &s->ports[s->nports++];
+    sp = gpr_malloc(sizeof(grpc_tcp_listener));
+    sp->next = s->head;
+    s->head = sp;
     sp->server = s;
     sp->socket = grpc_winsocket_create(sock, "listener");
     sp->shutting_down = 0;
     sp->AcceptEx = AcceptEx;
     sp->new_socket = INVALID_SOCKET;
+    sp->port = port;
+    gpr_ref_init(&sp->refs, 1);
     grpc_closure_init(&sp->on_accept, on_accept, sp);
     GPR_ASSERT(sp->socket);
     gpr_mu_unlock(&s->mu);
   }
 
-  return port;
+  return sp;
 }
 
-int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
-                             size_t addr_len) {
-  int allocated_port = -1;
-  unsigned i;
+grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
+                                            const void *addr,
+                                            size_t addr_len) {
+  grpc_tcp_listener *sp;
   SOCKET sock;
   struct sockaddr_in6 addr6_v4mapped;
   struct sockaddr_in6 wildcard;
@@ -415,9 +414,9 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
   /* Check if this is a wildcard port, and if so, try to keep the port the same
      as some previously created listener. */
   if (grpc_sockaddr_get_port(addr) == 0) {
-    for (i = 0; i < s->nports; i++) {
+    for (sp = s->head; sp; sp = sp->next) {
       sockname_len = sizeof(sockname_temp);
-      if (0 == getsockname(s->ports[i].socket->socket,
+      if (0 == getsockname(sp->socket->socket,
                            (struct sockaddr *)&sockname_temp, &sockname_len)) {
         port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
         if (port > 0) {
@@ -452,33 +451,55 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
     gpr_free(utf8_message);
   }
 
-  allocated_port = add_socket_to_server(s, sock, addr, addr_len);
+  sp = add_socket_to_server(s, sock, addr, addr_len);
   gpr_free(allocated_addr);
 
-  return allocated_port;
+  return sp;
 }
 
-SOCKET
-grpc_tcp_server_get_socket(grpc_tcp_server *s, unsigned index) {
-  return (index < s->nports) ? s->ports[index].socket->socket : INVALID_SOCKET;
+int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) {
+  grpc_tcp_listener *sp;
+  for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--);
+  if (port_index == 0 && sp) {
+    return _open_osfhandle(sp->socket->socket, 0);
+  } else {
+    return -1;
+  }
 }
 
 void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
                            grpc_pollset **pollset, size_t pollset_count,
                            grpc_tcp_server_cb on_accept_cb,
                            void *on_accept_cb_arg) {
-  size_t i;
+  grpc_tcp_listener *sp;
   GPR_ASSERT(on_accept_cb);
   gpr_mu_lock(&s->mu);
   GPR_ASSERT(!s->on_accept_cb);
   GPR_ASSERT(s->active_ports == 0);
   s->on_accept_cb = on_accept_cb;
   s->on_accept_cb_arg = on_accept_cb_arg;
-  for (i = 0; i < s->nports; i++) {
-    start_accept(exec_ctx, s->ports + i);
+  for (sp = s->head; sp; sp = sp->next) {
+    start_accept(exec_ctx, sp);
     s->active_ports++;
   }
   gpr_mu_unlock(&s->mu);
 }
 
+int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
+  grpc_tcp_listener *sp = listener;
+  return sp->port;
+}
+
+void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {
+  grpc_tcp_listener *sp = listener;
+  gpr_ref(&sp->refs);
+}
+
+void grpc_tcp_listener_unref(grpc_tcp_listener *listener) {
+  grpc_tcp_listener *sp = listener;
+  if (gpr_unref(&sp->refs)) {
+    gpr_free(listener);
+  }
+}
+
 #endif /* GPR_WINSOCK_SOCKET */
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index c780b65873cb02145d4a456b28bec165323096ef..be2522a7a01fbdd70662eb227815bafe0243716d 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -50,7 +50,7 @@
 
 /* We can have a per-call credentials. */
 typedef struct {
-  grpc_credentials *creds;
+  grpc_call_credentials *creds;
   grpc_mdstr *host;
   grpc_mdstr *method;
   /* pollset bound to this call; if we need to make external
@@ -143,39 +143,35 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
   channel_data *chand = elem->channel_data;
   grpc_client_security_context *ctx =
       (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
-  grpc_credentials *channel_creds =
+  grpc_call_credentials *channel_call_creds =
       chand->security_connector->request_metadata_creds;
-  int channel_creds_has_md =
-      (channel_creds != NULL) &&
-      grpc_credentials_has_request_metadata(channel_creds);
-  int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL) &&
-                          grpc_credentials_has_request_metadata(ctx->creds);
+  int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL);
 
-  if (!channel_creds_has_md && !call_creds_has_md) {
+  if (channel_call_creds == NULL && !call_creds_has_md) {
     /* Skip sending metadata altogether. */
     grpc_call_next_op(exec_ctx, elem, op);
     return;
   }
 
-  if (channel_creds_has_md && call_creds_has_md) {
-    calld->creds =
-        grpc_composite_credentials_create(channel_creds, ctx->creds, NULL);
+  if (channel_call_creds != NULL && call_creds_has_md) {
+    calld->creds = grpc_composite_call_credentials_create(channel_call_creds,
+                                                          ctx->creds, NULL);
     if (calld->creds == NULL) {
       bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT,
                       "Incompatible credentials set on channel and call.");
       return;
     }
   } else {
-    calld->creds =
-        grpc_credentials_ref(call_creds_has_md ? ctx->creds : channel_creds);
+    calld->creds = grpc_call_credentials_ref(
+        call_creds_has_md ? ctx->creds : channel_call_creds);
   }
 
   build_service_url(chand->security_connector->base.url_scheme, calld);
   calld->op = *op; /* Copy op (originates from the caller's stack). */
   GPR_ASSERT(calld->pollset);
-  grpc_credentials_get_request_metadata(exec_ctx, calld->creds, calld->pollset,
-                                        calld->service_url,
-                                        on_credentials_metadata, elem);
+  grpc_call_credentials_get_request_metadata(exec_ctx, calld->creds,
+                                             calld->pollset, calld->service_url,
+                                             on_credentials_metadata, elem);
 }
 
 static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -282,7 +278,7 @@ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
 static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
                               grpc_call_element *elem) {
   call_data *calld = elem->call_data;
-  grpc_credentials_unref(calld->creds);
+  grpc_call_credentials_unref(calld->creds);
   if (calld->host != NULL) {
     GRPC_MDSTR_UNREF(calld->host);
   }
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 2a8ffae5d7f08974782e9e2c24d928117005ca6e..f7a2e7378588a9575ff7851ecc4ad7a85d1183ab 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -54,18 +54,18 @@
 /* -- Common. -- */
 
 struct grpc_credentials_metadata_request {
-  grpc_credentials *creds;
+  grpc_call_credentials *creds;
   grpc_credentials_metadata_cb cb;
   void *user_data;
 };
 
 static grpc_credentials_metadata_request *
-grpc_credentials_metadata_request_create(grpc_credentials *creds,
+grpc_credentials_metadata_request_create(grpc_call_credentials *creds,
                                          grpc_credentials_metadata_cb cb,
                                          void *user_data) {
   grpc_credentials_metadata_request *r =
       gpr_malloc(sizeof(grpc_credentials_metadata_request));
-  r->creds = grpc_credentials_ref(creds);
+  r->creds = grpc_call_credentials_ref(creds);
   r->cb = cb;
   r->user_data = user_data;
   return r;
@@ -73,44 +73,56 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds,
 
 static void grpc_credentials_metadata_request_destroy(
     grpc_credentials_metadata_request *r) {
-  grpc_credentials_unref(r->creds);
+  grpc_call_credentials_unref(r->creds);
   gpr_free(r);
 }
 
-grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) {
+grpc_channel_credentials *grpc_channel_credentials_ref(
+    grpc_channel_credentials *creds) {
   if (creds == NULL) return NULL;
   gpr_ref(&creds->refcount);
   return creds;
 }
 
-void grpc_credentials_unref(grpc_credentials *creds) {
+void grpc_channel_credentials_unref(grpc_channel_credentials *creds) {
   if (creds == NULL) return;
   if (gpr_unref(&creds->refcount)) {
-    creds->vtable->destruct(creds);
+    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
     gpr_free(creds);
   }
 }
 
-void grpc_credentials_release(grpc_credentials *creds) {
-  GRPC_API_TRACE("grpc_credentials_release(creds=%p)", 1, (creds));
-  grpc_credentials_unref(creds);
+void grpc_channel_credentials_release(grpc_channel_credentials *creds) {
+  GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds));
+  grpc_channel_credentials_unref(creds);
 }
 
-int grpc_credentials_has_request_metadata(grpc_credentials *creds) {
-  if (creds == NULL) return 0;
-  return creds->vtable->has_request_metadata(creds);
+grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) {
+  if (creds == NULL) return NULL;
+  gpr_ref(&creds->refcount);
+  return creds;
+}
+
+void grpc_call_credentials_unref(grpc_call_credentials *creds) {
+  if (creds == NULL) return;
+  if (gpr_unref(&creds->refcount)) {
+    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
+    gpr_free(creds);
+  }
 }
 
-int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) {
-  if (creds == NULL) return 0;
-  return creds->vtable->has_request_metadata_only(creds);
+void grpc_call_credentials_release(grpc_call_credentials *creds) {
+  GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds));
+  grpc_call_credentials_unref(creds);
 }
 
-void grpc_credentials_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
-  if (creds == NULL || !grpc_credentials_has_request_metadata(creds) ||
-      creds->vtable->get_request_metadata == NULL) {
+void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                                grpc_call_credentials *creds,
+                                                grpc_pollset *pollset,
+                                                const char *service_url,
+                                                grpc_credentials_metadata_cb cb,
+                                                void *user_data) {
+  if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
     if (cb != NULL) {
       cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
     }
@@ -120,19 +132,17 @@ void grpc_credentials_get_request_metadata(
                                       user_data);
 }
 
-grpc_security_status grpc_credentials_create_security_connector(
-    grpc_credentials *creds, const char *target, const grpc_channel_args *args,
-    grpc_credentials *request_metadata_creds,
-    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+grpc_security_status grpc_channel_credentials_create_security_connector(
+    grpc_channel_credentials *channel_creds, const char *target,
+    const grpc_channel_args *args, grpc_channel_security_connector **sc,
+    grpc_channel_args **new_args) {
   *new_args = NULL;
-  if (creds == NULL || creds->vtable->create_security_connector == NULL ||
-      grpc_credentials_has_request_metadata_only(creds)) {
-    gpr_log(GPR_ERROR,
-            "Invalid credentials for creating a security connector.");
+  if (channel_creds == NULL) {
     return GRPC_SECURITY_ERROR;
   }
-  return creds->vtable->create_security_connector(
-      creds, target, args, request_metadata_creds, sc, new_args);
+  GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL);
+  return channel_creds->vtable->create_security_connector(
+      channel_creds, NULL, target, args, sc, new_args);
 }
 
 grpc_server_credentials *grpc_server_credentials_ref(
@@ -145,7 +155,7 @@ grpc_server_credentials *grpc_server_credentials_ref(
 void grpc_server_credentials_unref(grpc_server_credentials *creds) {
   if (creds == NULL) return;
   if (gpr_unref(&creds->refcount)) {
-    creds->vtable->destruct(creds);
+    if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
     if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
       creds->processor.destroy(creds->processor.state);
     }
@@ -224,7 +234,7 @@ grpc_server_credentials *grpc_find_server_credentials_in_args(
 
 /* -- Ssl credentials. -- */
 
-static void ssl_destruct(grpc_credentials *creds) {
+static void ssl_destruct(grpc_channel_credentials *creds) {
   grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
   if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
   if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
@@ -253,15 +263,9 @@ static void ssl_server_destruct(grpc_server_credentials *creds) {
   if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
 }
 
-static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; }
-
-static int ssl_has_request_metadata_only(const grpc_credentials *creds) {
-  return 0;
-}
-
 static grpc_security_status ssl_create_security_connector(
-    grpc_credentials *creds, const char *target, const grpc_channel_args *args,
-    grpc_credentials *request_metadata_creds,
+    grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
+    const char *target, const grpc_channel_args *args,
     grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
   grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
   grpc_security_status status = GRPC_SECURITY_OK;
@@ -278,7 +282,7 @@ static grpc_security_status ssl_create_security_connector(
     }
   }
   status = grpc_ssl_channel_security_connector_create(
-      request_metadata_creds, &c->config, target, overridden_target_name, sc);
+      call_creds, &c->config, target, overridden_target_name, sc);
   if (status != GRPC_SECURITY_OK) {
     return status;
   }
@@ -295,9 +299,8 @@ static grpc_security_status ssl_server_create_security_connector(
   return grpc_ssl_server_security_connector_create(&c->config, sc);
 }
 
-static grpc_credentials_vtable ssl_vtable = {
-    ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
-    ssl_create_security_connector};
+static grpc_channel_credentials_vtable ssl_vtable = {
+    ssl_destruct, ssl_create_security_connector};
 
 static grpc_server_credentials_vtable ssl_server_vtable = {
     ssl_server_destruct, ssl_server_create_security_connector};
@@ -362,7 +365,7 @@ static void ssl_build_server_config(
   }
 }
 
-grpc_credentials *grpc_ssl_credentials_create(
+grpc_channel_credentials *grpc_ssl_credentials_create(
     const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
     void *reserved) {
   grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
@@ -373,7 +376,7 @@ grpc_credentials *grpc_ssl_credentials_create(
       3, (pem_root_certs, pem_key_cert_pair, reserved));
   GPR_ASSERT(reserved == NULL);
   memset(c, 0, sizeof(grpc_ssl_credentials));
-  c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
+  c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
   c->base.vtable = &ssl_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
@@ -393,7 +396,7 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
           force_client_auth, reserved));
   GPR_ASSERT(reserved == NULL);
   memset(c, 0, sizeof(grpc_ssl_server_credentials));
-  c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
+  c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
   gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &ssl_server_vtable;
   ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
@@ -415,7 +418,7 @@ static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
   c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
 }
 
-static void jwt_destruct(grpc_credentials *creds) {
+static void jwt_destruct(grpc_call_credentials *creds) {
   grpc_service_account_jwt_access_credentials *c =
       (grpc_service_account_jwt_access_credentials *)creds;
   grpc_auth_json_key_destruct(&c->key);
@@ -423,15 +426,12 @@ static void jwt_destruct(grpc_credentials *creds) {
   gpr_mu_destroy(&c->cache_mu);
 }
 
-static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
-
-static int jwt_has_request_metadata_only(const grpc_credentials *creds) {
-  return 1;
-}
-
-static void jwt_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
+static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                     grpc_call_credentials *creds,
+                                     grpc_pollset *pollset,
+                                     const char *service_url,
+                                     grpc_credentials_metadata_cb cb,
+                                     void *user_data) {
   grpc_service_account_jwt_access_credentials *c =
       (grpc_service_account_jwt_access_credentials *)creds;
   gpr_timespec refresh_threshold = gpr_time_from_seconds(
@@ -483,11 +483,10 @@ static void jwt_get_request_metadata(
   }
 }
 
-static grpc_credentials_vtable jwt_vtable = {
-    jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only,
-    jwt_get_request_metadata, NULL};
+static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
+                                                  jwt_get_request_metadata};
 
-grpc_credentials *
+grpc_call_credentials *
 grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
     grpc_auth_json_key key, gpr_timespec token_lifetime) {
   grpc_service_account_jwt_access_credentials *c;
@@ -497,7 +496,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
   }
   c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
   memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
-  c->base.type = GRPC_CREDENTIALS_TYPE_JWT;
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT;
   gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &jwt_vtable;
   c->key = key;
@@ -507,7 +506,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
   return &c->base;
 }
 
-grpc_credentials *grpc_service_account_jwt_access_credentials_create(
+grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
     const char *json_key, gpr_timespec token_lifetime, void *reserved) {
   GRPC_API_TRACE(
       "grpc_service_account_jwt_access_credentials_create("
@@ -524,7 +523,7 @@ grpc_credentials *grpc_service_account_jwt_access_credentials_create(
 
 /* -- Oauth2TokenFetcher credentials -- */
 
-static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
+static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
   grpc_credentials_md_store_unref(c->access_token_md);
@@ -532,16 +531,6 @@ static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
   grpc_httpcli_context_destroy(&c->httpcli_context);
 }
 
-static int oauth2_token_fetcher_has_request_metadata(
-    const grpc_credentials *creds) {
-  return 1;
-}
-
-static int oauth2_token_fetcher_has_request_metadata_only(
-    const grpc_credentials *creds) {
-  return 1;
-}
-
 grpc_credentials_status
 grpc_oauth2_token_fetcher_credentials_parse_server_response(
     const grpc_httpcli_response *response, grpc_credentials_md_store **token_md,
@@ -659,8 +648,9 @@ static void on_oauth2_token_fetcher_http_response(
 }
 
 static void oauth2_token_fetcher_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, const char *service_url,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
   gpr_timespec refresh_threshold = gpr_time_from_seconds(
@@ -693,7 +683,7 @@ static void oauth2_token_fetcher_get_request_metadata(
 static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
                                       grpc_fetch_oauth2_func fetch_func) {
   memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials));
-  c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
   gpr_ref_init(&c->base.refcount, 1);
   gpr_mu_init(&c->mu);
   c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
@@ -703,10 +693,8 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
 
 /* -- GoogleComputeEngine credentials. -- */
 
-static grpc_credentials_vtable compute_engine_vtable = {
-    oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata,
-    oauth2_token_fetcher_has_request_metadata_only,
-    oauth2_token_fetcher_get_request_metadata, NULL};
+static grpc_call_credentials_vtable compute_engine_vtable = {
+    oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata};
 
 static void compute_engine_fetch_oauth2(
     grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
@@ -723,7 +711,7 @@ static void compute_engine_fetch_oauth2(
                    response_cb, metadata_req);
 }
 
-grpc_credentials *grpc_google_compute_engine_credentials_create(
+grpc_call_credentials *grpc_google_compute_engine_credentials_create(
     void *reserved) {
   grpc_oauth2_token_fetcher_credentials *c =
       gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
@@ -737,17 +725,15 @@ grpc_credentials *grpc_google_compute_engine_credentials_create(
 
 /* -- GoogleRefreshToken credentials. -- */
 
-static void refresh_token_destruct(grpc_credentials *creds) {
+static void refresh_token_destruct(grpc_call_credentials *creds) {
   grpc_google_refresh_token_credentials *c =
       (grpc_google_refresh_token_credentials *)creds;
   grpc_auth_refresh_token_destruct(&c->refresh_token);
   oauth2_token_fetcher_destruct(&c->base.base);
 }
 
-static grpc_credentials_vtable refresh_token_vtable = {
-    refresh_token_destruct, oauth2_token_fetcher_has_request_metadata,
-    oauth2_token_fetcher_has_request_metadata_only,
-    oauth2_token_fetcher_get_request_metadata, NULL};
+static grpc_call_credentials_vtable refresh_token_vtable = {
+    refresh_token_destruct, oauth2_token_fetcher_get_request_metadata};
 
 static void refresh_token_fetch_oauth2(
     grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
@@ -773,7 +759,8 @@ static void refresh_token_fetch_oauth2(
   gpr_free(body);
 }
 
-grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
+grpc_call_credentials *
+grpc_refresh_token_credentials_create_from_auth_refresh_token(
     grpc_auth_refresh_token refresh_token) {
   grpc_google_refresh_token_credentials *c;
   if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
@@ -788,7 +775,7 @@ grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
   return &c->base.base;
 }
 
-grpc_credentials *grpc_google_refresh_token_credentials_create(
+grpc_call_credentials *grpc_google_refresh_token_credentials_create(
     const char *json_refresh_token, void *reserved) {
   GRPC_API_TRACE(
       "grpc_refresh_token_credentials_create(json_refresh_token=%s, "
@@ -801,20 +788,11 @@ grpc_credentials *grpc_google_refresh_token_credentials_create(
 
 /* -- Metadata-only credentials. -- */
 
-static void md_only_test_destruct(grpc_credentials *creds) {
+static void md_only_test_destruct(grpc_call_credentials *creds) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
   grpc_credentials_md_store_unref(c->md_store);
 }
 
-static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
-  return 1;
-}
-
-static int md_only_test_has_request_metadata_only(
-    const grpc_credentials *creds) {
-  return 1;
-}
-
 static void on_simulated_token_fetch_done(void *user_data) {
   grpc_credentials_metadata_request *r =
       (grpc_credentials_metadata_request *)user_data;
@@ -826,9 +804,12 @@ static void on_simulated_token_fetch_done(void *user_data) {
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void md_only_test_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
+static void md_only_test_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                              grpc_call_credentials *creds,
+                                              grpc_pollset *pollset,
+                                              const char *service_url,
+                                              grpc_credentials_metadata_cb cb,
+                                              void *user_data) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
 
   if (c->is_async) {
@@ -841,18 +822,15 @@ static void md_only_test_get_request_metadata(
   }
 }
 
-static grpc_credentials_vtable md_only_test_vtable = {
-    md_only_test_destruct, md_only_test_has_request_metadata,
-    md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
-    NULL};
+static grpc_call_credentials_vtable md_only_test_vtable = {
+    md_only_test_destruct, md_only_test_get_request_metadata};
 
-grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
-                                                       const char *md_value,
-                                                       int is_async) {
+grpc_call_credentials *grpc_md_only_test_credentials_create(
+    const char *md_key, const char *md_value, int is_async) {
   grpc_md_only_test_credentials *c =
       gpr_malloc(sizeof(grpc_md_only_test_credentials));
   memset(c, 0, sizeof(grpc_md_only_test_credentials));
-  c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
   c->base.vtable = &md_only_test_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   c->md_store = grpc_credentials_md_store_create(1);
@@ -863,34 +841,26 @@ grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
 
 /* -- Oauth2 Access Token credentials. -- */
 
-static void access_token_destruct(grpc_credentials *creds) {
+static void access_token_destruct(grpc_call_credentials *creds) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
   grpc_credentials_md_store_unref(c->access_token_md);
 }
 
-static int access_token_has_request_metadata(const grpc_credentials *creds) {
-  return 1;
-}
-
-static int access_token_has_request_metadata_only(
-    const grpc_credentials *creds) {
-  return 1;
-}
-
-static void access_token_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
+static void access_token_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                              grpc_call_credentials *creds,
+                                              grpc_pollset *pollset,
+                                              const char *service_url,
+                                              grpc_credentials_metadata_cb cb,
+                                              void *user_data) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
   cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
 }
 
-static grpc_credentials_vtable access_token_vtable = {
-    access_token_destruct, access_token_has_request_metadata,
-    access_token_has_request_metadata_only, access_token_get_request_metadata,
-    NULL};
+static grpc_call_credentials_vtable access_token_vtable = {
+    access_token_destruct, access_token_get_request_metadata};
 
-grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
-                                                       void *reserved) {
+grpc_call_credentials *grpc_access_token_credentials_create(
+    const char *access_token, void *reserved) {
   grpc_access_token_credentials *c =
       gpr_malloc(sizeof(grpc_access_token_credentials));
   char *token_md_value;
@@ -900,7 +870,7 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
       2, (access_token, reserved));
   GPR_ASSERT(reserved == NULL);
   memset(c, 0, sizeof(grpc_access_token_credentials));
-  c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
   c->base.vtable = &access_token_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   c->access_token_md = grpc_credentials_md_store_create(1);
@@ -913,31 +883,11 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
 
 /* -- Fake transport security credentials. -- */
 
-static void fake_transport_security_credentials_destruct(
-    grpc_credentials *creds) {
-  /* Nothing to do here. */
-}
-
-static void fake_transport_security_server_credentials_destruct(
-    grpc_server_credentials *creds) {
-  /* Nothing to do here. */
-}
-
-static int fake_transport_security_has_request_metadata(
-    const grpc_credentials *creds) {
-  return 0;
-}
-
-static int fake_transport_security_has_request_metadata_only(
-    const grpc_credentials *creds) {
-  return 0;
-}
-
 static grpc_security_status fake_transport_security_create_security_connector(
-    grpc_credentials *c, const char *target, const grpc_channel_args *args,
-    grpc_credentials *request_metadata_creds,
+    grpc_channel_credentials *c, grpc_call_credentials *call_creds,
+    const char *target, const grpc_channel_args *args,
     grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
-  *sc = grpc_fake_channel_security_connector_create(request_metadata_creds, 1);
+  *sc = grpc_fake_channel_security_connector_create(call_creds, 1);
   return GRPC_SECURITY_OK;
 }
 
@@ -948,21 +898,19 @@ fake_transport_security_server_create_security_connector(
   return GRPC_SECURITY_OK;
 }
 
-static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
-    fake_transport_security_credentials_destruct,
-    fake_transport_security_has_request_metadata,
-    fake_transport_security_has_request_metadata_only, NULL,
-    fake_transport_security_create_security_connector};
+static grpc_channel_credentials_vtable
+    fake_transport_security_credentials_vtable = {
+        NULL, fake_transport_security_create_security_connector};
 
 static grpc_server_credentials_vtable
     fake_transport_security_server_credentials_vtable = {
-        fake_transport_security_server_credentials_destruct,
-        fake_transport_security_server_create_security_connector};
+        NULL, fake_transport_security_server_create_security_connector};
 
-grpc_credentials *grpc_fake_transport_security_credentials_create(void) {
-  grpc_credentials *c = gpr_malloc(sizeof(grpc_credentials));
-  memset(c, 0, sizeof(grpc_credentials));
-  c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
+grpc_channel_credentials *grpc_fake_transport_security_credentials_create(
+    void) {
+  grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials));
+  memset(c, 0, sizeof(grpc_channel_credentials));
+  c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
   c->vtable = &fake_transport_security_credentials_vtable;
   gpr_ref_init(&c->refcount, 1);
   return c;
@@ -972,69 +920,46 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
     void) {
   grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
   memset(c, 0, sizeof(grpc_server_credentials));
-  c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
+  c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
   gpr_ref_init(&c->refcount, 1);
   c->vtable = &fake_transport_security_server_credentials_vtable;
   return c;
 }
 
-/* -- Composite credentials. -- */
+/* -- Composite call credentials. -- */
 
 typedef struct {
-  grpc_composite_credentials *composite_creds;
+  grpc_composite_call_credentials *composite_creds;
   size_t creds_index;
   grpc_credentials_md_store *md_elems;
   char *service_url;
   void *user_data;
   grpc_pollset *pollset;
   grpc_credentials_metadata_cb cb;
-} grpc_composite_credentials_metadata_context;
+} grpc_composite_call_credentials_metadata_context;
 
-static void composite_destruct(grpc_credentials *creds) {
-  grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
+static void composite_call_destruct(grpc_call_credentials *creds) {
+  grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
   size_t i;
   for (i = 0; i < c->inner.num_creds; i++) {
-    grpc_credentials_unref(c->inner.creds_array[i]);
+    grpc_call_credentials_unref(c->inner.creds_array[i]);
   }
   gpr_free(c->inner.creds_array);
 }
 
-static int composite_has_request_metadata(const grpc_credentials *creds) {
-  const grpc_composite_credentials *c =
-      (const grpc_composite_credentials *)creds;
-  size_t i;
-  for (i = 0; i < c->inner.num_creds; i++) {
-    if (grpc_credentials_has_request_metadata(c->inner.creds_array[i])) {
-      return 1;
-    }
-  }
-  return 0;
-}
-
-static int composite_has_request_metadata_only(const grpc_credentials *creds) {
-  const grpc_composite_credentials *c =
-      (const grpc_composite_credentials *)creds;
-  size_t i;
-  for (i = 0; i < c->inner.num_creds; i++) {
-    if (!grpc_credentials_has_request_metadata_only(c->inner.creds_array[i])) {
-      return 0;
-    }
-  }
-  return 1;
-}
-
-static void composite_md_context_destroy(
-    grpc_composite_credentials_metadata_context *ctx) {
+static void composite_call_md_context_destroy(
+    grpc_composite_call_credentials_metadata_context *ctx) {
   grpc_credentials_md_store_unref(ctx->md_elems);
   if (ctx->service_url != NULL) gpr_free(ctx->service_url);
   gpr_free(ctx);
 }
 
-static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
-                                  grpc_credentials_md *md_elems, size_t num_md,
-                                  grpc_credentials_status status) {
-  grpc_composite_credentials_metadata_context *ctx =
-      (grpc_composite_credentials_metadata_context *)user_data;
+static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
+                                       grpc_credentials_md *md_elems,
+                                       size_t num_md,
+                                       grpc_credentials_status status) {
+  grpc_composite_call_credentials_metadata_context *ctx =
+      (grpc_composite_call_credentials_metadata_context *)user_data;
   if (status != GRPC_CREDENTIALS_OK) {
     ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status);
     return;
@@ -1050,158 +975,114 @@ static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
   }
 
   /* See if we need to get some more metadata. */
-  while (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
-    grpc_credentials *inner_creds =
+  if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
+    grpc_call_credentials *inner_creds =
         ctx->composite_creds->inner.creds_array[ctx->creds_index++];
-    if (grpc_credentials_has_request_metadata(inner_creds)) {
-      grpc_credentials_get_request_metadata(exec_ctx, inner_creds, ctx->pollset,
-                                            ctx->service_url,
-                                            composite_metadata_cb, ctx);
-      return;
-    }
+    grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds,
+                                               ctx->pollset, ctx->service_url,
+                                               composite_call_metadata_cb, ctx);
+    return;
   }
 
   /* We're done!. */
   ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
           ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK);
-  composite_md_context_destroy(ctx);
+  composite_call_md_context_destroy(ctx);
 }
 
-static void composite_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
-  grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
-  grpc_composite_credentials_metadata_context *ctx;
-  if (!grpc_credentials_has_request_metadata(creds)) {
-    cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
-    return;
-  }
-  ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context));
-  memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context));
+static void composite_call_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                                grpc_call_credentials *creds,
+                                                grpc_pollset *pollset,
+                                                const char *service_url,
+                                                grpc_credentials_metadata_cb cb,
+                                                void *user_data) {
+  grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
+  grpc_composite_call_credentials_metadata_context *ctx;
+
+  ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
+  memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
   ctx->service_url = gpr_strdup(service_url);
   ctx->user_data = user_data;
   ctx->cb = cb;
   ctx->composite_creds = c;
   ctx->pollset = pollset;
   ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
-  while (ctx->creds_index < c->inner.num_creds) {
-    grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++];
-    if (grpc_credentials_has_request_metadata(inner_creds)) {
-      grpc_credentials_get_request_metadata(exec_ctx, inner_creds, pollset,
-                                            service_url, composite_metadata_cb,
-                                            ctx);
-      return;
-    }
-  }
-  GPR_ASSERT(0); /* Should have exited before. */
-}
-
-static grpc_security_status composite_create_security_connector(
-    grpc_credentials *creds, const char *target, const grpc_channel_args *args,
-    grpc_credentials *request_metadata_creds,
-    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
-  grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
-  if (c->connector_creds == NULL) {
-    gpr_log(GPR_ERROR,
-            "Cannot create security connector, missing connector credentials.");
-    return GRPC_SECURITY_ERROR;
-  }
-  return grpc_credentials_create_security_connector(c->connector_creds, target,
-                                                    args, creds, sc, new_args);
+  grpc_call_credentials_get_request_metadata(
+      exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, service_url,
+      composite_call_metadata_cb, ctx);
 }
 
-static grpc_credentials_vtable composite_credentials_vtable = {
-    composite_destruct, composite_has_request_metadata,
-    composite_has_request_metadata_only, composite_get_request_metadata,
-    composite_create_security_connector};
+static grpc_call_credentials_vtable composite_call_credentials_vtable = {
+    composite_call_destruct, composite_call_get_request_metadata};
 
-static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) {
-  grpc_credentials_array result;
-  grpc_credentials *creds = *creds_addr;
+static grpc_call_credentials_array get_creds_array(
+    grpc_call_credentials **creds_addr) {
+  grpc_call_credentials_array result;
+  grpc_call_credentials *creds = *creds_addr;
   result.creds_array = creds_addr;
   result.num_creds = 1;
-  if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
-    result = *grpc_composite_credentials_get_credentials(creds);
+  if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
+    result = *grpc_composite_call_credentials_get_credentials(creds);
   }
   return result;
 }
 
-grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
-                                                    grpc_credentials *creds2,
-                                                    void *reserved) {
+grpc_call_credentials *grpc_composite_call_credentials_create(
+    grpc_call_credentials *creds1, grpc_call_credentials *creds2,
+    void *reserved) {
   size_t i;
   size_t creds_array_byte_size;
-  grpc_credentials_array creds1_array;
-  grpc_credentials_array creds2_array;
-  grpc_composite_credentials *c;
+  grpc_call_credentials_array creds1_array;
+  grpc_call_credentials_array creds2_array;
+  grpc_composite_call_credentials *c;
   GRPC_API_TRACE(
-      "grpc_composite_credentials_create(creds1=%p, creds2=%p, "
+      "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
       "reserved=%p)",
       3, (creds1, creds2, reserved));
   GPR_ASSERT(reserved == NULL);
   GPR_ASSERT(creds1 != NULL);
   GPR_ASSERT(creds2 != NULL);
-  c = gpr_malloc(sizeof(grpc_composite_credentials));
-  memset(c, 0, sizeof(grpc_composite_credentials));
-  c->base.type = GRPC_CREDENTIALS_TYPE_COMPOSITE;
-  c->base.vtable = &composite_credentials_vtable;
+  c = gpr_malloc(sizeof(grpc_composite_call_credentials));
+  memset(c, 0, sizeof(grpc_composite_call_credentials));
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
+  c->base.vtable = &composite_call_credentials_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   creds1_array = get_creds_array(&creds1);
   creds2_array = get_creds_array(&creds2);
   c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
-  creds_array_byte_size = c->inner.num_creds * sizeof(grpc_credentials *);
+  creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
   c->inner.creds_array = gpr_malloc(creds_array_byte_size);
   memset(c->inner.creds_array, 0, creds_array_byte_size);
   for (i = 0; i < creds1_array.num_creds; i++) {
-    grpc_credentials *cur_creds = creds1_array.creds_array[i];
-    if (!grpc_credentials_has_request_metadata_only(cur_creds)) {
-      if (c->connector_creds == NULL) {
-        c->connector_creds = cur_creds;
-      } else {
-        gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials.");
-        goto fail;
-      }
-    }
-    c->inner.creds_array[i] = grpc_credentials_ref(cur_creds);
+    grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
+    c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
   }
   for (i = 0; i < creds2_array.num_creds; i++) {
-    grpc_credentials *cur_creds = creds2_array.creds_array[i];
-    if (!grpc_credentials_has_request_metadata_only(cur_creds)) {
-      if (c->connector_creds == NULL) {
-        c->connector_creds = cur_creds;
-      } else {
-        gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials.");
-        goto fail;
-      }
-    }
+    grpc_call_credentials *cur_creds = creds2_array.creds_array[i];
     c->inner.creds_array[i + creds1_array.num_creds] =
-        grpc_credentials_ref(cur_creds);
+        grpc_call_credentials_ref(cur_creds);
   }
   return &c->base;
-
-fail:
-  grpc_credentials_unref(&c->base);
-  return NULL;
 }
 
-const grpc_credentials_array *grpc_composite_credentials_get_credentials(
-    grpc_credentials *creds) {
-  const grpc_composite_credentials *c =
-      (const grpc_composite_credentials *)creds;
-  GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0);
+const grpc_call_credentials_array *
+grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) {
+  const grpc_composite_call_credentials *c =
+      (const grpc_composite_call_credentials *)creds;
+  GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
   return &c->inner;
 }
 
-grpc_credentials *grpc_credentials_contains_type(
-    grpc_credentials *creds, const char *type,
-    grpc_credentials **composite_creds) {
+grpc_call_credentials *grpc_credentials_contains_type(
+    grpc_call_credentials *creds, const char *type,
+    grpc_call_credentials **composite_creds) {
   size_t i;
   if (strcmp(creds->type, type) == 0) {
     if (composite_creds != NULL) *composite_creds = NULL;
     return creds;
-  } else if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
-    const grpc_credentials_array *inner_creds_array =
-        grpc_composite_credentials_get_credentials(creds);
+  } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
+    const grpc_call_credentials_array *inner_creds_array =
+        grpc_composite_call_credentials_get_credentials(creds);
     for (i = 0; i < inner_creds_array->num_creds; i++) {
       if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
         if (composite_creds != NULL) *composite_creds = creds;
@@ -1214,30 +1095,26 @@ grpc_credentials *grpc_credentials_contains_type(
 
 /* -- IAM credentials. -- */
 
-static void iam_destruct(grpc_credentials *creds) {
+static void iam_destruct(grpc_call_credentials *creds) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
   grpc_credentials_md_store_unref(c->iam_md);
 }
 
-static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; }
-
-static int iam_has_request_metadata_only(const grpc_credentials *creds) {
-  return 1;
-}
-
-static void iam_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
+static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                     grpc_call_credentials *creds,
+                                     grpc_pollset *pollset,
+                                     const char *service_url,
+                                     grpc_credentials_metadata_cb cb,
+                                     void *user_data) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
   cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
      GRPC_CREDENTIALS_OK);
 }
 
-static grpc_credentials_vtable iam_vtable = {
-    iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only,
-    iam_get_request_metadata, NULL};
+static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
+                                                  iam_get_request_metadata};
 
-grpc_credentials *grpc_google_iam_credentials_create(
+grpc_call_credentials *grpc_google_iam_credentials_create(
     const char *token, const char *authority_selector, void *reserved) {
   grpc_google_iam_credentials *c;
   GRPC_API_TRACE(
@@ -1249,7 +1126,7 @@ grpc_credentials *grpc_google_iam_credentials_create(
   GPR_ASSERT(authority_selector != NULL);
   c = gpr_malloc(sizeof(grpc_google_iam_credentials));
   memset(c, 0, sizeof(grpc_google_iam_credentials));
-  c->base.type = GRPC_CREDENTIALS_TYPE_IAM;
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
   c->base.vtable = &iam_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   c->iam_md = grpc_credentials_md_store_create(2);
@@ -1267,21 +1144,13 @@ typedef struct {
   grpc_credentials_metadata_cb cb;
 } grpc_metadata_plugin_request;
 
-static void plugin_destruct(grpc_credentials *creds) {
+static void plugin_destruct(grpc_call_credentials *creds) {
   grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
   if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
     c->plugin.destroy(c->plugin.state);
   }
 }
 
-static int plugin_has_request_metadata(const grpc_credentials *creds) {
-  return 1;
-}
-
-static int plugin_has_request_metadata_only(const grpc_credentials *creds) {
-  return 1;
-}
-
 static void plugin_md_request_metadata_ready(void *request,
                                              const grpc_metadata *md,
                                              size_t num_md,
@@ -1320,9 +1189,12 @@ static void plugin_md_request_metadata_ready(void *request,
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void plugin_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
+static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                        grpc_call_credentials *creds,
+                                        grpc_pollset *pollset,
+                                        const char *service_url,
+                                        grpc_credentials_metadata_cb cb,
+                                        void *user_data) {
   grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
   if (c->plugin.get_metadata != NULL) {
     grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
@@ -1336,18 +1208,75 @@ static void plugin_get_request_metadata(
   }
 }
 
-static grpc_credentials_vtable plugin_vtable = {
-    plugin_destruct, plugin_has_request_metadata,
-    plugin_has_request_metadata_only, plugin_get_request_metadata, NULL};
+static grpc_call_credentials_vtable plugin_vtable = {
+    plugin_destruct, plugin_get_request_metadata};
 
-grpc_credentials *grpc_metadata_credentials_create_from_plugin(
+grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
     grpc_metadata_credentials_plugin plugin, void *reserved) {
   grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
+  GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
+                 (reserved));
   GPR_ASSERT(reserved == NULL);
   memset(c, 0, sizeof(*c));
-  c->base.type = GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN;
+  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN;
   c->base.vtable = &plugin_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   c->plugin = plugin;
   return &c->base;
 }
+
+/* -- Composite channel credentials. -- */
+
+static void composite_channel_destruct(grpc_channel_credentials *creds) {
+  grpc_composite_channel_credentials *c =
+      (grpc_composite_channel_credentials *)creds;
+  grpc_channel_credentials_unref(c->inner_creds);
+  grpc_call_credentials_unref(c->call_creds);
+}
+
+static grpc_security_status composite_channel_create_security_connector(
+    grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
+    const char *target, const grpc_channel_args *args,
+    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+  grpc_composite_channel_credentials *c =
+      (grpc_composite_channel_credentials *)creds;
+  grpc_security_status status = GRPC_SECURITY_ERROR;
+
+  GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL &&
+             c->inner_creds->vtable != NULL &&
+             c->inner_creds->vtable->create_security_connector != NULL);
+  /* If we are passed a call_creds, create a call composite to pass it
+     downstream. */
+  if (call_creds != NULL) {
+    grpc_call_credentials *composite_call_creds =
+        grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL);
+    status = c->inner_creds->vtable->create_security_connector(
+        c->inner_creds, composite_call_creds, target, args, sc, new_args);
+    grpc_call_credentials_unref(composite_call_creds);
+  } else {
+    status = c->inner_creds->vtable->create_security_connector(
+        c->inner_creds, c->call_creds, target, args, sc, new_args);
+  }
+  return status;
+}
+
+static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
+    composite_channel_destruct, composite_channel_create_security_connector};
+
+grpc_channel_credentials *grpc_composite_channel_credentials_create(
+    grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
+    void *reserved) {
+  grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
+  memset(c, 0, sizeof(*c));
+  GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
+  GRPC_API_TRACE(
+      "grpc_composite_channel_credentials_create(channel_creds=%p, "
+      "call_creds=%p, reserved=%p)",
+      3, (channel_creds, call_creds, reserved));
+  c->base.type = channel_creds->type;
+  c->base.vtable = &composite_channel_credentials_vtable;
+  gpr_ref_init(&c->base.refcount, 1);
+  c->inner_creds = grpc_channel_credentials_ref(channel_creds);
+  c->call_creds = grpc_call_credentials_ref(call_creds);
+  return &c->base;
+}
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index c74beef0e4f2f9c30b56e6b0fcbb3d89f85549c8..132060910ec71e00c26350ab7287c36d4c864fdf 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -54,15 +54,17 @@ typedef enum {
 
 #define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake"
 
-#define GRPC_CREDENTIALS_TYPE_SSL "Ssl"
-#define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
-#define GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
-#define GRPC_CREDENTIALS_TYPE_JWT "Jwt"
-#define GRPC_CREDENTIALS_TYPE_IAM "Iam"
-#define GRPC_CREDENTIALS_TYPE_COMPOSITE "Composite"
-#define GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY "FakeTransportSecurity"
-
-#define GRPC_AUTHORIZATION_METADATA_KEY "Authorization"
+#define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl"
+#define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \
+  "FakeTransportSecurity"
+
+#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
+#define GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
+#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
+#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
+#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
+
+#define GRPC_AUTHORIZATION_METADATA_KEY "authorization"
 #define GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY \
   "x-goog-iam-authorization-token"
 #define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector"
@@ -87,6 +89,41 @@ typedef enum {
 #define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \
   "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token"
 
+/* --- Google utils --- */
+
+/* It is the caller's responsibility to gpr_free the result if not NULL. */
+char *grpc_get_well_known_google_credentials_file_path(void);
+
+/* --- grpc_channel_credentials. --- */
+
+typedef struct {
+  void (*destruct)(grpc_channel_credentials *c);
+
+  grpc_security_status (*create_security_connector)(
+      grpc_channel_credentials *c, grpc_call_credentials *call_creds,
+      const char *target, const grpc_channel_args *args,
+      grpc_channel_security_connector **sc, grpc_channel_args **new_args);
+} grpc_channel_credentials_vtable;
+
+struct grpc_channel_credentials {
+  const grpc_channel_credentials_vtable *vtable;
+  const char *type;
+  gpr_refcount refcount;
+};
+
+grpc_channel_credentials *grpc_channel_credentials_ref(
+    grpc_channel_credentials *creds);
+void grpc_channel_credentials_unref(grpc_channel_credentials *creds);
+
+/* Creates a security connector for the channel. May also create new channel
+   args for the channel to be used in place of the passed in const args if
+   returned non NULL. In that case the caller is responsible for destroying
+   new_args after channel creation. */
+grpc_security_status grpc_channel_credentials_create_security_connector(
+    grpc_channel_credentials *creds, const char *target,
+    const grpc_channel_args *args, grpc_channel_security_connector **sc,
+    grpc_channel_args **new_args);
+
 /* --- grpc_credentials_md. --- */
 
 typedef struct {
@@ -113,16 +150,7 @@ grpc_credentials_md_store *grpc_credentials_md_store_ref(
     grpc_credentials_md_store *store);
 void grpc_credentials_md_store_unref(grpc_credentials_md_store *store);
 
-/* --- grpc_credentials. --- */
-
-/* Creates a fake transport security credentials object for testing. */
-grpc_credentials *grpc_fake_transport_security_credentials_create(void);
-/* Creates a fake server transport security credentials object for testing. */
-grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
-    void);
-
-/* It is the caller's responsibility to gpr_free the result if not NULL. */
-char *grpc_get_well_known_google_credentials_file_path(void);
+/* --- grpc_call_credentials. --- */
 
 typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx,
                                              void *user_data,
@@ -131,57 +159,45 @@ typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx,
                                              grpc_credentials_status status);
 
 typedef struct {
-  void (*destruct)(grpc_credentials *c);
-  int (*has_request_metadata)(const grpc_credentials *c);
-  int (*has_request_metadata_only)(const grpc_credentials *c);
-  void (*get_request_metadata)(grpc_exec_ctx *exec_ctx, grpc_credentials *c,
-                               grpc_pollset *pollset, const char *service_url,
+  void (*destruct)(grpc_call_credentials *c);
+  void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
+                               grpc_call_credentials *c, grpc_pollset *pollset,
+                               const char *service_url,
                                grpc_credentials_metadata_cb cb,
                                void *user_data);
-  grpc_security_status (*create_security_connector)(
-      grpc_credentials *c, const char *target, const grpc_channel_args *args,
-      grpc_credentials *request_metadata_creds,
-      grpc_channel_security_connector **sc, grpc_channel_args **new_args);
-} grpc_credentials_vtable;
+} grpc_call_credentials_vtable;
 
-struct grpc_credentials {
-  const grpc_credentials_vtable *vtable;
+struct grpc_call_credentials {
+  const grpc_call_credentials_vtable *vtable;
   const char *type;
   gpr_refcount refcount;
 };
 
-grpc_credentials *grpc_credentials_ref(grpc_credentials *creds);
-void grpc_credentials_unref(grpc_credentials *creds);
-int grpc_credentials_has_request_metadata(grpc_credentials *creds);
-int grpc_credentials_has_request_metadata_only(grpc_credentials *creds);
-void grpc_credentials_get_request_metadata(
-    grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
-    const char *service_url, grpc_credentials_metadata_cb cb, void *user_data);
-
-/* Creates a security connector for the channel. May also create new channel
-   args for the channel to be used in place of the passed in const args if
-   returned non NULL. In that case the caller is responsible for destroying
-   new_args after channel creation. */
-grpc_security_status grpc_credentials_create_security_connector(
-    grpc_credentials *creds, const char *target, const grpc_channel_args *args,
-    grpc_credentials *request_metadata_creds,
-    grpc_channel_security_connector **sc, grpc_channel_args **new_args);
+grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
+void grpc_call_credentials_unref(grpc_call_credentials *creds);
+void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
+                                                grpc_call_credentials *creds,
+                                                grpc_pollset *pollset,
+                                                const char *service_url,
+                                                grpc_credentials_metadata_cb cb,
+                                                void *user_data);
 
 typedef struct {
-  grpc_credentials **creds_array;
+  grpc_call_credentials **creds_array;
   size_t num_creds;
-} grpc_credentials_array;
+} grpc_call_credentials_array;
 
-const grpc_credentials_array *grpc_composite_credentials_get_credentials(
-    grpc_credentials *composite_creds);
+const grpc_call_credentials_array *
+grpc_composite_call_credentials_get_credentials(
+    grpc_call_credentials *composite_creds);
 
 /* Returns creds if creds is of the specified type or the inner creds of the
    specified type (if found), if the creds is of type COMPOSITE.
    If composite_creds is not NULL, *composite_creds will point to creds if of
    type COMPOSITE in case of success. */
-grpc_credentials *grpc_credentials_contains_type(
-    grpc_credentials *creds, const char *type,
-    grpc_credentials **composite_creds);
+grpc_call_credentials *grpc_credentials_contains_type(
+    grpc_call_credentials *creds, const char *type,
+    grpc_call_credentials **composite_creds);
 
 /* Exposed for testing only. */
 grpc_credentials_status
@@ -192,19 +208,19 @@ void grpc_flush_cached_google_default_credentials(void);
 
 /* Metadata-only credentials with the specified key and value where
    asynchronicity can be simulated for testing. */
-grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
-                                                       const char *md_value,
-                                                       int is_async);
+grpc_call_credentials *grpc_md_only_test_credentials_create(
+    const char *md_key, const char *md_value, int is_async);
 
 /* Private constructor for jwt credentials from an already parsed json key.
    Takes ownership of the key. */
-grpc_credentials *
+grpc_call_credentials *
 grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
     grpc_auth_json_key key, gpr_timespec token_lifetime);
 
 /* Private constructor for refresh token credentials from an already parsed
    refresh token. Takes ownership of the refresh token. */
-grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
+grpc_call_credentials *
+grpc_refresh_token_credentials_create_from_auth_refresh_token(
     grpc_auth_refresh_token token);
 
 /* --- grpc_server_credentials. --- */
@@ -237,10 +253,18 @@ grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg);
 grpc_server_credentials *grpc_find_server_credentials_in_args(
     const grpc_channel_args *args);
 
+/* -- Fake transport security credentials. -- */
+
+/* Creates a fake transport security credentials object for testing. */
+grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void);
+/* Creates a fake server transport security credentials object for testing. */
+grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
+    void);
+
 /* -- Ssl credentials. -- */
 
 typedef struct {
-  grpc_credentials base;
+  grpc_channel_credentials base;
   grpc_ssl_config config;
 } grpc_ssl_credentials;
 
@@ -249,10 +273,18 @@ typedef struct {
   grpc_ssl_server_config config;
 } grpc_ssl_server_credentials;
 
+/* -- Channel composite credentials. -- */
+
+typedef struct {
+  grpc_channel_credentials base;
+  grpc_channel_credentials *inner_creds;
+  grpc_call_credentials *call_creds;
+} grpc_composite_channel_credentials;
+
 /* -- Jwt credentials -- */
 
 typedef struct {
-  grpc_credentials base;
+  grpc_call_credentials base;
 
   /* Have a simple cache for now with just 1 entry. We could have a map based on
      the service_url for a more sophisticated one. */
@@ -283,7 +315,7 @@ typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx,
                                        gpr_timespec deadline);
 
 typedef struct {
-  grpc_credentials base;
+  grpc_call_credentials base;
   gpr_mu mu;
   grpc_credentials_md_store *access_token_md;
   gpr_timespec token_expiration;
@@ -301,14 +333,14 @@ typedef struct {
 /* -- Oauth2 Access Token credentials. -- */
 
 typedef struct {
-  grpc_credentials base;
+  grpc_call_credentials base;
   grpc_credentials_md_store *access_token_md;
 } grpc_access_token_credentials;
 
 /* --  Metadata-only Test credentials. -- */
 
 typedef struct {
-  grpc_credentials base;
+  grpc_call_credentials base;
   grpc_credentials_md_store *md_store;
   int is_async;
 } grpc_md_only_test_credentials;
@@ -316,22 +348,21 @@ typedef struct {
 /* -- GoogleIAM credentials. -- */
 
 typedef struct {
-  grpc_credentials base;
+  grpc_call_credentials base;
   grpc_credentials_md_store *iam_md;
 } grpc_google_iam_credentials;
 
 /* -- Composite credentials. -- */
 
 typedef struct {
-  grpc_credentials base;
-  grpc_credentials_array inner;
-  grpc_credentials *connector_creds;
-} grpc_composite_credentials;
+  grpc_call_credentials base;
+  grpc_call_credentials_array inner;
+} grpc_composite_call_credentials;
 
 /* -- Plugin credentials. -- */
 
 typedef struct {
-  grpc_credentials base;
+  grpc_call_credentials base;
   grpc_metadata_credentials_plugin plugin;
   grpc_credentials_md_store *plugin_md;
 } grpc_plugin_credentials;
diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
index 45135305b2883395bd5eef481408878252992ee4..6a54fe4e47cd37feade3568605fb5ce080eb66e0 100644
--- a/src/core/security/google_default_credentials.c
+++ b/src/core/security/google_default_credentials.c
@@ -50,7 +50,7 @@
 
 /* -- Default credentials. -- */
 
-static grpc_credentials *default_credentials = NULL;
+static grpc_channel_credentials *default_credentials = NULL;
 static int compute_engine_detection_done = 0;
 static gpr_mu g_mu;
 static gpr_once g_once = GPR_ONCE_INIT;
@@ -138,11 +138,11 @@ static int is_stack_running_on_compute_engine(void) {
 }
 
 /* Takes ownership of creds_path if not NULL. */
-static grpc_credentials *create_default_creds_from_path(char *creds_path) {
+static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
   grpc_json *json = NULL;
   grpc_auth_json_key key;
   grpc_auth_refresh_token token;
-  grpc_credentials *result = NULL;
+  grpc_call_credentials *result = NULL;
   gpr_slice creds_data = gpr_empty_slice();
   int file_ok = 0;
   if (creds_path == NULL) goto end;
@@ -176,9 +176,9 @@ end:
   return result;
 }
 
-grpc_credentials *grpc_google_default_credentials_create(void) {
-  grpc_credentials *result = NULL;
-  int serving_cached_credentials = 0;
+grpc_channel_credentials *grpc_google_default_credentials_create(void) {
+  grpc_channel_credentials *result = NULL;
+  grpc_call_credentials *call_creds = NULL;
 
   GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
 
@@ -187,20 +187,19 @@ grpc_credentials *grpc_google_default_credentials_create(void) {
   gpr_mu_lock(&g_mu);
 
   if (default_credentials != NULL) {
-    result = grpc_credentials_ref(default_credentials);
-    serving_cached_credentials = 1;
+    result = grpc_channel_credentials_ref(default_credentials);
     goto end;
   }
 
   /* First, try the environment variable. */
-  result = create_default_creds_from_path(
+  call_creds = create_default_creds_from_path(
       gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
-  if (result != NULL) goto end;
+  if (call_creds != NULL) goto end;
 
   /* Then the well-known file. */
-  result = create_default_creds_from_path(
+  call_creds = create_default_creds_from_path(
       grpc_get_well_known_google_credentials_file_path());
-  if (result != NULL) goto end;
+  if (call_creds != NULL) goto end;
 
   /* At last try to see if we're on compute engine (do the detection only once
      since it requires a network test). */
@@ -208,21 +207,28 @@ grpc_credentials *grpc_google_default_credentials_create(void) {
     int need_compute_engine_creds = is_stack_running_on_compute_engine();
     compute_engine_detection_done = 1;
     if (need_compute_engine_creds) {
-      result = grpc_google_compute_engine_credentials_create(NULL);
+      call_creds = grpc_google_compute_engine_credentials_create(NULL);
     }
   }
 
 end:
-  if (!serving_cached_credentials && result != NULL) {
-    /* Blend with default ssl credentials and add a global reference so that it
-       can be cached and re-served. */
-    grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL);
-    default_credentials = grpc_credentials_ref(
-        grpc_composite_credentials_create(ssl_creds, result, NULL));
-    GPR_ASSERT(default_credentials != NULL);
-    grpc_credentials_unref(ssl_creds);
-    grpc_credentials_unref(result);
-    result = default_credentials;
+  if (result == NULL) {
+    if (call_creds != NULL) {
+      /* Blend with default ssl credentials and add a global reference so that
+         it
+         can be cached and re-served. */
+      grpc_channel_credentials *ssl_creds =
+          grpc_ssl_credentials_create(NULL, NULL, NULL);
+      default_credentials = grpc_channel_credentials_ref(
+          grpc_composite_channel_credentials_create(ssl_creds, call_creds,
+                                                    NULL));
+      GPR_ASSERT(default_credentials != NULL);
+      grpc_channel_credentials_unref(ssl_creds);
+      grpc_call_credentials_unref(call_creds);
+      result = default_credentials;
+    } else {
+      gpr_log(GPR_ERROR, "Could not create google default credentials.");
+    }
   }
   gpr_mu_unlock(&g_mu);
   return result;
@@ -232,7 +238,7 @@ void grpc_flush_cached_google_default_credentials(void) {
   gpr_once_init(&g_once, init_default_credentials);
   gpr_mu_lock(&g_mu);
   if (default_credentials != NULL) {
-    grpc_credentials_unref(default_credentials);
+    grpc_channel_credentials_unref(default_credentials);
     default_credentials = NULL;
   }
   gpr_mu_unlock(&g_mu);
diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c
index 7c4cf6f04d66ca7cbf4943be8ab67da7f9d04933..3c54a4deae17dac3b48aa478c95247ef4651793e 100644
--- a/src/core/security/security_connector.c
+++ b/src/core/security/security_connector.c
@@ -203,16 +203,6 @@ grpc_security_connector *grpc_find_security_connector_in_args(
   return NULL;
 }
 
-static int check_request_metadata_creds(grpc_credentials *creds) {
-  if (creds != NULL && !grpc_credentials_has_request_metadata(creds)) {
-    gpr_log(GPR_ERROR,
-            "Incompatible credentials for channel security connector: needs to "
-            "set request metadata.");
-    return 0;
-  }
-  return 1;
-}
-
 /* -- Fake implementation. -- */
 
 typedef struct {
@@ -222,7 +212,7 @@ typedef struct {
 
 static void fake_channel_destroy(grpc_security_connector *sc) {
   grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc;
-  grpc_credentials_unref(c->request_metadata_creds);
+  grpc_call_credentials_unref(c->request_metadata_creds);
   GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
   gpr_free(sc);
 }
@@ -306,7 +296,8 @@ static grpc_security_connector_vtable fake_server_vtable = {
     fake_server_destroy, fake_server_do_handshake, fake_check_peer};
 
 grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
-    grpc_credentials *request_metadata_creds, int call_host_check_is_async) {
+    grpc_call_credentials *request_metadata_creds,
+    int call_host_check_is_async) {
   grpc_fake_channel_security_connector *c =
       gpr_malloc(sizeof(grpc_fake_channel_security_connector));
   memset(c, 0, sizeof(grpc_fake_channel_security_connector));
@@ -314,8 +305,8 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
   c->base.base.is_client_side = 1;
   c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
   c->base.base.vtable = &fake_channel_vtable;
-  GPR_ASSERT(check_request_metadata_creds(request_metadata_creds));
-  c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
+  c->base.request_metadata_creds =
+      grpc_call_credentials_ref(request_metadata_creds);
   c->base.check_call_host = fake_channel_check_call_host;
   c->call_host_check_is_async = call_host_check_is_async;
   return &c->base;
@@ -349,7 +340,7 @@ typedef struct {
 static void ssl_channel_destroy(grpc_security_connector *sc) {
   grpc_ssl_channel_security_connector *c =
       (grpc_ssl_channel_security_connector *)sc;
-  grpc_credentials_unref(c->base.request_metadata_creds);
+  grpc_call_credentials_unref(c->base.request_metadata_creds);
   if (c->handshaker_factory != NULL) {
     tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
   }
@@ -580,9 +571,9 @@ size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) {
 }
 
 grpc_security_status grpc_ssl_channel_security_connector_create(
-    grpc_credentials *request_metadata_creds, const grpc_ssl_config *config,
-    const char *target_name, const char *overridden_target_name,
-    grpc_channel_security_connector **sc) {
+    grpc_call_credentials *request_metadata_creds,
+    const grpc_ssl_config *config, const char *target_name,
+    const char *overridden_target_name, grpc_channel_security_connector **sc) {
   size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
   const unsigned char **alpn_protocol_strings =
       gpr_malloc(sizeof(const char *) * num_alpn_protocols);
@@ -606,9 +597,6 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
     gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name.");
     goto error;
   }
-  if (!check_request_metadata_creds(request_metadata_creds)) {
-    goto error;
-  }
   if (config->pem_root_certs == NULL) {
     pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
     if (pem_root_certs == NULL || pem_root_certs_size == 0) {
@@ -627,7 +615,8 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
   c->base.base.vtable = &ssl_channel_vtable;
   c->base.base.is_client_side = 1;
   c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
-  c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
+  c->base.request_metadata_creds =
+      grpc_call_credentials_ref(request_metadata_creds);
   c->base.check_call_host = ssl_channel_check_call_host;
   gpr_split_host_port(target_name, &c->target_name, &port);
   gpr_free(port);
diff --git a/src/core/security/security_connector.h b/src/core/security/security_connector.h
index 9218a3caab0adebb46487c0bcce8107b1fa58877..c5f00c5563784ed042327350e36611880058f89a 100644
--- a/src/core/security/security_connector.h
+++ b/src/core/security/security_connector.h
@@ -145,7 +145,7 @@ typedef struct grpc_channel_security_connector grpc_channel_security_connector;
 
 struct grpc_channel_security_connector {
   grpc_security_connector base; /* requires is_client_side to be non 0. */
-  grpc_credentials *request_metadata_creds;
+  grpc_call_credentials *request_metadata_creds;
   grpc_security_status (*check_call_host)(grpc_exec_ctx *exec_ctx,
                                           grpc_channel_security_connector *sc,
                                           const char *host,
@@ -167,7 +167,8 @@ grpc_security_status grpc_channel_security_connector_check_call_host(
 /* For TESTING ONLY!
    Creates a fake connector that emulates real channel security.  */
 grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
-    grpc_credentials *request_metadata_creds, int call_host_check_is_async);
+    grpc_call_credentials *request_metadata_creds,
+    int call_host_check_is_async);
 
 /* For TESTING ONLY!
    Creates a fake connector that emulates real server security.  */
@@ -197,9 +198,9 @@ typedef struct {
   specific error code otherwise.
 */
 grpc_security_status grpc_ssl_channel_security_connector_create(
-    grpc_credentials *request_metadata_creds, const grpc_ssl_config *config,
-    const char *target_name, const char *overridden_target_name,
-    grpc_channel_security_connector **sc);
+    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);
 
 /* Gets the default ssl roots. */
 size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs);
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index ff3ad64d92d19f3ab7ffcd0f1fe6cbfb10c5de95..2068c97d78c22328708a1dd06b43b38a36829a6f 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -46,7 +46,7 @@
 /* --- grpc_call --- */
 
 grpc_call_error grpc_call_set_credentials(grpc_call *call,
-                                          grpc_credentials *creds) {
+                                          grpc_call_credentials *creds) {
   grpc_client_security_context *ctx = NULL;
   GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2,
                  (call, creds));
@@ -54,20 +54,16 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
     gpr_log(GPR_ERROR, "Method is client-side only.");
     return GRPC_CALL_ERROR_NOT_ON_SERVER;
   }
-  if (creds != NULL && !grpc_credentials_has_request_metadata_only(creds)) {
-    gpr_log(GPR_ERROR, "Incompatible credentials to set on a call.");
-    return GRPC_CALL_ERROR;
-  }
   ctx = (grpc_client_security_context *)grpc_call_context_get(
       call, GRPC_CONTEXT_SECURITY);
   if (ctx == NULL) {
     ctx = grpc_client_security_context_create();
-    ctx->creds = grpc_credentials_ref(creds);
+    ctx->creds = grpc_call_credentials_ref(creds);
     grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx,
                           grpc_client_security_context_destroy);
   } else {
-    grpc_credentials_unref(ctx->creds);
-    ctx->creds = grpc_credentials_ref(creds);
+    grpc_call_credentials_unref(ctx->creds);
+    ctx->creds = grpc_call_credentials_ref(creds);
   }
   return GRPC_CALL_OK;
 }
@@ -101,7 +97,7 @@ grpc_client_security_context *grpc_client_security_context_create(void) {
 
 void grpc_client_security_context_destroy(void *ctx) {
   grpc_client_security_context *c = (grpc_client_security_context *)ctx;
-  grpc_credentials_unref(c->creds);
+  grpc_call_credentials_unref(c->creds);
   GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context");
   gpr_free(ctx);
 }
diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h
index 2bbdc4be973e3f66237663b83ea59e6a10536fa0..794258edbcb1470474e9154416d2ddf17a35a2d0 100644
--- a/src/core/security/security_context.h
+++ b/src/core/security/security_context.h
@@ -85,7 +85,7 @@ void grpc_auth_property_reset(grpc_auth_property *property);
    Internal client-side security context. */
 
 typedef struct {
-  grpc_credentials *creds;
+  grpc_call_credentials *creds;
   grpc_auth_context *auth_context;
 } grpc_client_security_context;
 
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 851e0cfab31f3111cacdc2c6685538c3f9f15778..1ea269bf8f04063b5652841ab261d2b190b45061 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -249,9 +249,11 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
   }
 
   for (i = 0; i < resolved->naddrs; i++) {
-    port_temp = grpc_tcp_server_add_port(
+    grpc_tcp_listener *listener;
+    listener = grpc_tcp_server_add_port(
         tcp, (struct sockaddr *)&resolved->addrs[i].addr,
         resolved->addrs[i].len);
+    port_temp = grpc_tcp_listener_get_port(listener);
     if (port_temp >= 0) {
       if (port_num == -1) {
         port_num = port_temp;
diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c
index 17c0b6c0f652924bae22e6a19a5f331ce4c691de..856d3a24391e079500ce4ba7eb41db91ec600815 100644
--- a/src/core/support/slice_buffer.c
+++ b/src/core/support/slice_buffer.c
@@ -220,7 +220,7 @@ void gpr_slice_buffer_move_first(gpr_slice_buffer *src, size_t n,
     return;
   }
   src_idx = 0;
-  for (;;) {
+  while (src_idx < src->capacity) {
     gpr_slice slice = src->slices[src_idx];
     size_t slice_len = GPR_SLICE_LENGTH(slice);
     if (n > slice_len) {
diff --git a/src/core/support/time_win32.c b/src/core/support/time_win32.c
index bc0586d0691ff6d3e62445c9499a477eef8f5292..623a8d9233746fdb8a3629870d918fbce41267fd 100644
--- a/src/core/support/time_win32.c
+++ b/src/core/support/time_win32.c
@@ -66,14 +66,12 @@ gpr_timespec gpr_now(gpr_clock_type clock) {
       now_tv.tv_nsec = now_tb.millitm * 1000000;
       break;
     case GPR_CLOCK_MONOTONIC:
+    case GPR_CLOCK_PRECISE:
       QueryPerformanceCounter(&timestamp);
       now_dbl = (timestamp.QuadPart - g_start_time.QuadPart) * g_time_scale;
       now_tv.tv_sec = (time_t)now_dbl;
       now_tv.tv_nsec = (int)((now_dbl - (double)now_tv.tv_sec) * 1e9);
       break;
-    case GPR_CLOCK_PRECISE:
-      gpr_precise_clock_now(&now_tv);
-      break;
   }
   return now_tv;
 }
diff --git a/src/core/surface/byte_buffer_reader.c b/src/core/surface/byte_buffer_reader.c
index 9f830df68ce70dd57ad3b41c4ba30dc1f4ac956a..57417f41b0dd683d0c363782206dc02deb4224be 100644
--- a/src/core/surface/byte_buffer_reader.c
+++ b/src/core/surface/byte_buffer_reader.c
@@ -121,4 +121,3 @@ gpr_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader) {
   }
   return out_slice;
 }
-
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index aa435d44d38c1ecb43ab898e512ddabf2fcca137..86d5fca3880132c015e1b51069344b3d8ceb216e 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -922,7 +922,8 @@ static batch_control *allocate_batch_control(grpc_call *call) {
   size_t i;
   for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) {
     if ((call->used_batches & (1 << i)) == 0) {
-      call->used_batches |= (gpr_uint8)(1 << i);
+      call->used_batches =
+          (gpr_uint8)(call->used_batches | (gpr_uint8)(1 << i));
       return &call->active_batches[i];
     }
   }
diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c
index 1282ee99ed7ca18f315482ed763cb0d5527e6ce7..0dd0a3116944a0707ce0088d6d6921f50b327a0c 100644
--- a/src/core/surface/secure_channel_create.c
+++ b/src/core/surface/secure_channel_create.c
@@ -230,7 +230,7 @@ static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
    Asynchronously: - resolve target
                    - connect to it (trying alternatives as presented)
                    - perform handshakes */
-grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
+grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
                                          const char *target,
                                          const grpc_channel_args *args,
                                          void *reserved) {
@@ -261,9 +261,9 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
         "Security connector exists in channel args.");
   }
 
-  if (grpc_credentials_create_security_connector(
-          creds, target, args, NULL, &security_connector,
-          &new_args_from_connector) != GRPC_SECURITY_OK) {
+  if (grpc_channel_credentials_create_security_connector(
+          creds, target, args, &security_connector, &new_args_from_connector) !=
+      GRPC_SECURITY_OK) {
     grpc_exec_ctx_finish(&exec_ctx);
     return grpc_lame_client_channel_create(
         target, GRPC_STATUS_INVALID_ARGUMENT,
diff --git a/src/core/surface/server_chttp2.c b/src/core/surface/server_chttp2.c
index 580b91573c208c0ab8f36d8b1178fac3dda80b4b..1408f9c15926d220934fd91a961a1fb05ef71f5d 100644
--- a/src/core/surface/server_chttp2.c
+++ b/src/core/surface/server_chttp2.c
@@ -107,9 +107,11 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
   }
 
   for (i = 0; i < resolved->naddrs; i++) {
-    port_temp = grpc_tcp_server_add_port(
+    grpc_tcp_listener *listener;
+    listener = grpc_tcp_server_add_port(
         tcp, (struct sockaddr *)&resolved->addrs[i].addr,
         resolved->addrs[i].len);
+    port_temp = grpc_tcp_listener_get_port(listener);
     if (port_temp >= 0) {
       if (port_num == -1) {
         port_num = port_temp;
diff --git a/src/core/surface/version.c b/src/core/surface/version.c
index e559d51448a4f91440e21e249392c79d91b02e60..962a72112a15c94d8e089a9efa3ec3f9ec400a67 100644
--- a/src/core/surface/version.c
+++ b/src/core/surface/version.c
@@ -36,4 +36,4 @@
 
 #include <grpc/grpc.h>
 
-const char *grpc_version_string(void) { return "0.11.0.0"; }
+const char *grpc_version_string(void) { return "0.12.0.0"; }
diff --git a/src/core/transport/chttp2/hpack_encoder.c b/src/core/transport/chttp2/hpack_encoder.c
index 6c7c00b7c399660b4b90877fccce7db1def26dc2..758babc3d0c6270d8ae5ad9c60333c0259fd34e5 100644
--- a/src/core/transport/chttp2/hpack_encoder.c
+++ b/src/core/transport/chttp2/hpack_encoder.c
@@ -36,8 +36,10 @@
 #include <assert.h>
 #include <string.h>
 
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
+
 #include "src/core/transport/chttp2/bin_encoder.h"
 #include "src/core/transport/chttp2/hpack_table.h"
 #include "src/core/transport/chttp2/timeout_encoding.h"
@@ -154,6 +156,18 @@ static gpr_uint8 *add_tiny_header_data(framer_state *st, size_t len) {
   return gpr_slice_buffer_tiny_add(st->output, len);
 }
 
+static void evict_entry(grpc_chttp2_hpack_compressor *c) {
+  c->tail_remote_index++;
+  GPR_ASSERT(c->tail_remote_index > 0);
+  GPR_ASSERT(c->table_size >=
+             c->table_elem_size[c->tail_remote_index % c->cap_table_elems]);
+  GPR_ASSERT(c->table_elems > 0);
+  c->table_size = (gpr_uint16)(
+      c->table_size -
+      c->table_elem_size[c->tail_remote_index % c->cap_table_elems]);
+  c->table_elems--;
+}
+
 /* add an element to the decoder table */
 static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) {
   gpr_uint32 key_hash = elem->key->hash;
@@ -164,26 +178,21 @@ static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) {
 
   GPR_ASSERT(elem_size < 65536);
 
+  if (elem_size > c->max_table_size) {
+    while (c->table_size > 0) {
+      evict_entry(c);
+    }
+    return;
+  }
+
   /* Reserve space for this element in the remote table: if this overflows
      the current table, drop elements until it fits, matching the decompressor
      algorithm */
-  /* TODO(ctiller): constant */
-  while (c->table_size + elem_size > 4096) {
-    c->tail_remote_index++;
-    GPR_ASSERT(c->tail_remote_index > 0);
-    GPR_ASSERT(c->table_size >=
-               c->table_elem_size[c->tail_remote_index %
-                                  GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS]);
-    GPR_ASSERT(c->table_elems > 0);
-    c->table_size =
-        (gpr_uint16)(c->table_size -
-                     c->table_elem_size[c->tail_remote_index %
-                                        GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS]);
-    c->table_elems--;
+  while (c->table_size + elem_size > c->max_table_size) {
+    evict_entry(c);
   }
-  GPR_ASSERT(c->table_elems < GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS);
-  c->table_elem_size[new_index % GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS] =
-      (gpr_uint16)elem_size;
+  GPR_ASSERT(c->table_elems < c->max_table_size);
+  c->table_elem_size[new_index % c->cap_table_elems] = (gpr_uint16)elem_size;
   c->table_size = (gpr_uint16)(c->table_size + elem_size);
   c->table_elems++;
 
@@ -329,6 +338,14 @@ static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
   add_header_data(st, gpr_slice_ref(value_slice));
 }
 
+static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
+                                             framer_state *st) {
+  gpr_uint32 len = GRPC_CHTTP2_VARINT_LENGTH(c->max_table_size, 3);
+  GRPC_CHTTP2_WRITE_VARINT(c->max_table_size, 3, 0x20,
+                           add_tiny_header_data(st, len), len);
+  c->advertise_table_size_change = 0;
+}
+
 static gpr_uint32 dynidx(grpc_chttp2_hpack_compressor *c,
                          gpr_uint32 elem_index) {
   return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index +
@@ -447,11 +464,23 @@ gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id) {
   return slice;
 }
 
+static gpr_uint32 elems_for_bytes(gpr_uint32 bytes) {
+  return (bytes + 31) / 32;
+}
+
 void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c,
                                        grpc_mdctx *ctx) {
   memset(c, 0, sizeof(*c));
   c->mdctx = ctx;
   c->timeout_key_str = grpc_mdstr_from_string(ctx, "grpc-timeout");
+  c->max_table_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
+  c->cap_table_elems = elems_for_bytes(c->max_table_size);
+  c->max_table_elems = c->cap_table_elems;
+  c->max_usable_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
+  c->table_elem_size =
+      gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
+  memset(c->table_elem_size, 0,
+         sizeof(*c->table_elem_size) * c->cap_table_elems);
 }
 
 void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
@@ -461,6 +490,54 @@ void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
     if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]);
   }
   GRPC_MDSTR_UNREF(c->timeout_key_str);
+  gpr_free(c->table_elem_size);
+}
+
+void grpc_chttp2_hpack_compressor_set_max_usable_size(
+    grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size) {
+  c->max_usable_size = max_table_size;
+  grpc_chttp2_hpack_compressor_set_max_table_size(
+      c, GPR_MIN(c->max_table_size, max_table_size));
+}
+
+static void rebuild_elems(grpc_chttp2_hpack_compressor *c, gpr_uint32 new_cap) {
+  gpr_uint16 *table_elem_size = gpr_malloc(sizeof(*table_elem_size) * new_cap);
+  gpr_uint32 i;
+
+  memset(table_elem_size, 0, sizeof(*table_elem_size) * new_cap);
+  GPR_ASSERT(c->table_elems <= new_cap);
+
+  for (i = 0; i < c->table_elems; i++) {
+    gpr_uint32 ofs = c->tail_remote_index + i + 1;
+    table_elem_size[ofs % new_cap] = c->table_elem_size[ofs % c->cap_table_elems];
+  }
+
+  c->cap_table_elems = new_cap;
+  gpr_free(c->table_elem_size);
+  c->table_elem_size = table_elem_size;
+}
+
+void grpc_chttp2_hpack_compressor_set_max_table_size(
+    grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size) {
+  max_table_size = GPR_MIN(max_table_size, c->max_usable_size);
+  if (max_table_size == c->max_table_size) {
+    return;
+  }
+  while (c->table_size > 0 && c->table_size > max_table_size) {
+    evict_entry(c);
+  }
+  c->max_table_size = max_table_size;
+  c->max_table_elems = elems_for_bytes(max_table_size);
+  if (c->max_table_elems > c->cap_table_elems) {
+    rebuild_elems(c, GPR_MAX(c->max_table_elems, 2 * c->cap_table_elems));
+  } else if (c->max_table_elems < c->cap_table_elems / 3) {
+    gpr_uint32 new_cap = GPR_MAX(c->max_table_elems, 16);
+    if (new_cap != c->cap_table_elems) {
+      rebuild_elems(c, new_cap);
+    }
+  }
+  c->advertise_table_size_change = 1;
+  gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size);
 }
 
 void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c,
@@ -483,6 +560,9 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c,
      slot. THIS MAY NOT BE THE SAME ELEMENT (if a decoder table slot got
      updated). After this loop, we'll do a batch unref of elements. */
   begin_frame(&st);
+  if (c->advertise_table_size_change != 0) {
+    emit_advertise_table_size_change(c, &st);
+  }
   grpc_metadata_batch_assert_ok(metadata);
   for (l = metadata->list.head; l; l = l->next) {
     hpack_enc(c, l->md, &st);
diff --git a/src/core/transport/chttp2/hpack_encoder.h b/src/core/transport/chttp2/hpack_encoder.h
index 59b122dfdad8e39267d4ddf4f1b68acaaa91656b..ce83d101f2192dde7551597a57b3d76aca75974d 100644
--- a/src/core/transport/chttp2/hpack_encoder.h
+++ b/src/core/transport/chttp2/hpack_encoder.h
@@ -43,14 +43,26 @@
 
 #define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256
 #define GRPC_CHTTP2_HPACKC_NUM_VALUES 256
-#define GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS (4096 / 32)
+/* initial table size, per spec */
+#define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096
+/* maximum table size we'll actually use */
+#define GRPC_CHTTP2_HPACKC_MAX_TABLE_SIZE (1024 * 1024)
 
 typedef struct {
   gpr_uint32 filter_elems_sum;
+  gpr_uint32 max_table_size;
+  gpr_uint32 max_table_elems;
+  gpr_uint32 cap_table_elems;
+  /** if non-zero, advertise to the decoder that we'll start using a table
+      of this size */
+  gpr_uint8 advertise_table_size_change;
+  /** maximum number of bytes we'll use for the decode table (to guard against
+      peers ooming us by setting decode table size high) */
+  gpr_uint32 max_usable_size;
   /* one before the lowest usable table index */
   gpr_uint32 tail_remote_index;
-  gpr_uint16 table_size;
-  gpr_uint16 table_elems;
+  gpr_uint32 table_size;
+  gpr_uint32 table_elems;
 
   /* filter tables for elems: this tables provides an approximate
      popularity count for particular hashes, and are used to determine whether
@@ -71,12 +83,16 @@ typedef struct {
   gpr_uint32 indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
   gpr_uint32 indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
 
-  gpr_uint16 table_elem_size[GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS];
+  gpr_uint16 *table_elem_size;
 } grpc_chttp2_hpack_compressor;
 
 void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c,
                                        grpc_mdctx *mdctx);
 void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c);
+void grpc_chttp2_hpack_compressor_set_max_table_size(
+    grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size);
+void grpc_chttp2_hpack_compressor_set_max_usable_size(
+    grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size);
 
 void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, gpr_uint32 id,
                                grpc_metadata_batch *metadata, int is_eof,
diff --git a/src/core/transport/chttp2/hpack_parser.c b/src/core/transport/chttp2/hpack_parser.c
index 6eebfc3ce40584159dba604f8421cd9e48fa0b05..57a3a20b1d1a529bb17d86eb8bb9be5eb9d8bd70 100644
--- a/src/core/transport/chttp2/hpack_parser.c
+++ b/src/core/transport/chttp2/hpack_parser.c
@@ -74,6 +74,8 @@ static int parse_begin(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
                        const gpr_uint8 *end);
 static int parse_error(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
                        const gpr_uint8 *end);
+static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
+                            const gpr_uint8 *end);
 
 static int parse_string_prefix(grpc_chttp2_hpack_parser *p,
                                const gpr_uint8 *cur, const gpr_uint8 *end);
@@ -156,7 +158,7 @@ static const grpc_chttp2_hpack_parser_state first_byte_action[] = {
     parse_lithdr_incidx_x, parse_lithdr_incidx_v, parse_lithdr_notidx,
     parse_lithdr_notidx_x, parse_lithdr_notidx_v, parse_lithdr_nvridx,
     parse_lithdr_nvridx_x, parse_lithdr_nvridx_v, parse_max_tbl_size,
-    parse_max_tbl_size_x,  parse_error};
+    parse_max_tbl_size_x,  parse_illegal_op};
 
 /* indexes the first byte to a parse state function - generated by
    gen_hpack_tables.c */
@@ -169,7 +171,7 @@ static const gpr_uint8 first_byte_lut[256] = {
     LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
     LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
     LITHDR_NVRIDX,   LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX_X,
-    ILLEGAL,         MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
+    MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
     MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
     MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
     MAX_TBL_SIZE,    MAX_TBL_SIZE,  MAX_TBL_SIZE,  MAX_TBL_SIZE,
@@ -622,13 +624,15 @@ static const gpr_uint8 inverse_base64[256] = {
 };
 
 /* emission helpers */
-static void on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
-                   int add_to_table) {
+static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
+                  int add_to_table) {
   if (add_to_table) {
-    GRPC_MDELEM_REF(md);
-    grpc_chttp2_hptbl_add(&p->table, md);
+    if (!grpc_chttp2_hptbl_add(&p->table, md)) {
+      return 0;
+    }
   }
   p->on_header(p->on_header_user_data, md);
+  return 1;
 }
 
 static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
@@ -714,9 +718,12 @@ static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
 static int finish_indexed_field(grpc_chttp2_hpack_parser *p,
                                 const gpr_uint8 *cur, const gpr_uint8 *end) {
   grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
+  if (md == NULL) {
+    gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
+    return 0;
+  }
   GRPC_MDELEM_REF(md);
-  on_hdr(p, md, 0);
-  return parse_begin(p, cur, end);
+  return on_hdr(p, md, 0) && parse_begin(p, cur, end);
 }
 
 /* parse an indexed field with index < 127 */
@@ -742,21 +749,21 @@ static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
 static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p,
                                 const gpr_uint8 *cur, const gpr_uint8 *end) {
   grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
-                                              GRPC_MDSTR_REF(md->key),
-                                              take_string(p, &p->value)),
-         1);
-  return parse_begin(p, cur, end);
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
+                                                     GRPC_MDSTR_REF(md->key),
+                                                     take_string(p, &p->value)),
+                1) &&
+         parse_begin(p, cur, end);
 }
 
 /* finish a literal header with incremental indexing with no index */
 static int finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
                                   const gpr_uint8 *cur, const gpr_uint8 *end) {
-  on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
-                                              take_string(p, &p->key),
-                                              take_string(p, &p->value)),
-         1);
-  return parse_begin(p, cur, end);
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
+                                                     take_string(p, &p->key),
+                                                     take_string(p, &p->value)),
+                1) &&
+         parse_begin(p, cur, end);
 }
 
 /* parse a literal header with incremental indexing; index < 63 */
@@ -795,21 +802,21 @@ static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
 static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p,
                                 const gpr_uint8 *cur, const gpr_uint8 *end) {
   grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
-                                              GRPC_MDSTR_REF(md->key),
-                                              take_string(p, &p->value)),
-         0);
-  return parse_begin(p, cur, end);
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
+                                                     GRPC_MDSTR_REF(md->key),
+                                                     take_string(p, &p->value)),
+                0) &&
+         parse_begin(p, cur, end);
 }
 
 /* finish a literal header without incremental indexing with index = 0 */
 static int finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
                                   const gpr_uint8 *cur, const gpr_uint8 *end) {
-  on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
-                                              take_string(p, &p->key),
-                                              take_string(p, &p->value)),
-         0);
-  return parse_begin(p, cur, end);
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
+                                                     take_string(p, &p->key),
+                                                     take_string(p, &p->value)),
+                0) &&
+         parse_begin(p, cur, end);
 }
 
 /* parse a literal header without incremental indexing; index < 15 */
@@ -848,21 +855,21 @@ static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
 static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
                                 const gpr_uint8 *cur, const gpr_uint8 *end) {
   grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
-  on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
-                                              GRPC_MDSTR_REF(md->key),
-                                              take_string(p, &p->value)),
-         0);
-  return parse_begin(p, cur, end);
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
+                                                     GRPC_MDSTR_REF(md->key),
+                                                     take_string(p, &p->value)),
+                0) &&
+         parse_begin(p, cur, end);
 }
 
 /* finish a literal header that is never indexed with an extra value */
 static int finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
                                   const gpr_uint8 *cur, const gpr_uint8 *end) {
-  on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
-                                              take_string(p, &p->key),
-                                              take_string(p, &p->value)),
-         0);
-  return parse_begin(p, cur, end);
+  return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
+                                                     take_string(p, &p->key),
+                                                     take_string(p, &p->value)),
+                0) &&
+         parse_begin(p, cur, end);
 }
 
 /* parse a literal header that is never indexed; index < 15 */
@@ -901,14 +908,14 @@ static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
 static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p,
                                const gpr_uint8 *cur, const gpr_uint8 *end) {
   gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index);
-  abort(); /* not implemented */
-  return parse_begin(p, cur, end);
+  return grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index) &&
+         parse_begin(p, cur, end);
 }
 
 /* parse a max table size change, max size < 15 */
 static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
                               const gpr_uint8 *end) {
-  p->index = (*cur) & 0xf;
+  p->index = (*cur) & 0x1f;
   return finish_max_tbl_size(p, cur + 1, end);
 }
 
@@ -918,7 +925,7 @@ static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p,
   static const grpc_chttp2_hpack_parser_state and_then[] = {
       finish_max_tbl_size};
   p->next_state = and_then;
-  p->index = 0xf;
+  p->index = 0x1f;
   p->parsing.value = &p->index;
   return parse_value0(p, cur + 1, end);
 }
@@ -930,6 +937,13 @@ static int parse_error(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
   return 0;
 }
 
+static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
+                            const gpr_uint8 *end) {
+  GPR_ASSERT(cur != end);
+  gpr_log(GPR_DEBUG, "Illegal hpack op code %d", *cur);
+  return parse_error(p, cur, end);
+}
+
 /* parse the 1st byte of a varint into p->parsing.value
    no overflow is possible */
 static int parse_value0(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
diff --git a/src/core/transport/chttp2/hpack_table.c b/src/core/transport/chttp2/hpack_table.c
index c442c2c34139c50fd4ebfe6ae3b029a0c8fdca82..f2362b056c2596f2c6f8cdc8f2eea546968c512b 100644
--- a/src/core/transport/chttp2/hpack_table.c
+++ b/src/core/transport/chttp2/hpack_table.c
@@ -36,7 +36,9 @@
 #include <assert.h>
 #include <string.h>
 
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+
 #include "src/core/support/murmur_hash.h"
 
 static struct {
@@ -169,12 +171,22 @@ static struct {
     {"www-authenticate", ""},
 };
 
+static gpr_uint32 entries_for_bytes(gpr_uint32 bytes) {
+  return (bytes + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) /
+         GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
+}
+
 void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx) {
   size_t i;
 
   memset(tbl, 0, sizeof(*tbl));
   tbl->mdctx = mdctx;
-  tbl->max_bytes = GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE;
+  tbl->current_table_bytes = tbl->max_bytes =
+      GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE;
+  tbl->max_entries = tbl->cap_entries =
+      entries_for_bytes(tbl->current_table_bytes);
+  tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
+  memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
   for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
     tbl->static_ents[i - 1] = grpc_mdelem_from_strings(
         mdctx, static_table[i].key, static_table[i].value);
@@ -187,9 +199,9 @@ void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) {
     GRPC_MDELEM_UNREF(tbl->static_ents[i]);
   }
   for (i = 0; i < tbl->num_ents; i++) {
-    GRPC_MDELEM_UNREF(
-        tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT]);
+    GRPC_MDELEM_UNREF(tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]);
   }
+  gpr_free(tbl->ents);
 }
 
 grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
@@ -201,8 +213,8 @@ grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
   /* Otherwise, find the value in the list of valid entries */
   tbl_index -= (GRPC_CHTTP2_LAST_STATIC_ENTRY + 1);
   if (tbl_index < tbl->num_ents) {
-    gpr_uint32 offset = (tbl->num_ents - 1u - tbl_index + tbl->first_ent) %
-                        GRPC_CHTTP2_MAX_TABLE_COUNT;
+    gpr_uint32 offset =
+        (tbl->num_ents - 1u - tbl_index + tbl->first_ent) % tbl->cap_entries;
     return tbl->ents[offset];
   }
   /* Invalid entry: return error */
@@ -216,21 +228,81 @@ static void evict1(grpc_chttp2_hptbl *tbl) {
                       GPR_SLICE_LENGTH(first_ent->value->slice) +
                       GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
   GPR_ASSERT(elem_bytes <= tbl->mem_used);
-  tbl->mem_used = (gpr_uint16)(tbl->mem_used - elem_bytes);
-  tbl->first_ent =
-      (gpr_uint16)((tbl->first_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT);
+  tbl->mem_used -= (gpr_uint32)elem_bytes;
+  tbl->first_ent = ((tbl->first_ent + 1) % tbl->cap_entries);
   tbl->num_ents--;
   GRPC_MDELEM_UNREF(first_ent);
 }
 
-void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
+static void rebuild_ents(grpc_chttp2_hptbl *tbl, gpr_uint32 new_cap) {
+  grpc_mdelem **ents = gpr_malloc(sizeof(*ents) * new_cap);
+  gpr_uint32 i;
+
+  for (i = 0; i < tbl->num_ents; i++) {
+    ents[i] = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
+  }
+  gpr_free(tbl->ents);
+  tbl->ents = ents;
+  tbl->cap_entries = new_cap;
+  tbl->first_ent = 0;
+}
+
+void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
+                                     gpr_uint32 max_bytes) {
+  if (tbl->max_bytes == max_bytes) {
+    return;
+  }
+  gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes);
+  while (tbl->mem_used > max_bytes) {
+    evict1(tbl);
+  }
+  tbl->max_bytes = max_bytes;
+}
+
+int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
+                                             gpr_uint32 bytes) {
+  if (tbl->current_table_bytes == bytes) {
+    return 1;
+  }
+  if (bytes > tbl->max_bytes) {
+    gpr_log(GPR_ERROR,
+            "Attempt to make hpack table %d bytes when max is %d bytes", bytes,
+            tbl->max_bytes);
+    return 0;
+  }
+  gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
+  while (tbl->mem_used > bytes) {
+    evict1(tbl);
+  }
+  tbl->current_table_bytes = bytes;
+  tbl->max_entries = entries_for_bytes(bytes);
+  if (tbl->max_entries > tbl->cap_entries) {
+    rebuild_ents(tbl, GPR_MAX(tbl->max_entries, 2 * tbl->cap_entries));
+  } else if (tbl->max_entries < tbl->cap_entries / 3) {
+    gpr_uint32 new_cap = GPR_MAX(tbl->max_entries, 16u);
+    if (new_cap != tbl->cap_entries) {
+      rebuild_ents(tbl, new_cap);
+    }
+  }
+  return 1;
+}
+
+int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
   /* determine how many bytes of buffer this entry represents */
   size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) +
                       GPR_SLICE_LENGTH(md->value->slice) +
                       GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
 
+  if (tbl->current_table_bytes > tbl->max_bytes) {
+    gpr_log(GPR_ERROR,
+            "HPACK max table size reduced to %d but not reflected by hpack "
+            "stream (still at %d)",
+            tbl->max_bytes, tbl->current_table_bytes);
+    return 0;
+  }
+
   /* we can't add elements bigger than the max table size */
-  if (elem_bytes > tbl->max_bytes) {
+  if (elem_bytes > tbl->current_table_bytes) {
     /* HPACK draft 10 section 4.4 states:
      * If the size of the new entry is less than or equal to the maximum
      * size, that entry is added to the table.  It is not an error to
@@ -243,44 +315,43 @@ void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
     while (tbl->num_ents) {
       evict1(tbl);
     }
-    return;
+    return 1;
   }
 
   /* evict entries to ensure no overflow */
-  while (elem_bytes > (size_t)tbl->max_bytes - tbl->mem_used) {
+  while (elem_bytes > (size_t)tbl->current_table_bytes - tbl->mem_used) {
     evict1(tbl);
   }
 
   /* copy the finalized entry in */
-  tbl->ents[tbl->last_ent] = md;
+  tbl->ents[(tbl->first_ent + tbl->num_ents) % tbl->cap_entries] =
+      GRPC_MDELEM_REF(md);
 
   /* update accounting values */
-  tbl->last_ent =
-      (gpr_uint16)((tbl->last_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT);
   tbl->num_ents++;
-  tbl->mem_used = (gpr_uint16)(tbl->mem_used + elem_bytes);
+  tbl->mem_used += (gpr_uint32)elem_bytes;
+  return 1;
 }
 
 grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
     const grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
   grpc_chttp2_hptbl_find_result r = {0, 0};
-  gpr_uint16 i;
+  gpr_uint32 i;
 
   /* See if the string is in the static table */
   for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
     grpc_mdelem *ent = tbl->static_ents[i];
     if (md->key != ent->key) continue;
-    r.index = (gpr_uint16)(i + 1);
+    r.index = i + 1u;
     r.has_value = md->value == ent->value;
     if (r.has_value) return r;
   }
 
   /* Scan the dynamic table */
   for (i = 0; i < tbl->num_ents; i++) {
-    gpr_uint16 idx =
-        (gpr_uint16)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
-    grpc_mdelem *ent =
-        tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT];
+    gpr_uint32 idx =
+        (gpr_uint32)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
+    grpc_mdelem *ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
     if (md->key != ent->key) continue;
     r.index = idx;
     r.has_value = md->value == ent->value;
diff --git a/src/core/transport/chttp2/hpack_table.h b/src/core/transport/chttp2/hpack_table.h
index 4f882e2e03ba80f5b6b95911573556221a51672b..e03b8c19b3c3d38da2ea4bfd8a2b5aaf3a873dee 100644
--- a/src/core/transport/chttp2/hpack_table.h
+++ b/src/core/transport/chttp2/hpack_table.h
@@ -49,47 +49,59 @@
 #define GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE
 /* Per entry overhead bytes as per the spec */
 #define GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD 32
+#if 0
 /* Maximum number of entries we could possibly fit in the table, given defined
    overheads */
 #define GRPC_CHTTP2_MAX_TABLE_COUNT                                            \
   ((GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / \
    GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD)
+#endif
 
 /* hpack decoder table */
 typedef struct {
   grpc_mdctx *mdctx;
   /* the first used entry in ents */
-  gpr_uint16 first_ent;
-  /* the last used entry in ents */
-  gpr_uint16 last_ent;
+  gpr_uint32 first_ent;
   /* how many entries are in the table */
-  gpr_uint16 num_ents;
+  gpr_uint32 num_ents;
   /* the amount of memory used by the table, according to the hpack algorithm */
-  gpr_uint16 mem_used;
+  gpr_uint32 mem_used;
   /* the max memory allowed to be used by the table, according to the hpack
      algorithm */
-  gpr_uint16 max_bytes;
+  gpr_uint32 max_bytes;
+  /* the currently agreed size of the table, according to the hpack algorithm */
+  gpr_uint32 current_table_bytes;
+  /* Maximum number of entries we could possibly fit in the table, given defined
+     overheads */
+  gpr_uint32 max_entries;
+  /* Number of entries allocated in ents */
+  gpr_uint32 cap_entries;
   /* a circular buffer of headers - this is stored in the opposite order to
      what hpack specifies, in order to simplify table management a little...
      meaning lookups need to SUBTRACT from the end position */
-  grpc_mdelem *ents[GRPC_CHTTP2_MAX_TABLE_COUNT];
+  grpc_mdelem **ents;
   grpc_mdelem *static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY];
 } grpc_chttp2_hptbl;
 
 /* initialize a hpack table */
 void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx);
 void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl);
+void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
+                                     gpr_uint32 max_bytes);
+int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
+                                             gpr_uint32 bytes);
 
 /* lookup a table entry based on its hpack index */
 grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
                                       gpr_uint32 index);
 /* add a table entry to the index */
-void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md);
+int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
+                          grpc_mdelem *md) GRPC_MUST_USE_RESULT;
 /* Find a key/value pair in the table... returns the index in the table of the
    most similar entry, or 0 if the value was not found */
 typedef struct {
-  gpr_uint16 index;
-  gpr_uint8 has_value;
+  gpr_uint32 index;
+  int has_value;
 } grpc_chttp2_hptbl_find_result;
 grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
     const grpc_chttp2_hptbl *tbl, grpc_mdelem *md);
diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h
index 2d0cb4abdbb6ebf75d2ac071457fe74f64dc4dc2..216439549c4e8cf68b7cbea1e8d16855e29f61f6 100644
--- a/src/core/transport/chttp2/internal.h
+++ b/src/core/transport/chttp2/internal.h
@@ -227,6 +227,9 @@ struct grpc_chttp2_transport_parsing {
   /** was a goaway frame received? */
   gpr_uint8 goaway_received;
 
+  /** the last sent max_table_size setting */
+  gpr_uint32 last_sent_max_table_size;
+
   /** initial window change */
   gpr_int64 initial_window_update;
 
@@ -483,7 +486,8 @@ struct grpc_chttp2_stream {
 /** Someone is unlocking the transport mutex: check to see if writes
     are required, and schedule them if so */
 int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
-                                       grpc_chttp2_transport_writing *writing);
+                                       grpc_chttp2_transport_writing *writing,
+                                       int is_parsing);
 void grpc_chttp2_perform_writes(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
     grpc_endpoint *endpoint);
diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c
index 8cef8fbb772291dee6c1ec7b6f18cd0e92e2dfe2..1e06532c035b0d1ddbf2fb2a2f498f7e97811ff9 100644
--- a/src/core/transport/chttp2/parsing.c
+++ b/src/core/transport/chttp2/parsing.c
@@ -78,6 +78,9 @@ void grpc_chttp2_prepare_to_read(
   GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
 
   transport_parsing->next_stream_id = transport_global->next_stream_id;
+  transport_parsing->last_sent_max_table_size =
+      transport_global->settings[GRPC_SENT_SETTINGS]
+                                [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE];
 
   /* update the parsing view of incoming window */
   while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
@@ -127,6 +130,7 @@ void grpc_chttp2_publish_reads(
            transport_global->settings[GRPC_SENT_SETTINGS],
            GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
     transport_parsing->settings_ack_received = 0;
+    transport_global->sent_local_settings = 0;
   }
 
   /* move goaway to the global state if we received one (it will be
@@ -819,6 +823,9 @@ static int init_settings_frame_parser(
   }
   if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
     transport_parsing->settings_ack_received = 1;
+    grpc_chttp2_hptbl_set_max_bytes(
+        &transport_parsing->hpack_parser.table,
+        transport_parsing->last_sent_max_table_size);
   }
   transport_parsing->parser = grpc_chttp2_settings_parser_parse;
   transport_parsing->parser_data = &transport_parsing->simple.settings;
diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c
index 7fe5649e5ef0e5599a16022e20cae856d8923d2c..805d05222d518a2e3352d024259bbaee0002da19 100644
--- a/src/core/transport/chttp2/writing.c
+++ b/src/core/transport/chttp2/writing.c
@@ -45,7 +45,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
 
 int grpc_chttp2_unlocking_check_writes(
     grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_transport_writing *transport_writing) {
+    grpc_chttp2_transport_writing *transport_writing, int is_parsing) {
   grpc_chttp2_stream_global *stream_global;
   grpc_chttp2_stream_writing *stream_writing;
 
@@ -55,8 +55,13 @@ int grpc_chttp2_unlocking_check_writes(
   gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf);
   GPR_ASSERT(transport_global->qbuf.count == 0);
 
+  grpc_chttp2_hpack_compressor_set_max_table_size(
+      &transport_writing->hpack_compressor,
+      transport_global->settings[GRPC_PEER_SETTINGS]
+                                [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
+
   if (transport_global->dirtied_local_settings &&
-      !transport_global->sent_local_settings) {
+      !transport_global->sent_local_settings && !is_parsing) {
     gpr_slice_buffer_add(
         &transport_writing->outbuf,
         grpc_chttp2_settings_create(
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index f62294c7c50c60c5e4349f32515290e55428e4ac..fdd835def93276fd21c2b7f622784d7b4eed12fb 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -338,6 +338,31 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
           t->global.next_stream_id =
               (gpr_uint32)channel_args->args[i].value.integer;
         }
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) {
+        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s: must be an integer",
+                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
+        } else if (channel_args->args[i].value.integer < 0) {
+          gpr_log(GPR_DEBUG, "%s: must be non-negative",
+                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
+        } else {
+          push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
+                       (gpr_uint32)channel_args->args[i].value.integer);
+        }
+      } else if (0 == strcmp(channel_args->args[i].key,
+                             GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
+        if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
+          gpr_log(GPR_ERROR, "%s: must be an integer",
+                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
+        } else if (channel_args->args[i].value.integer < 0) {
+          gpr_log(GPR_DEBUG, "%s: must be non-negative",
+                  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
+        } else {
+          grpc_chttp2_hpack_compressor_set_max_usable_size(
+              &t->writing.hpack_compressor,
+              (gpr_uint32)channel_args->args[i].value.integer);
+        }
       }
     }
   }
@@ -563,7 +588,8 @@ static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
 static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
   GPR_TIMER_BEGIN("unlock", 0);
   if (!t->writing_active && !t->closed &&
-      grpc_chttp2_unlocking_check_writes(&t->global, &t->writing)) {
+      grpc_chttp2_unlocking_check_writes(&t->global, &t->writing,
+                                         t->parsing_active)) {
     t->writing_active = 1;
     REF_TRANSPORT(t, "writing");
     grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, 1);
@@ -735,6 +761,8 @@ static int contains_non_ok_status(
   return 0;
 }
 
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, int success) {}
+
 static void perform_stream_op_locked(
     grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op) {
@@ -743,6 +771,9 @@ static void perform_stream_op_locked(
   GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
 
   on_complete = op->on_complete;
+  if (on_complete == NULL) {
+    on_complete = grpc_closure_create(do_nothing, NULL);
+  }
   /* use final_data as a barrier until enqueue time; the inital counter is
      dropped at the end of this function */
   on_complete->final_data = 2;
@@ -806,7 +837,7 @@ static void perform_stream_op_locked(
     }
     if (stream_global->write_closed) {
       grpc_chttp2_complete_closure_step(
-          exec_ctx, &stream_global->send_trailing_metadata_finished, 
+          exec_ctx, &stream_global->send_trailing_metadata_finished,
           grpc_metadata_batch_is_empty(op->send_trailing_metadata));
     } else if (stream_global->id != 0) {
       /* TODO(ctiller): check if there's flow control for any outstanding
@@ -1033,7 +1064,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
      to the upper layers - drop what we've got, and then publish
      what we want - which is safe because we haven't told anyone
      about the metadata yet */
-  if (!stream_global->published_trailing_metadata || stream_global->recv_trailing_metadata_finished != NULL) {
+  if (!stream_global->published_trailing_metadata ||
+      stream_global->recv_trailing_metadata_finished != NULL) {
     grpc_mdctx *mdctx =
         TRANSPORT_FROM_GLOBAL(transport_global)->metadata_context;
     char status_string[GPR_LTOA_MIN_BUFSIZE];
diff --git a/src/core/tsi/test_creds/server1.pem b/src/core/tsi/test_creds/server1.pem
index 8e582e571f643ca3fb6042a786c709a53f5afcf3..f3d43fcc5beadd98542abdaa32acfb555b807559 100644
--- a/src/core/tsi/test_creds/server1.pem
+++ b/src/core/tsi/test_creds/server1.pem
@@ -1,16 +1,16 @@
 -----BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
-MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
-MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
-BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
-c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
-JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
-RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
-3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
-BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
-b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
-KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
-wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
-aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
+MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
+MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
+BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
+ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
+LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
+zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
+9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
+CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
+em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
+CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
+hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
+y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
 -----END CERTIFICATE-----
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index 574656a7e9b0a34ae1beb302732019b6fba34be3..9bb358b2339f123b58076ff0c6bc9fdb7dcbf153 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -48,6 +48,7 @@ namespace grpc {
 ClientContext::ClientContext()
     : initial_metadata_received_(false),
       call_(nullptr),
+      call_canceled_(false),
       deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
       propagate_from_call_(nullptr) {}
 
@@ -72,6 +73,7 @@ void ClientContext::AddMetadata(const grpc::string& meta_key,
 
 void ClientContext::set_call(grpc_call* call,
                              const std::shared_ptr<Channel>& channel) {
+  grpc::unique_lock<grpc::mutex> lock(mu_);
   GPR_ASSERT(call_ == nullptr);
   call_ = call;
   channel_ = channel;
@@ -79,6 +81,9 @@ void ClientContext::set_call(grpc_call* call,
     grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED,
                                  "Failed to set credentials to rpc.", nullptr);
   }
+  if (call_canceled_) {
+    grpc_call_cancel(call_, nullptr);
+  }
 }
 
 void ClientContext::set_compression_algorithm(
@@ -101,8 +106,11 @@ std::shared_ptr<const AuthContext> ClientContext::auth_context() const {
 }
 
 void ClientContext::TryCancel() {
+  grpc::unique_lock<grpc::mutex> lock(mu_);
   if (call_) {
     grpc_call_cancel(call_, nullptr);
+  } else {
+    call_canceled_ = true;
   }
 }
 
diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc
index d2b2d30126c0d990fd46490e3af07237ca2e45ea..3bbca807d37e1ff6d790148ad74a75996c5d0397 100644
--- a/src/cpp/client/create_channel.cc
+++ b/src/cpp/client/create_channel.cc
@@ -44,12 +44,14 @@ namespace grpc {
 class ChannelArguments;
 
 std::shared_ptr<Channel> CreateChannel(
-    const grpc::string& target, const std::shared_ptr<Credentials>& creds) {
+    const grpc::string& target,
+    const std::shared_ptr<ChannelCredentials>& creds) {
   return CreateCustomChannel(target, creds, ChannelArguments());
 }
 
 std::shared_ptr<Channel> CreateCustomChannel(
-    const grpc::string& target, const std::shared_ptr<Credentials>& creds,
+    const grpc::string& target,
+    const std::shared_ptr<ChannelCredentials>& creds,
     const ChannelArguments& args) {
   GrpcLibrary init_lib;  // We need to call init in case of a bad creds.
   ChannelArguments cp_args = args;
diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc
index 7a8149e9c7a06e31cb1715bdde76bc20303a66fb..0c08db11a9c5f87ae86ae33cf4763b15032a1b4c 100644
--- a/src/cpp/client/credentials.cc
+++ b/src/cpp/client/credentials.cc
@@ -35,6 +35,8 @@
 
 namespace grpc {
 
-Credentials::~Credentials() {}
+ChannelCredentials::~ChannelCredentials() {}
+
+CallCredentials::~CallCredentials() {}
 
 }  // namespace grpc
diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc
index c476f3ce95b4e5feb57148d09d45b0ba25550c98..1293203b932cdb1b4d6e272265c7b70cb70319cd 100644
--- a/src/cpp/client/insecure_credentials.cc
+++ b/src/cpp/client/insecure_credentials.cc
@@ -43,7 +43,7 @@
 namespace grpc {
 
 namespace {
-class InsecureCredentialsImpl GRPC_FINAL : public Credentials {
+class InsecureChannelCredentialsImpl GRPC_FINAL : public ChannelCredentials {
  public:
   std::shared_ptr<grpc::Channel> CreateChannel(
       const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE {
@@ -54,15 +54,15 @@ class InsecureCredentialsImpl GRPC_FINAL : public Credentials {
         grpc_insecure_channel_create(target.c_str(), &channel_args, nullptr));
   }
 
-  // InsecureCredentials should not be applied to a call.
-  bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE { return false; }
-
-  SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return nullptr; }
+  SecureChannelCredentials* AsSecureCredentials() GRPC_OVERRIDE {
+    return nullptr;
+  }
 };
 }  // namespace
 
-std::shared_ptr<Credentials> InsecureCredentials() {
-  return std::shared_ptr<Credentials>(new InsecureCredentialsImpl());
+std::shared_ptr<ChannelCredentials> InsecureChannelCredentials() {
+  return std::shared_ptr<ChannelCredentials>(
+      new InsecureChannelCredentialsImpl());
 }
 
 }  // namespace grpc
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 8299ebeb8a233499ec6bf9d8bc007e9b120fe44b..a1b9a3018e83ea8bfb669639d9858473124aa183 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -40,7 +40,7 @@
 
 namespace grpc {
 
-std::shared_ptr<grpc::Channel> SecureCredentials::CreateChannel(
+std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannel(
     const string& target, const grpc::ChannelArguments& args) {
   grpc_channel_args channel_args;
   args.SetChannelArgs(&channel_args);
@@ -50,96 +50,104 @@ std::shared_ptr<grpc::Channel> SecureCredentials::CreateChannel(
                                  nullptr));
 }
 
-bool SecureCredentials::ApplyToCall(grpc_call* call) {
+bool SecureCallCredentials::ApplyToCall(grpc_call* call) {
   return grpc_call_set_credentials(call, c_creds_) == GRPC_CALL_OK;
 }
 
 namespace {
-std::shared_ptr<Credentials> WrapCredentials(grpc_credentials* creds) {
-  return creds == nullptr
-             ? nullptr
-             : std::shared_ptr<Credentials>(new SecureCredentials(creds));
+std::shared_ptr<ChannelCredentials> WrapChannelCredentials(
+    grpc_channel_credentials* creds) {
+  return creds == nullptr ? nullptr : std::shared_ptr<ChannelCredentials>(
+                                          new SecureChannelCredentials(creds));
+}
+
+std::shared_ptr<CallCredentials> WrapCallCredentials(
+    grpc_call_credentials* creds) {
+  return creds == nullptr ? nullptr : std::shared_ptr<CallCredentials>(
+                                          new SecureCallCredentials(creds));
 }
 }  // namespace
 
-std::shared_ptr<Credentials> GoogleDefaultCredentials() {
+std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
   GrpcLibrary init;  // To call grpc_init().
-  return WrapCredentials(grpc_google_default_credentials_create());
+  return WrapChannelCredentials(grpc_google_default_credentials_create());
 }
 
 // Builds SSL Credentials given SSL specific options
-std::shared_ptr<Credentials> SslCredentials(
+std::shared_ptr<ChannelCredentials> SslCredentials(
     const SslCredentialsOptions& options) {
   GrpcLibrary init;  // To call grpc_init().
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
       options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
 
-  grpc_credentials* c_creds = grpc_ssl_credentials_create(
+  grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
       options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
       options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr);
-  return WrapCredentials(c_creds);
+  return WrapChannelCredentials(c_creds);
 }
 
 // Builds credentials for use when running in GCE
-std::shared_ptr<Credentials> GoogleComputeEngineCredentials() {
+std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
   GrpcLibrary init;  // To call grpc_init().
-  return WrapCredentials(
+  return WrapCallCredentials(
       grpc_google_compute_engine_credentials_create(nullptr));
 }
 
 // Builds JWT credentials.
-std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
+std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
     const grpc::string& json_key, long token_lifetime_seconds) {
   GrpcLibrary init;  // To call grpc_init().
   if (token_lifetime_seconds <= 0) {
     gpr_log(GPR_ERROR,
             "Trying to create JWTCredentials with non-positive lifetime");
-    return WrapCredentials(nullptr);
+    return WrapCallCredentials(nullptr);
   }
   gpr_timespec lifetime =
       gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN);
-  return WrapCredentials(grpc_service_account_jwt_access_credentials_create(
+  return WrapCallCredentials(grpc_service_account_jwt_access_credentials_create(
       json_key.c_str(), lifetime, nullptr));
 }
 
 // Builds refresh token credentials.
-std::shared_ptr<Credentials> GoogleRefreshTokenCredentials(
+std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
     const grpc::string& json_refresh_token) {
   GrpcLibrary init;  // To call grpc_init().
-  return WrapCredentials(grpc_google_refresh_token_credentials_create(
+  return WrapCallCredentials(grpc_google_refresh_token_credentials_create(
       json_refresh_token.c_str(), nullptr));
 }
 
 // Builds access token credentials.
-std::shared_ptr<Credentials> AccessTokenCredentials(
+std::shared_ptr<CallCredentials> AccessTokenCredentials(
     const grpc::string& access_token) {
   GrpcLibrary init;  // To call grpc_init().
-  return WrapCredentials(
+  return WrapCallCredentials(
       grpc_access_token_credentials_create(access_token.c_str(), nullptr));
 }
 
 // Builds IAM credentials.
-std::shared_ptr<Credentials> GoogleIAMCredentials(
+std::shared_ptr<CallCredentials> GoogleIAMCredentials(
     const grpc::string& authorization_token,
     const grpc::string& authority_selector) {
   GrpcLibrary init;  // To call grpc_init().
-  return WrapCredentials(grpc_google_iam_credentials_create(
+  return WrapCallCredentials(grpc_google_iam_credentials_create(
       authorization_token.c_str(), authority_selector.c_str(), nullptr));
 }
 
-// Combines two credentials objects into a composite credentials.
-std::shared_ptr<Credentials> CompositeCredentials(
-    const std::shared_ptr<Credentials>& creds1,
-    const std::shared_ptr<Credentials>& creds2) {
-  // Note that we are not saving shared_ptrs to the two credentials
-  // passed in here. This is OK because the underlying C objects (i.e.,
-  // creds1 and creds2) into grpc_composite_credentials_create will see their
-  // refcounts incremented.
-  SecureCredentials* s1 = creds1->AsSecureCredentials();
-  SecureCredentials* s2 = creds2->AsSecureCredentials();
-  if (s1 && s2) {
-    return WrapCredentials(grpc_composite_credentials_create(
-        s1->GetRawCreds(), s2->GetRawCreds(), nullptr));
+// Combines one channel credentials and one call credentials into a channel
+// composite credentials.
+std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
+    const std::shared_ptr<ChannelCredentials>& channel_creds,
+    const std::shared_ptr<CallCredentials>& call_creds) {
+  // Note that we are not saving shared_ptrs to the two credentials passed in
+  // here. This is OK because the underlying C objects (i.e., channel_creds and
+  // call_creds) into grpc_composite_credentials_create will see their refcounts
+  // incremented.
+  SecureChannelCredentials* s_channel_creds =
+      channel_creds->AsSecureCredentials();
+  SecureCallCredentials* s_call_creds = call_creds->AsSecureCredentials();
+  if (s_channel_creds && s_call_creds) {
+    return WrapChannelCredentials(grpc_composite_channel_credentials_create(
+        s_channel_creds->GetRawCreds(), s_call_creds->GetRawCreds(), nullptr));
   }
   return nullptr;
 }
@@ -193,7 +201,7 @@ MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
     std::unique_ptr<MetadataCredentialsPlugin> plugin)
     : thread_pool_(CreateDefaultThreadPool()), plugin_(std::move(plugin)) {}
 
-std::shared_ptr<Credentials> MetadataCredentialsFromPlugin(
+std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
     std::unique_ptr<MetadataCredentialsPlugin> plugin) {
   GrpcLibrary init;  // To call grpc_init().
   MetadataCredentialsPluginWrapper* wrapper =
@@ -201,7 +209,7 @@ std::shared_ptr<Credentials> MetadataCredentialsFromPlugin(
   grpc_metadata_credentials_plugin c_plugin = {
       MetadataCredentialsPluginWrapper::GetMetadata,
       MetadataCredentialsPluginWrapper::Destroy, wrapper};
-  return WrapCredentials(
+  return WrapCallCredentials(
       grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
 }
 
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index d354827725a30c77290e8dbf2f500759baee3f4b..e9afa9e57f8d5cacaf3adee5f5d5a20bb3ad733f 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -43,19 +43,37 @@
 
 namespace grpc {
 
-class SecureCredentials GRPC_FINAL : public Credentials {
+class SecureChannelCredentials GRPC_FINAL : public ChannelCredentials {
  public:
-  explicit SecureCredentials(grpc_credentials* c_creds) : c_creds_(c_creds) {}
-  ~SecureCredentials() GRPC_OVERRIDE { grpc_credentials_release(c_creds_); }
-  grpc_credentials* GetRawCreds() { return c_creds_; }
-  bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE;
+  explicit SecureChannelCredentials(grpc_channel_credentials* c_creds)
+      : c_creds_(c_creds) {}
+  ~SecureChannelCredentials() GRPC_OVERRIDE {
+    grpc_channel_credentials_release(c_creds_);
+  }
+  grpc_channel_credentials* GetRawCreds() { return c_creds_; }
 
   std::shared_ptr<grpc::Channel> CreateChannel(
       const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE;
-  SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
+  SecureChannelCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
+
+ private:
+  grpc_channel_credentials* const c_creds_;
+};
+
+class SecureCallCredentials GRPC_FINAL : public CallCredentials {
+ public:
+  explicit SecureCallCredentials(grpc_call_credentials* c_creds)
+      : c_creds_(c_creds) {}
+  ~SecureCallCredentials() GRPC_OVERRIDE {
+    grpc_call_credentials_release(c_creds_);
+  }
+  grpc_call_credentials* GetRawCreds() { return c_creds_; }
+
+  bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE;
+  SecureCallCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
 
  private:
-  grpc_credentials* const c_creds_;
+  grpc_call_credentials* const c_creds_;
 };
 
 class MetadataCredentialsPluginWrapper GRPC_FINAL {
diff --git a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs
index 87d55cd276ae5601b84a1dd3b7db97dd4aac5fe7..144b8320b9df5c276fe8a19f773e4a61593cc1de 100644
--- a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs
+++ b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs
@@ -57,7 +57,7 @@ namespace Grpc.Core.Tests
             get { return composable; }
         }
 
-        internal override CredentialsSafeHandle ToNativeCredentials()
+        internal override ChannelCredentialsSafeHandle ToNativeCredentials()
         {
             return null;
         }
@@ -65,7 +65,7 @@ namespace Grpc.Core.Tests
 
     internal class FakeCallCredentials : CallCredentials
     {
-        internal override CredentialsSafeHandle ToNativeCredentials()
+        internal override CallCredentialsSafeHandle ToNativeCredentials()
         {
             return null;
         }
diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core/CallCredentials.cs
index 400a9825de220029cb0d2e5fbf39acf4345f2041..5ea179dfea152353b051902c03dde16cc2c477da 100644
--- a/src/csharp/Grpc.Core/CallCredentials.cs
+++ b/src/csharp/Grpc.Core/CallCredentials.cs
@@ -78,7 +78,7 @@ namespace Grpc.Core
         /// Creates native object for the credentials.
         /// </summary>
         /// <returns>The native credentials.</returns>
-        internal abstract CredentialsSafeHandle ToNativeCredentials();
+        internal abstract CallCredentialsSafeHandle ToNativeCredentials();
     }
 
     /// <summary>
@@ -98,7 +98,7 @@ namespace Grpc.Core
             this.interceptor = Preconditions.CheckNotNull(interceptor);
         }
 
-        internal override CredentialsSafeHandle ToNativeCredentials()
+        internal override CallCredentialsSafeHandle ToNativeCredentials()
         {
             NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor);
             return plugin.Credentials;
@@ -123,14 +123,14 @@ namespace Grpc.Core
             this.credentials = new List<CallCredentials>(credentials);
         }
 
-        internal override CredentialsSafeHandle ToNativeCredentials()
+        internal override CallCredentialsSafeHandle ToNativeCredentials()
         {
             return ToNativeRecursive(0);
         }
 
         // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier.
         // In practice, we won't usually see composites from more than two credentials anyway.
-        private CredentialsSafeHandle ToNativeRecursive(int startIndex)
+        private CallCredentialsSafeHandle ToNativeRecursive(int startIndex)
         {
             if (startIndex == credentials.Count - 1)
             {
@@ -140,7 +140,7 @@ namespace Grpc.Core
             using (var cred1 = credentials[startIndex].ToNativeCredentials())
             using (var cred2 = ToNativeRecursive(startIndex + 1))
             {
-                var nativeComposite = CredentialsSafeHandle.CreateComposite(cred1, cred2);
+                var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2);
                 if (nativeComposite.IsInvalid)
                 {
                     throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index 6b99055d4c893cb7b92d703d11b4bdbc2360fb71..f5eec969f5ed5b4ee91b4a74f39d304b7736a51f 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -75,8 +75,8 @@ namespace Grpc.Core
             this.options = options != null ? new List<ChannelOption>(options) : new List<ChannelOption>();
 
             EnsureUserAgentChannelOption(this.options);
-            using (CredentialsSafeHandle nativeCredentials = credentials.ToNativeCredentials())
-            using (ChannelArgsSafeHandle nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options))
+            using (var nativeCredentials = credentials.ToNativeCredentials())
+            using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options))
             {
                 if (nativeCredentials != null)
                 {
diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs
index 9d2bcdabe843abc2799d04fcdf7d581de37cbe62..5d96958e7c082f1871f585a29af91883b7276022 100644
--- a/src/csharp/Grpc.Core/ChannelCredentials.cs
+++ b/src/csharp/Grpc.Core/ChannelCredentials.cs
@@ -76,7 +76,7 @@ namespace Grpc.Core
         /// should be created.
         /// </summary>
         /// <returns>The native credentials.</returns>
-        internal abstract CredentialsSafeHandle ToNativeCredentials();
+        internal abstract ChannelCredentialsSafeHandle ToNativeCredentials();
 
         /// <summary>
         /// Returns <c>true</c> if this credential type allows being composed by <c>CompositeCredentials</c>.
@@ -88,7 +88,7 @@ namespace Grpc.Core
 
         private sealed class InsecureCredentialsImpl : ChannelCredentials
         {
-            internal override CredentialsSafeHandle ToNativeCredentials()
+            internal override ChannelCredentialsSafeHandle ToNativeCredentials()
             {
                 return null;
             }
@@ -160,9 +160,9 @@ namespace Grpc.Core
             get { return true; }
         }
 
-        internal override CredentialsSafeHandle ToNativeCredentials()
+        internal override ChannelCredentialsSafeHandle ToNativeCredentials()
         {
-            return CredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair);
+            return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair);
         }
     }
 
@@ -188,12 +188,12 @@ namespace Grpc.Core
             Preconditions.CheckArgument(channelCredentials.IsComposable, "Supplied channel credentials do not allow composition.");
         }
 
-        internal override CredentialsSafeHandle ToNativeCredentials()
+        internal override ChannelCredentialsSafeHandle ToNativeCredentials()
         {
-            using (var cred1 = channelCredentials.ToNativeCredentials())
-            using (var cred2 = callCredentials.ToNativeCredentials())
+            using (var channelCreds = channelCredentials.ToNativeCredentials())
+            using (var callCreds = callCredentials.ToNativeCredentials())
             {
-                var nativeComposite = CredentialsSafeHandle.CreateComposite(cred1, cred2);
+                var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCreds, callCreds);
                 if (nativeComposite.IsInvalid)
                 {
                     throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 0aab7bdd8ad2a4591bf12ef21bdcfff3523e1aec..c4f799297d6688cd0314fea7a8b8079353e7f9d9 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -80,7 +80,6 @@
     <Compile Include="ServerServiceDefinition.cs" />
     <Compile Include="Utils\AsyncStreamExtensions.cs" />
     <Compile Include="Utils\BenchmarkUtil.cs" />
-    <Compile Include="Internal\CredentialsSafeHandle.cs" />
     <Compile Include="ChannelCredentials.cs" />
     <Compile Include="Internal\ChannelArgsSafeHandle.cs" />
     <Compile Include="Internal\AsyncCompletion.cs" />
@@ -119,6 +118,8 @@
     <Compile Include="CompressionLevel.cs" />
     <Compile Include="WriteOptions.cs" />
     <Compile Include="ContextPropagationToken.cs" />
+    <Compile Include="Internal\CallCredentialsSafeHandle.cs" />
+    <Compile Include="Internal\ChannelCredentialsSafeHandle.cs" />
     <Compile Include="Profiling\ProfilerEntry.cs" />
     <Compile Include="Profiling\ProfilerScope.cs" />
     <Compile Include="Profiling\IProfiler.cs" />
@@ -157,4 +158,4 @@
   <ItemGroup>
     <Folder Include="Profiling\" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3678c7dd86f413a4b8cfa920e1b51c7c0306e074
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs
@@ -0,0 +1,64 @@
+#region Copyright notice and license
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// grpc_call_credentials from <c>grpc/grpc_security.h</c>
+    /// </summary>
+    internal class CallCredentialsSafeHandle : SafeHandleZeroIsInvalid
+    {
+        [DllImport("grpc_csharp_ext.dll")]
+        static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2);
+
+        [DllImport("grpc_csharp_ext.dll")]
+        static extern void grpcsharp_call_credentials_release(IntPtr credentials);
+
+        private CallCredentialsSafeHandle()
+        {
+        }
+
+        public static CallCredentialsSafeHandle CreateComposite(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2)
+        {
+            return grpcsharp_composite_call_credentials_create(creds1, creds2);
+        }
+
+        protected override bool ReleaseHandle()
+        {
+            grpcsharp_call_credentials_release(handle);
+            return true;
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index ddeedebd117f650f99702c759d22bd5a824110ae..ad2e2919b7411911c0b64c1fdca92b86b5df71e0 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -100,7 +100,7 @@ namespace Grpc.Core.Internal
             BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
 
         [DllImport("grpc_csharp_ext.dll")]
-        static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CredentialsSafeHandle credentials);
+        static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials);
 
         [DllImport("grpc_csharp_ext.dll")]
         static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call);
@@ -117,7 +117,7 @@ namespace Grpc.Core.Internal
             this.completionRegistry = completionRegistry;
         }
 
-        public void SetCredentials(CredentialsSafeHandle credentials)
+        public void SetCredentials(CallCredentialsSafeHandle credentials)
         {
             grpcsharp_call_set_credentials(this, credentials).CheckOk();
         }
diff --git a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs
similarity index 68%
rename from src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs
rename to src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs
index bab45108e02a060952e8b96dcc64cd807dd63779..8a58c64478e44726a52cabbaae3b04a308e94bc2 100644
--- a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs
@@ -36,31 +36,31 @@ using System.Threading.Tasks;
 namespace Grpc.Core.Internal
 {
     /// <summary>
-    /// grpc_credentials from <c>grpc/grpc_security.h</c>
+    /// grpc_channel_credentials from <c>grpc/grpc_security.h</c>
     /// </summary>
-    internal class CredentialsSafeHandle : SafeHandleZeroIsInvalid
+    internal class ChannelCredentialsSafeHandle : SafeHandleZeroIsInvalid
     {
         [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
-        static extern CredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey);
+        static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey);
 
         [DllImport("grpc_csharp_ext.dll")]
-        static extern CredentialsSafeHandle grpcsharp_composite_credentials_create(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2);
+        static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds);
 
         [DllImport("grpc_csharp_ext.dll")]
-        static extern void grpcsharp_credentials_release(IntPtr credentials);
+        static extern void grpcsharp_channel_credentials_release(IntPtr credentials);
 
-        private CredentialsSafeHandle()
+        private ChannelCredentialsSafeHandle()
         {
         }
 
-        public static CredentialsSafeHandle CreateNullCredentials()
+        public static ChannelCredentialsSafeHandle CreateNullCredentials()
         {
-            var creds = new CredentialsSafeHandle();
+            var creds = new ChannelCredentialsSafeHandle();
             creds.SetHandle(IntPtr.Zero);
             return creds;
         }
 
-        public static CredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair)
+        public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair)
         {
             if (keyCertPair != null)
             {
@@ -72,14 +72,14 @@ namespace Grpc.Core.Internal
             }
         }
 
-        public static CredentialsSafeHandle CreateComposite(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2)
+        public static ChannelCredentialsSafeHandle CreateComposite(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds)
         {
-            return grpcsharp_composite_credentials_create(creds1, creds2);
+            return grpcsharp_composite_channel_credentials_create(channelCreds, callCreds);
         }
 
         protected override bool ReleaseHandle()
         {
-            grpcsharp_credentials_release(handle);
+            grpcsharp_channel_credentials_release(handle);
             return true;
         }
     }
diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
index 5f9169bcb2f02b70878a4fd871379c3c7eca6fca..b3aa27c40fa1c17c63a25110e8f57311dab63746 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
@@ -45,7 +45,7 @@ namespace Grpc.Core.Internal
         static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs);
 
         [DllImport("grpc_csharp_ext.dll")]
-        static extern ChannelSafeHandle grpcsharp_secure_channel_create(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs);
+        static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs);
 
         [DllImport("grpc_csharp_ext.dll")]
         static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
@@ -75,7 +75,7 @@ namespace Grpc.Core.Internal
             return grpcsharp_insecure_channel_create(target, channelArgs);
         }
 
-        public static ChannelSafeHandle CreateSecure(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs)
+        public static ChannelSafeHandle CreateSecure(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs)
         {
             // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle.
             // Doing so would make object finalizer crash if we end up abandoning the handle.
@@ -83,7 +83,7 @@ namespace Grpc.Core.Internal
             return grpcsharp_secure_channel_create(credentials, target, channelArgs);
         }
 
-        public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CredentialsSafeHandle credentials)
+        public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials)
         {
             using (Profilers.ForCurrentThread().NewScope("ChannelSafeHandle.CreateCall"))
             {
diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
index f76492cba4a90b9b7151a52bafe5f026e62c9cfe..2a571cd6c9862b4f0f6a4daa33fbeeb8522569a6 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
@@ -46,7 +46,7 @@ namespace Grpc.Core.Internal
         static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeMetadataCredentialsPlugin>();
 
         [DllImport("grpc_csharp_ext.dll")]
-        static extern CredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor);
+        static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor);
         
         [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
         static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
@@ -54,7 +54,7 @@ namespace Grpc.Core.Internal
         AsyncAuthInterceptor interceptor;
         GCHandle gcHandle;
         NativeMetadataInterceptor nativeInterceptor;
-        CredentialsSafeHandle credentials;
+        CallCredentialsSafeHandle credentials;
 
         public NativeMetadataCredentialsPlugin(AsyncAuthInterceptor interceptor)
         {
@@ -66,7 +66,7 @@ namespace Grpc.Core.Internal
             this.credentials = grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor);
         }
 
-        public CredentialsSafeHandle Credentials
+        public CallCredentialsSafeHandle Credentials
         {
             get { return credentials; }
         }
diff --git a/src/csharp/Grpc.Core/Profiling/IProfiler.cs b/src/csharp/Grpc.Core/Profiling/IProfiler.cs
index c426c365d2d6a7cc76c216d902f24a24d5264414..e850375004ec42fd3d615f43051e3669e6fdf9bb 100644
--- a/src/csharp/Grpc.Core/Profiling/IProfiler.cs
+++ b/src/csharp/Grpc.Core/Profiling/IProfiler.cs
@@ -41,7 +41,9 @@ namespace Grpc.Core.Profiling
     internal interface IProfiler 
     {
         void Begin(string tag);
+
         void End(string tag);
+
         void Mark(string tag);
     }
 }
diff --git a/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs b/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs
index 5cc4c3c05429378b3ecb8bd1ae3d345304bce427..792e3c3cd056dfbd6d8743b160300a2363243d60 100644
--- a/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs
+++ b/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs
@@ -40,7 +40,8 @@ namespace Grpc.Core.Profiling
 {
     internal struct ProfilerEntry
     {
-        public enum Type {
+        public enum Type
+        {
             BEGIN,
             END,
             MARK
diff --git a/src/csharp/Grpc.Core/Profiling/Profilers.cs b/src/csharp/Grpc.Core/Profiling/Profilers.cs
index c8123347f2b954295583c46802f713a15722d31c..471ee20875eaecdf52bab596316b5881df6a43c2 100644
--- a/src/csharp/Grpc.Core/Profiling/Profilers.cs
+++ b/src/csharp/Grpc.Core/Profiling/Profilers.cs
@@ -40,12 +40,12 @@ namespace Grpc.Core.Profiling
 {
     internal static class Profilers
     {
-        static readonly NopProfiler defaultProfiler = new NopProfiler();
+        static readonly NopProfiler DefaultProfiler = new NopProfiler();
         static readonly ThreadLocal<IProfiler> profilers = new ThreadLocal<IProfiler>();
 
         public static IProfiler ForCurrentThread()
         {
-            return profilers.Value ?? defaultProfiler;
+            return profilers.Value ?? DefaultProfiler;
         }
 
         public static void SetForCurrentThread(IProfiler profiler)
@@ -89,15 +89,18 @@ namespace Grpc.Core.Profiling
             this.entries = new ProfilerEntry[capacity];
         }
 
-        public void Begin(string tag) {
+        public void Begin(string tag)
+        {
             AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.BEGIN, tag));
         }
 
-        public void End(string tag) {
+        public void End(string tag)
+        {
             AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.END, tag));
         }
 
-        public void Mark(string tag) {
+        public void Mark(string tag)
+        {
             AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.MARK, tag));
         }
 
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore b/src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a382af2294f7a8b9d7789117aeeb80a0a56bc19b
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore
@@ -0,0 +1,3 @@
+bin
+obj
+
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..8b245ade2e2b609f32f0649219ca59fbeab93302
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Grpc.IntegrationTesting.QpsWorker</RootNamespace>
+    <AssemblyName>Grpc.IntegrationTesting.QpsWorker</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\ReleaseSigned</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Grpc.Core\Version.cs">
+      <Link>Version.cs</Link>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
+      <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
+      <Name>Grpc.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Grpc.IntegrationTesting\Grpc.IntegrationTesting.csproj">
+      <Project>{C61154BA-DD4A-4838-8420-0162A28925E0}</Project>
+      <Name>Grpc.IntegrationTesting</Name>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs
new file mode 100644
index 0000000000000000000000000000000000000000..308463337fc5983b00b2423e74368e8d182712b3
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs
@@ -0,0 +1,46 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using Grpc.IntegrationTesting;
+
+namespace Grpc.IntegrationTesting
+{
+    class Program
+    {
+        public static void Main(string[] args)
+        {
+            QpsWorker.Run(args);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..aacfc16ef450a706419ca10970deaa0c84fd684f
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Grpc.IntegrationTesting.QpsWorker")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..47a15224f165d8458d4a3589ac46bb27d3ca241d
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
@@ -0,0 +1,76 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+
+namespace Grpc.Testing
+{
+    /// <summary>
+    /// Implementation of BenchmarkService server
+    /// </summary>
+    public class BenchmarkServiceImpl : BenchmarkService.IBenchmarkService
+    {
+        private readonly int responseSize;
+
+        public BenchmarkServiceImpl(int responseSize)
+        {
+            this.responseSize = responseSize;
+        }
+
+        public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
+        {
+            var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) };
+            return Task.FromResult(response);
+        }
+
+        public async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
+        {
+            await requestStream.ForEachAsync(async request =>
+            {
+                var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) };
+                await responseStream.WriteAsync(response);
+            });
+        }
+
+        private static Payload CreateZerosPayload(int size)
+        {
+            return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e9e659cb1fb188b930cde1394cc97c2af7bbfe2b
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
@@ -0,0 +1,153 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Helper methods to start client runners for performance testing.
+    /// </summary>
+    public static class ClientRunners
+    {
+        /// <summary>
+        /// Creates a started client runner.
+        /// </summary>
+        public static IClientRunner CreateStarted(ClientConfig config)
+        {
+            string target = config.ServerTargets.Single();
+            Grpc.Core.Utils.Preconditions.CheckArgument(config.LoadParams.LoadCase == LoadParams.LoadOneofCase.ClosedLoop);
+
+            var credentials = config.SecurityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure;
+            var channel = new Channel(target, credentials);
+
+            switch (config.RpcType)
+            {
+                case RpcType.UNARY:
+                    return new SyncUnaryClientRunner(channel,
+                        config.PayloadConfig.SimpleParams.ReqSize,
+                        config.HistogramParams);
+
+                case RpcType.STREAMING:
+                default:
+                    throw new ArgumentException("Unsupported RpcType.");
+            }
+        }
+    }
+
+    /// <summary>
+    /// Client that starts synchronous unary calls in a closed loop.
+    /// </summary>
+    public class SyncUnaryClientRunner : IClientRunner
+    {
+        const double SecondsToNanos = 1e9;
+
+        readonly Channel channel;
+        readonly int payloadSize;
+        readonly Histogram histogram;
+
+        readonly BenchmarkService.IBenchmarkServiceClient client;
+        readonly Task runnerTask;
+        readonly CancellationTokenSource stoppedCts;
+        readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
+        
+        public SyncUnaryClientRunner(Channel channel, int payloadSize, HistogramParams histogramParams)
+        {
+            this.channel = Grpc.Core.Utils.Preconditions.CheckNotNull(channel);
+            this.payloadSize = payloadSize;
+            this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible);
+
+            this.stoppedCts = new CancellationTokenSource();
+            this.client = BenchmarkService.NewClient(channel);
+            this.runnerTask = Task.Factory.StartNew(Run, TaskCreationOptions.LongRunning);
+        }
+
+        public ClientStats GetStats(bool reset)
+        {
+            var histogramData = histogram.GetSnapshot(reset);
+            var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
+
+            // TODO: populate user time and system time
+            return new ClientStats
+            {
+                Latencies = histogramData,
+                TimeElapsed = secondsElapsed,
+                TimeUser = 0,
+                TimeSystem = 0
+            };
+        }
+
+        public async Task StopAsync()
+        {
+            stoppedCts.Cancel();
+            await runnerTask;
+            await channel.ShutdownAsync();
+        }
+
+        private void Run()
+        {
+            var request = new SimpleRequest
+            {
+                Payload = CreateZerosPayload(payloadSize)
+            };
+            var stopwatch = new Stopwatch();
+
+            while (!stoppedCts.Token.IsCancellationRequested)
+            {
+                stopwatch.Restart();
+                client.UnaryCall(request);
+                stopwatch.Stop();
+
+                // spec requires data point in nanoseconds.
+                histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
+            }
+        }
+
+        private static Payload CreateZerosPayload(int size)
+        {
+            return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4764e1072bdbb93baf49626799ce91d66b54bd63
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -0,0 +1,2362 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: test/proto/benchmarks/control.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class Control {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static Control() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiN0ZXN0L3Byb3RvL2JlbmNobWFya3MvY29udHJvbC5wcm90bxIMZ3JwYy50", 
+            "ZXN0aW5nGiR0ZXN0L3Byb3RvL2JlbmNobWFya3MvcGF5bG9hZHMucHJvdG8a", 
+            "IXRlc3QvcHJvdG8vYmVuY2htYXJrcy9zdGF0cy5wcm90byIlCg1Qb2lzc29u", 
+            "UGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASJBCg1Vbmlmb3JtUGFyYW1z", 
+            "EhcKD2ludGVyYXJyaXZhbF9sbxgBIAEoARIXCg9pbnRlcmFycml2YWxfaGkY", 
+            "AiABKAEiKwoTRGV0ZXJtaW5pc3RpY1BhcmFtcxIUCgxvZmZlcmVkX2xvYWQY", 
+            "ASABKAEiOAoMUGFyZXRvUGFyYW1zEhkKEWludGVyYXJyaXZhbF9iYXNlGAEg", 
+            "ASgBEg0KBWFscGhhGAIgASgBIhIKEENsb3NlZExvb3BQYXJhbXMijgIKCkxv", 
+            "YWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5ncnBjLnRlc3Rpbmcu", 
+            "Q2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiABKAsyGy5ncnBjLnRl", 
+            "c3RpbmcuUG9pc3NvblBhcmFtc0gAEi4KB3VuaWZvcm0YAyABKAsyGy5ncnBj", 
+            "LnRlc3RpbmcuVW5pZm9ybVBhcmFtc0gAEjMKBmRldGVybRgEIAEoCzIhLmdy", 
+            "cGMudGVzdGluZy5EZXRlcm1pbmlzdGljUGFyYW1zSAASLAoGcGFyZXRvGAUg", 
+            "ASgLMhouZ3JwYy50ZXN0aW5nLlBhcmV0b1BhcmFtc0gAQgYKBGxvYWQiQwoO", 
+            "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy", 
+            "X2hvc3Rfb3ZlcnJpZGUYAiABKAkirwMKDENsaWVudENvbmZpZxIWCg5zZXJ2", 
+            "ZXJfdGFyZ2V0cxgBIAMoCRItCgtjbGllbnRfdHlwZRgCIAEoDjIYLmdycGMu", 
+            "dGVzdGluZy5DbGllbnRUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgDIAEoCzIc", 
+            "LmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIkChxvdXRzdGFuZGluZ19y", 
+            "cGNzX3Blcl9jaGFubmVsGAQgASgFEhcKD2NsaWVudF9jaGFubmVscxgFIAEo", 
+            "BRIcChRhc3luY19jbGllbnRfdGhyZWFkcxgHIAEoBRInCghycGNfdHlwZRgI", 
+            "IAEoDjIVLmdycGMudGVzdGluZy5ScGNUeXBlEi0KC2xvYWRfcGFyYW1zGAog", 
+            "ASgLMhguZ3JwYy50ZXN0aW5nLkxvYWRQYXJhbXMSMwoOcGF5bG9hZF9jb25m", 
+            "aWcYCyABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxI3ChBoaXN0", 
+            "b2dyYW1fcGFyYW1zGAwgASgLMh0uZ3JwYy50ZXN0aW5nLkhpc3RvZ3JhbVBh", 
+            "cmFtcyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBjLnRl", 
+            "c3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNldBgBIAEoCCJoCgpD", 
+            "bGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVu", 
+            "dENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRlc3RpbmcuTWFya0gA", 
+            "QgkKB2FyZ3R5cGUi9wEKDFNlcnZlckNvbmZpZxItCgtzZXJ2ZXJfdHlwZRgB", 
+            "IAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUKD3NlY3VyaXR5X3Bh", 
+            "cmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIMCgRo", 
+            "b3N0GAMgASgJEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVyX3RocmVh", 
+            "ZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2FkX2NvbmZp", 
+            "ZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnImgKClNlcnZl", 
+            "ckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2VydmVyQ29u", 
+            "ZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJrSABCCQoH", 
+            "YXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBj", 
+            "LnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVjb3JlcxgD", 
+            "IAEoBSovCgpDbGllbnRUeXBlEg8KC1NZTkNfQ0xJRU5UEAASEAoMQVNZTkNf", 
+            "Q0xJRU5UEAEqLwoKU2VydmVyVHlwZRIPCgtTWU5DX1NFUlZFUhAAEhAKDEFT", 
+            "WU5DX1NFUlZFUhABKiMKB1JwY1R5cGUSCQoFVU5BUlkQABINCglTVFJFQU1J", 
+            "TkcQAWIGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { global::Grpc.Testing.Payloads.Descriptor, global::Grpc.Testing.Stats.Descriptor, },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PoissonParams), new[]{ "OfferedLoad" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.UniformParams), new[]{ "InterarrivalLo", "InterarrivalHi" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.DeterministicParams), new[]{ "OfferedLoad" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ParetoParams), new[]{ "InterarrivalBase", "Alpha" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.LoadParams), new[]{ "ClosedLoop", "Poisson", "Uniform", "Determ", "Pareto" }, new[]{ "Load" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SecurityParams), new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientConfig), new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStatus), new[]{ "Stats" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Mark), new[]{ "Reset" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientArgs), new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerConfig), new[]{ "ServerType", "SecurityParams", "Host", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerArgs), new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStatus), new[]{ "Stats", "Port", "Cores" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum ClientType {
+    SYNC_CLIENT = 0,
+    ASYNC_CLIENT = 1,
+  }
+
+  public enum ServerType {
+    SYNC_SERVER = 0,
+    ASYNC_SERVER = 1,
+  }
+
+  public enum RpcType {
+    UNARY = 0,
+    STREAMING = 1,
+  }
+
+  #endregion
+
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class PoissonParams : pb::IMessage<PoissonParams> {
+    private static readonly pb::MessageParser<PoissonParams> _parser = new pb::MessageParser<PoissonParams>(() => new PoissonParams());
+    public static pb::MessageParser<PoissonParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public PoissonParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public PoissonParams(PoissonParams other) : this() {
+      offeredLoad_ = other.offeredLoad_;
+    }
+
+    public PoissonParams Clone() {
+      return new PoissonParams(this);
+    }
+
+    public const int OfferedLoadFieldNumber = 1;
+    private double offeredLoad_;
+    public double OfferedLoad {
+      get { return offeredLoad_; }
+      set {
+        offeredLoad_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as PoissonParams);
+    }
+
+    public bool Equals(PoissonParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (OfferedLoad != other.OfferedLoad) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (OfferedLoad != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(OfferedLoad);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (OfferedLoad != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(PoissonParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.OfferedLoad != 0D) {
+        OfferedLoad = other.OfferedLoad;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 9: {
+            OfferedLoad = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class UniformParams : pb::IMessage<UniformParams> {
+    private static readonly pb::MessageParser<UniformParams> _parser = new pb::MessageParser<UniformParams>(() => new UniformParams());
+    public static pb::MessageParser<UniformParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public UniformParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public UniformParams(UniformParams other) : this() {
+      interarrivalLo_ = other.interarrivalLo_;
+      interarrivalHi_ = other.interarrivalHi_;
+    }
+
+    public UniformParams Clone() {
+      return new UniformParams(this);
+    }
+
+    public const int InterarrivalLoFieldNumber = 1;
+    private double interarrivalLo_;
+    public double InterarrivalLo {
+      get { return interarrivalLo_; }
+      set {
+        interarrivalLo_ = value;
+      }
+    }
+
+    public const int InterarrivalHiFieldNumber = 2;
+    private double interarrivalHi_;
+    public double InterarrivalHi {
+      get { return interarrivalHi_; }
+      set {
+        interarrivalHi_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as UniformParams);
+    }
+
+    public bool Equals(UniformParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (InterarrivalLo != other.InterarrivalLo) return false;
+      if (InterarrivalHi != other.InterarrivalHi) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (InterarrivalLo != 0D) hash ^= InterarrivalLo.GetHashCode();
+      if (InterarrivalHi != 0D) hash ^= InterarrivalHi.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (InterarrivalLo != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(InterarrivalLo);
+      }
+      if (InterarrivalHi != 0D) {
+        output.WriteRawTag(17);
+        output.WriteDouble(InterarrivalHi);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (InterarrivalLo != 0D) {
+        size += 1 + 8;
+      }
+      if (InterarrivalHi != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(UniformParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.InterarrivalLo != 0D) {
+        InterarrivalLo = other.InterarrivalLo;
+      }
+      if (other.InterarrivalHi != 0D) {
+        InterarrivalHi = other.InterarrivalHi;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 9: {
+            InterarrivalLo = input.ReadDouble();
+            break;
+          }
+          case 17: {
+            InterarrivalHi = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class DeterministicParams : pb::IMessage<DeterministicParams> {
+    private static readonly pb::MessageParser<DeterministicParams> _parser = new pb::MessageParser<DeterministicParams>(() => new DeterministicParams());
+    public static pb::MessageParser<DeterministicParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public DeterministicParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public DeterministicParams(DeterministicParams other) : this() {
+      offeredLoad_ = other.offeredLoad_;
+    }
+
+    public DeterministicParams Clone() {
+      return new DeterministicParams(this);
+    }
+
+    public const int OfferedLoadFieldNumber = 1;
+    private double offeredLoad_;
+    public double OfferedLoad {
+      get { return offeredLoad_; }
+      set {
+        offeredLoad_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as DeterministicParams);
+    }
+
+    public bool Equals(DeterministicParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (OfferedLoad != other.OfferedLoad) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (OfferedLoad != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(OfferedLoad);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (OfferedLoad != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(DeterministicParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.OfferedLoad != 0D) {
+        OfferedLoad = other.OfferedLoad;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 9: {
+            OfferedLoad = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ParetoParams : pb::IMessage<ParetoParams> {
+    private static readonly pb::MessageParser<ParetoParams> _parser = new pb::MessageParser<ParetoParams>(() => new ParetoParams());
+    public static pb::MessageParser<ParetoParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ParetoParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ParetoParams(ParetoParams other) : this() {
+      interarrivalBase_ = other.interarrivalBase_;
+      alpha_ = other.alpha_;
+    }
+
+    public ParetoParams Clone() {
+      return new ParetoParams(this);
+    }
+
+    public const int InterarrivalBaseFieldNumber = 1;
+    private double interarrivalBase_;
+    public double InterarrivalBase {
+      get { return interarrivalBase_; }
+      set {
+        interarrivalBase_ = value;
+      }
+    }
+
+    public const int AlphaFieldNumber = 2;
+    private double alpha_;
+    public double Alpha {
+      get { return alpha_; }
+      set {
+        alpha_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ParetoParams);
+    }
+
+    public bool Equals(ParetoParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (InterarrivalBase != other.InterarrivalBase) return false;
+      if (Alpha != other.Alpha) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (InterarrivalBase != 0D) hash ^= InterarrivalBase.GetHashCode();
+      if (Alpha != 0D) hash ^= Alpha.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (InterarrivalBase != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(InterarrivalBase);
+      }
+      if (Alpha != 0D) {
+        output.WriteRawTag(17);
+        output.WriteDouble(Alpha);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (InterarrivalBase != 0D) {
+        size += 1 + 8;
+      }
+      if (Alpha != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(ParetoParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.InterarrivalBase != 0D) {
+        InterarrivalBase = other.InterarrivalBase;
+      }
+      if (other.Alpha != 0D) {
+        Alpha = other.Alpha;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 9: {
+            InterarrivalBase = input.ReadDouble();
+            break;
+          }
+          case 17: {
+            Alpha = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ClosedLoopParams : pb::IMessage<ClosedLoopParams> {
+    private static readonly pb::MessageParser<ClosedLoopParams> _parser = new pb::MessageParser<ClosedLoopParams>(() => new ClosedLoopParams());
+    public static pb::MessageParser<ClosedLoopParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ClosedLoopParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ClosedLoopParams(ClosedLoopParams other) : this() {
+    }
+
+    public ClosedLoopParams Clone() {
+      return new ClosedLoopParams(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ClosedLoopParams);
+    }
+
+    public bool Equals(ClosedLoopParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(ClosedLoopParams other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class LoadParams : pb::IMessage<LoadParams> {
+    private static readonly pb::MessageParser<LoadParams> _parser = new pb::MessageParser<LoadParams>(() => new LoadParams());
+    public static pb::MessageParser<LoadParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public LoadParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public LoadParams(LoadParams other) : this() {
+      switch (other.LoadCase) {
+        case LoadOneofCase.ClosedLoop:
+          ClosedLoop = other.ClosedLoop.Clone();
+          break;
+        case LoadOneofCase.Poisson:
+          Poisson = other.Poisson.Clone();
+          break;
+        case LoadOneofCase.Uniform:
+          Uniform = other.Uniform.Clone();
+          break;
+        case LoadOneofCase.Determ:
+          Determ = other.Determ.Clone();
+          break;
+        case LoadOneofCase.Pareto:
+          Pareto = other.Pareto.Clone();
+          break;
+      }
+
+    }
+
+    public LoadParams Clone() {
+      return new LoadParams(this);
+    }
+
+    public const int ClosedLoopFieldNumber = 1;
+    public global::Grpc.Testing.ClosedLoopParams ClosedLoop {
+      get { return loadCase_ == LoadOneofCase.ClosedLoop ? (global::Grpc.Testing.ClosedLoopParams) load_ : null; }
+      set {
+        load_ = value;
+        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.ClosedLoop;
+      }
+    }
+
+    public const int PoissonFieldNumber = 2;
+    public global::Grpc.Testing.PoissonParams Poisson {
+      get { return loadCase_ == LoadOneofCase.Poisson ? (global::Grpc.Testing.PoissonParams) load_ : null; }
+      set {
+        load_ = value;
+        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Poisson;
+      }
+    }
+
+    public const int UniformFieldNumber = 3;
+    public global::Grpc.Testing.UniformParams Uniform {
+      get { return loadCase_ == LoadOneofCase.Uniform ? (global::Grpc.Testing.UniformParams) load_ : null; }
+      set {
+        load_ = value;
+        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Uniform;
+      }
+    }
+
+    public const int DetermFieldNumber = 4;
+    public global::Grpc.Testing.DeterministicParams Determ {
+      get { return loadCase_ == LoadOneofCase.Determ ? (global::Grpc.Testing.DeterministicParams) load_ : null; }
+      set {
+        load_ = value;
+        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Determ;
+      }
+    }
+
+    public const int ParetoFieldNumber = 5;
+    public global::Grpc.Testing.ParetoParams Pareto {
+      get { return loadCase_ == LoadOneofCase.Pareto ? (global::Grpc.Testing.ParetoParams) load_ : null; }
+      set {
+        load_ = value;
+        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Pareto;
+      }
+    }
+
+    private object load_;
+    public enum LoadOneofCase {
+      None = 0,
+      ClosedLoop = 1,
+      Poisson = 2,
+      Uniform = 3,
+      Determ = 4,
+      Pareto = 5,
+    }
+    private LoadOneofCase loadCase_ = LoadOneofCase.None;
+    public LoadOneofCase LoadCase {
+      get { return loadCase_; }
+    }
+
+    public void ClearLoad() {
+      loadCase_ = LoadOneofCase.None;
+      load_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as LoadParams);
+    }
+
+    public bool Equals(LoadParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false;
+      if (!object.Equals(Poisson, other.Poisson)) return false;
+      if (!object.Equals(Uniform, other.Uniform)) return false;
+      if (!object.Equals(Determ, other.Determ)) return false;
+      if (!object.Equals(Pareto, other.Pareto)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode();
+      if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode();
+      if (loadCase_ == LoadOneofCase.Uniform) hash ^= Uniform.GetHashCode();
+      if (loadCase_ == LoadOneofCase.Determ) hash ^= Determ.GetHashCode();
+      if (loadCase_ == LoadOneofCase.Pareto) hash ^= Pareto.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (loadCase_ == LoadOneofCase.ClosedLoop) {
+        output.WriteRawTag(10);
+        output.WriteMessage(ClosedLoop);
+      }
+      if (loadCase_ == LoadOneofCase.Poisson) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Poisson);
+      }
+      if (loadCase_ == LoadOneofCase.Uniform) {
+        output.WriteRawTag(26);
+        output.WriteMessage(Uniform);
+      }
+      if (loadCase_ == LoadOneofCase.Determ) {
+        output.WriteRawTag(34);
+        output.WriteMessage(Determ);
+      }
+      if (loadCase_ == LoadOneofCase.Pareto) {
+        output.WriteRawTag(42);
+        output.WriteMessage(Pareto);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (loadCase_ == LoadOneofCase.ClosedLoop) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClosedLoop);
+      }
+      if (loadCase_ == LoadOneofCase.Poisson) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson);
+      }
+      if (loadCase_ == LoadOneofCase.Uniform) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Uniform);
+      }
+      if (loadCase_ == LoadOneofCase.Determ) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Determ);
+      }
+      if (loadCase_ == LoadOneofCase.Pareto) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Pareto);
+      }
+      return size;
+    }
+
+    public void MergeFrom(LoadParams other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.LoadCase) {
+        case LoadOneofCase.ClosedLoop:
+          ClosedLoop = other.ClosedLoop;
+          break;
+        case LoadOneofCase.Poisson:
+          Poisson = other.Poisson;
+          break;
+        case LoadOneofCase.Uniform:
+          Uniform = other.Uniform;
+          break;
+        case LoadOneofCase.Determ:
+          Determ = other.Determ;
+          break;
+        case LoadOneofCase.Pareto:
+          Pareto = other.Pareto;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams();
+            if (loadCase_ == LoadOneofCase.ClosedLoop) {
+              subBuilder.MergeFrom(ClosedLoop);
+            }
+            input.ReadMessage(subBuilder);
+            ClosedLoop = subBuilder;
+            break;
+          }
+          case 18: {
+            global::Grpc.Testing.PoissonParams subBuilder = new global::Grpc.Testing.PoissonParams();
+            if (loadCase_ == LoadOneofCase.Poisson) {
+              subBuilder.MergeFrom(Poisson);
+            }
+            input.ReadMessage(subBuilder);
+            Poisson = subBuilder;
+            break;
+          }
+          case 26: {
+            global::Grpc.Testing.UniformParams subBuilder = new global::Grpc.Testing.UniformParams();
+            if (loadCase_ == LoadOneofCase.Uniform) {
+              subBuilder.MergeFrom(Uniform);
+            }
+            input.ReadMessage(subBuilder);
+            Uniform = subBuilder;
+            break;
+          }
+          case 34: {
+            global::Grpc.Testing.DeterministicParams subBuilder = new global::Grpc.Testing.DeterministicParams();
+            if (loadCase_ == LoadOneofCase.Determ) {
+              subBuilder.MergeFrom(Determ);
+            }
+            input.ReadMessage(subBuilder);
+            Determ = subBuilder;
+            break;
+          }
+          case 42: {
+            global::Grpc.Testing.ParetoParams subBuilder = new global::Grpc.Testing.ParetoParams();
+            if (loadCase_ == LoadOneofCase.Pareto) {
+              subBuilder.MergeFrom(Pareto);
+            }
+            input.ReadMessage(subBuilder);
+            Pareto = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class SecurityParams : pb::IMessage<SecurityParams> {
+    private static readonly pb::MessageParser<SecurityParams> _parser = new pb::MessageParser<SecurityParams>(() => new SecurityParams());
+    public static pb::MessageParser<SecurityParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public SecurityParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public SecurityParams(SecurityParams other) : this() {
+      useTestCa_ = other.useTestCa_;
+      serverHostOverride_ = other.serverHostOverride_;
+    }
+
+    public SecurityParams Clone() {
+      return new SecurityParams(this);
+    }
+
+    public const int UseTestCaFieldNumber = 1;
+    private bool useTestCa_;
+    public bool UseTestCa {
+      get { return useTestCa_; }
+      set {
+        useTestCa_ = value;
+      }
+    }
+
+    public const int ServerHostOverrideFieldNumber = 2;
+    private string serverHostOverride_ = "";
+    public string ServerHostOverride {
+      get { return serverHostOverride_; }
+      set {
+        serverHostOverride_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as SecurityParams);
+    }
+
+    public bool Equals(SecurityParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (UseTestCa != other.UseTestCa) return false;
+      if (ServerHostOverride != other.ServerHostOverride) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (UseTestCa != false) hash ^= UseTestCa.GetHashCode();
+      if (ServerHostOverride.Length != 0) hash ^= ServerHostOverride.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (UseTestCa != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(UseTestCa);
+      }
+      if (ServerHostOverride.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(ServerHostOverride);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (UseTestCa != false) {
+        size += 1 + 1;
+      }
+      if (ServerHostOverride.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(ServerHostOverride);
+      }
+      return size;
+    }
+
+    public void MergeFrom(SecurityParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.UseTestCa != false) {
+        UseTestCa = other.UseTestCa;
+      }
+      if (other.ServerHostOverride.Length != 0) {
+        ServerHostOverride = other.ServerHostOverride;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            UseTestCa = input.ReadBool();
+            break;
+          }
+          case 18: {
+            ServerHostOverride = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ClientConfig : pb::IMessage<ClientConfig> {
+    private static readonly pb::MessageParser<ClientConfig> _parser = new pb::MessageParser<ClientConfig>(() => new ClientConfig());
+    public static pb::MessageParser<ClientConfig> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[7]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ClientConfig() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ClientConfig(ClientConfig other) : this() {
+      serverTargets_ = other.serverTargets_.Clone();
+      clientType_ = other.clientType_;
+      SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
+      outstandingRpcsPerChannel_ = other.outstandingRpcsPerChannel_;
+      clientChannels_ = other.clientChannels_;
+      asyncClientThreads_ = other.asyncClientThreads_;
+      rpcType_ = other.rpcType_;
+      LoadParams = other.loadParams_ != null ? other.LoadParams.Clone() : null;
+      PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
+      HistogramParams = other.histogramParams_ != null ? other.HistogramParams.Clone() : null;
+    }
+
+    public ClientConfig Clone() {
+      return new ClientConfig(this);
+    }
+
+    public const int ServerTargetsFieldNumber = 1;
+    private static readonly pb::FieldCodec<string> _repeated_serverTargets_codec
+        = pb::FieldCodec.ForString(10);
+    private readonly pbc::RepeatedField<string> serverTargets_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> ServerTargets {
+      get { return serverTargets_; }
+    }
+
+    public const int ClientTypeFieldNumber = 2;
+    private global::Grpc.Testing.ClientType clientType_ = global::Grpc.Testing.ClientType.SYNC_CLIENT;
+    public global::Grpc.Testing.ClientType ClientType {
+      get { return clientType_; }
+      set {
+        clientType_ = value;
+      }
+    }
+
+    public const int SecurityParamsFieldNumber = 3;
+    private global::Grpc.Testing.SecurityParams securityParams_;
+    public global::Grpc.Testing.SecurityParams SecurityParams {
+      get { return securityParams_; }
+      set {
+        securityParams_ = value;
+      }
+    }
+
+    public const int OutstandingRpcsPerChannelFieldNumber = 4;
+    private int outstandingRpcsPerChannel_;
+    public int OutstandingRpcsPerChannel {
+      get { return outstandingRpcsPerChannel_; }
+      set {
+        outstandingRpcsPerChannel_ = value;
+      }
+    }
+
+    public const int ClientChannelsFieldNumber = 5;
+    private int clientChannels_;
+    public int ClientChannels {
+      get { return clientChannels_; }
+      set {
+        clientChannels_ = value;
+      }
+    }
+
+    public const int AsyncClientThreadsFieldNumber = 7;
+    private int asyncClientThreads_;
+    public int AsyncClientThreads {
+      get { return asyncClientThreads_; }
+      set {
+        asyncClientThreads_ = value;
+      }
+    }
+
+    public const int RpcTypeFieldNumber = 8;
+    private global::Grpc.Testing.RpcType rpcType_ = global::Grpc.Testing.RpcType.UNARY;
+    public global::Grpc.Testing.RpcType RpcType {
+      get { return rpcType_; }
+      set {
+        rpcType_ = value;
+      }
+    }
+
+    public const int LoadParamsFieldNumber = 10;
+    private global::Grpc.Testing.LoadParams loadParams_;
+    public global::Grpc.Testing.LoadParams LoadParams {
+      get { return loadParams_; }
+      set {
+        loadParams_ = value;
+      }
+    }
+
+    public const int PayloadConfigFieldNumber = 11;
+    private global::Grpc.Testing.PayloadConfig payloadConfig_;
+    public global::Grpc.Testing.PayloadConfig PayloadConfig {
+      get { return payloadConfig_; }
+      set {
+        payloadConfig_ = value;
+      }
+    }
+
+    public const int HistogramParamsFieldNumber = 12;
+    private global::Grpc.Testing.HistogramParams histogramParams_;
+    public global::Grpc.Testing.HistogramParams HistogramParams {
+      get { return histogramParams_; }
+      set {
+        histogramParams_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ClientConfig);
+    }
+
+    public bool Equals(ClientConfig other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!serverTargets_.Equals(other.serverTargets_)) return false;
+      if (ClientType != other.ClientType) return false;
+      if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
+      if (OutstandingRpcsPerChannel != other.OutstandingRpcsPerChannel) return false;
+      if (ClientChannels != other.ClientChannels) return false;
+      if (AsyncClientThreads != other.AsyncClientThreads) return false;
+      if (RpcType != other.RpcType) return false;
+      if (!object.Equals(LoadParams, other.LoadParams)) return false;
+      if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
+      if (!object.Equals(HistogramParams, other.HistogramParams)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= serverTargets_.GetHashCode();
+      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) hash ^= ClientType.GetHashCode();
+      if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
+      if (OutstandingRpcsPerChannel != 0) hash ^= OutstandingRpcsPerChannel.GetHashCode();
+      if (ClientChannels != 0) hash ^= ClientChannels.GetHashCode();
+      if (AsyncClientThreads != 0) hash ^= AsyncClientThreads.GetHashCode();
+      if (RpcType != global::Grpc.Testing.RpcType.UNARY) hash ^= RpcType.GetHashCode();
+      if (loadParams_ != null) hash ^= LoadParams.GetHashCode();
+      if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
+      if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      serverTargets_.WriteTo(output, _repeated_serverTargets_codec);
+      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+        output.WriteRawTag(16);
+        output.WriteEnum((int) ClientType);
+      }
+      if (securityParams_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(SecurityParams);
+      }
+      if (OutstandingRpcsPerChannel != 0) {
+        output.WriteRawTag(32);
+        output.WriteInt32(OutstandingRpcsPerChannel);
+      }
+      if (ClientChannels != 0) {
+        output.WriteRawTag(40);
+        output.WriteInt32(ClientChannels);
+      }
+      if (AsyncClientThreads != 0) {
+        output.WriteRawTag(56);
+        output.WriteInt32(AsyncClientThreads);
+      }
+      if (RpcType != global::Grpc.Testing.RpcType.UNARY) {
+        output.WriteRawTag(64);
+        output.WriteEnum((int) RpcType);
+      }
+      if (loadParams_ != null) {
+        output.WriteRawTag(82);
+        output.WriteMessage(LoadParams);
+      }
+      if (payloadConfig_ != null) {
+        output.WriteRawTag(90);
+        output.WriteMessage(PayloadConfig);
+      }
+      if (histogramParams_ != null) {
+        output.WriteRawTag(98);
+        output.WriteMessage(HistogramParams);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += serverTargets_.CalculateSize(_repeated_serverTargets_codec);
+      if (ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ClientType);
+      }
+      if (securityParams_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
+      }
+      if (OutstandingRpcsPerChannel != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OutstandingRpcsPerChannel);
+      }
+      if (ClientChannels != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientChannels);
+      }
+      if (AsyncClientThreads != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncClientThreads);
+      }
+      if (RpcType != global::Grpc.Testing.RpcType.UNARY) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RpcType);
+      }
+      if (loadParams_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(LoadParams);
+      }
+      if (payloadConfig_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
+      }
+      if (histogramParams_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(HistogramParams);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ClientConfig other) {
+      if (other == null) {
+        return;
+      }
+      serverTargets_.Add(other.serverTargets_);
+      if (other.ClientType != global::Grpc.Testing.ClientType.SYNC_CLIENT) {
+        ClientType = other.ClientType;
+      }
+      if (other.securityParams_ != null) {
+        if (securityParams_ == null) {
+          securityParams_ = new global::Grpc.Testing.SecurityParams();
+        }
+        SecurityParams.MergeFrom(other.SecurityParams);
+      }
+      if (other.OutstandingRpcsPerChannel != 0) {
+        OutstandingRpcsPerChannel = other.OutstandingRpcsPerChannel;
+      }
+      if (other.ClientChannels != 0) {
+        ClientChannels = other.ClientChannels;
+      }
+      if (other.AsyncClientThreads != 0) {
+        AsyncClientThreads = other.AsyncClientThreads;
+      }
+      if (other.RpcType != global::Grpc.Testing.RpcType.UNARY) {
+        RpcType = other.RpcType;
+      }
+      if (other.loadParams_ != null) {
+        if (loadParams_ == null) {
+          loadParams_ = new global::Grpc.Testing.LoadParams();
+        }
+        LoadParams.MergeFrom(other.LoadParams);
+      }
+      if (other.payloadConfig_ != null) {
+        if (payloadConfig_ == null) {
+          payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
+        }
+        PayloadConfig.MergeFrom(other.PayloadConfig);
+      }
+      if (other.histogramParams_ != null) {
+        if (histogramParams_ == null) {
+          histogramParams_ = new global::Grpc.Testing.HistogramParams();
+        }
+        HistogramParams.MergeFrom(other.HistogramParams);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            serverTargets_.AddEntriesFrom(input, _repeated_serverTargets_codec);
+            break;
+          }
+          case 16: {
+            clientType_ = (global::Grpc.Testing.ClientType) input.ReadEnum();
+            break;
+          }
+          case 26: {
+            if (securityParams_ == null) {
+              securityParams_ = new global::Grpc.Testing.SecurityParams();
+            }
+            input.ReadMessage(securityParams_);
+            break;
+          }
+          case 32: {
+            OutstandingRpcsPerChannel = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            ClientChannels = input.ReadInt32();
+            break;
+          }
+          case 56: {
+            AsyncClientThreads = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            rpcType_ = (global::Grpc.Testing.RpcType) input.ReadEnum();
+            break;
+          }
+          case 82: {
+            if (loadParams_ == null) {
+              loadParams_ = new global::Grpc.Testing.LoadParams();
+            }
+            input.ReadMessage(loadParams_);
+            break;
+          }
+          case 90: {
+            if (payloadConfig_ == null) {
+              payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
+            }
+            input.ReadMessage(payloadConfig_);
+            break;
+          }
+          case 98: {
+            if (histogramParams_ == null) {
+              histogramParams_ = new global::Grpc.Testing.HistogramParams();
+            }
+            input.ReadMessage(histogramParams_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ClientStatus : pb::IMessage<ClientStatus> {
+    private static readonly pb::MessageParser<ClientStatus> _parser = new pb::MessageParser<ClientStatus>(() => new ClientStatus());
+    public static pb::MessageParser<ClientStatus> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[8]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ClientStatus() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ClientStatus(ClientStatus other) : this() {
+      Stats = other.stats_ != null ? other.Stats.Clone() : null;
+    }
+
+    public ClientStatus Clone() {
+      return new ClientStatus(this);
+    }
+
+    public const int StatsFieldNumber = 1;
+    private global::Grpc.Testing.ClientStats stats_;
+    public global::Grpc.Testing.ClientStats Stats {
+      get { return stats_; }
+      set {
+        stats_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ClientStatus);
+    }
+
+    public bool Equals(ClientStatus other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Stats, other.Stats)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (stats_ != null) hash ^= Stats.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (stats_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Stats);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (stats_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ClientStatus other) {
+      if (other == null) {
+        return;
+      }
+      if (other.stats_ != null) {
+        if (stats_ == null) {
+          stats_ = new global::Grpc.Testing.ClientStats();
+        }
+        Stats.MergeFrom(other.Stats);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (stats_ == null) {
+              stats_ = new global::Grpc.Testing.ClientStats();
+            }
+            input.ReadMessage(stats_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Mark : pb::IMessage<Mark> {
+    private static readonly pb::MessageParser<Mark> _parser = new pb::MessageParser<Mark>(() => new Mark());
+    public static pb::MessageParser<Mark> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[9]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Mark() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Mark(Mark other) : this() {
+      reset_ = other.reset_;
+    }
+
+    public Mark Clone() {
+      return new Mark(this);
+    }
+
+    public const int ResetFieldNumber = 1;
+    private bool reset_;
+    public bool Reset {
+      get { return reset_; }
+      set {
+        reset_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Mark);
+    }
+
+    public bool Equals(Mark other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Reset != other.Reset) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Reset != false) hash ^= Reset.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Reset != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(Reset);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Reset != false) {
+        size += 1 + 1;
+      }
+      return size;
+    }
+
+    public void MergeFrom(Mark other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Reset != false) {
+        Reset = other.Reset;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Reset = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ClientArgs : pb::IMessage<ClientArgs> {
+    private static readonly pb::MessageParser<ClientArgs> _parser = new pb::MessageParser<ClientArgs>(() => new ClientArgs());
+    public static pb::MessageParser<ClientArgs> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[10]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ClientArgs() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ClientArgs(ClientArgs other) : this() {
+      switch (other.ArgtypeCase) {
+        case ArgtypeOneofCase.Setup:
+          Setup = other.Setup.Clone();
+          break;
+        case ArgtypeOneofCase.Mark:
+          Mark = other.Mark.Clone();
+          break;
+      }
+
+    }
+
+    public ClientArgs Clone() {
+      return new ClientArgs(this);
+    }
+
+    public const int SetupFieldNumber = 1;
+    public global::Grpc.Testing.ClientConfig Setup {
+      get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ClientConfig) argtype_ : null; }
+      set {
+        argtype_ = value;
+        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup;
+      }
+    }
+
+    public const int MarkFieldNumber = 2;
+    public global::Grpc.Testing.Mark Mark {
+      get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; }
+      set {
+        argtype_ = value;
+        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark;
+      }
+    }
+
+    private object argtype_;
+    public enum ArgtypeOneofCase {
+      None = 0,
+      Setup = 1,
+      Mark = 2,
+    }
+    private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
+    public ArgtypeOneofCase ArgtypeCase {
+      get { return argtypeCase_; }
+    }
+
+    public void ClearArgtype() {
+      argtypeCase_ = ArgtypeOneofCase.None;
+      argtype_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ClientArgs);
+    }
+
+    public bool Equals(ClientArgs other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Setup, other.Setup)) return false;
+      if (!object.Equals(Mark, other.Mark)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
+      if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Setup);
+      }
+      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Mark);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup);
+      }
+      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ClientArgs other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.ArgtypeCase) {
+        case ArgtypeOneofCase.Setup:
+          Setup = other.Setup;
+          break;
+        case ArgtypeOneofCase.Mark:
+          Mark = other.Mark;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig();
+            if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+              subBuilder.MergeFrom(Setup);
+            }
+            input.ReadMessage(subBuilder);
+            Setup = subBuilder;
+            break;
+          }
+          case 18: {
+            global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark();
+            if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+              subBuilder.MergeFrom(Mark);
+            }
+            input.ReadMessage(subBuilder);
+            Mark = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ServerConfig : pb::IMessage<ServerConfig> {
+    private static readonly pb::MessageParser<ServerConfig> _parser = new pb::MessageParser<ServerConfig>(() => new ServerConfig());
+    public static pb::MessageParser<ServerConfig> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[11]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ServerConfig() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ServerConfig(ServerConfig other) : this() {
+      serverType_ = other.serverType_;
+      SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
+      host_ = other.host_;
+      port_ = other.port_;
+      asyncServerThreads_ = other.asyncServerThreads_;
+      coreLimit_ = other.coreLimit_;
+      PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
+    }
+
+    public ServerConfig Clone() {
+      return new ServerConfig(this);
+    }
+
+    public const int ServerTypeFieldNumber = 1;
+    private global::Grpc.Testing.ServerType serverType_ = global::Grpc.Testing.ServerType.SYNC_SERVER;
+    public global::Grpc.Testing.ServerType ServerType {
+      get { return serverType_; }
+      set {
+        serverType_ = value;
+      }
+    }
+
+    public const int SecurityParamsFieldNumber = 2;
+    private global::Grpc.Testing.SecurityParams securityParams_;
+    public global::Grpc.Testing.SecurityParams SecurityParams {
+      get { return securityParams_; }
+      set {
+        securityParams_ = value;
+      }
+    }
+
+    public const int HostFieldNumber = 3;
+    private string host_ = "";
+    public string Host {
+      get { return host_; }
+      set {
+        host_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int PortFieldNumber = 4;
+    private int port_;
+    public int Port {
+      get { return port_; }
+      set {
+        port_ = value;
+      }
+    }
+
+    public const int AsyncServerThreadsFieldNumber = 7;
+    private int asyncServerThreads_;
+    public int AsyncServerThreads {
+      get { return asyncServerThreads_; }
+      set {
+        asyncServerThreads_ = value;
+      }
+    }
+
+    public const int CoreLimitFieldNumber = 8;
+    private int coreLimit_;
+    public int CoreLimit {
+      get { return coreLimit_; }
+      set {
+        coreLimit_ = value;
+      }
+    }
+
+    public const int PayloadConfigFieldNumber = 9;
+    private global::Grpc.Testing.PayloadConfig payloadConfig_;
+    public global::Grpc.Testing.PayloadConfig PayloadConfig {
+      get { return payloadConfig_; }
+      set {
+        payloadConfig_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ServerConfig);
+    }
+
+    public bool Equals(ServerConfig other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (ServerType != other.ServerType) return false;
+      if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
+      if (Host != other.Host) return false;
+      if (Port != other.Port) return false;
+      if (AsyncServerThreads != other.AsyncServerThreads) return false;
+      if (CoreLimit != other.CoreLimit) return false;
+      if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) hash ^= ServerType.GetHashCode();
+      if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
+      if (Host.Length != 0) hash ^= Host.GetHashCode();
+      if (Port != 0) hash ^= Port.GetHashCode();
+      if (AsyncServerThreads != 0) hash ^= AsyncServerThreads.GetHashCode();
+      if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
+      if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) ServerType);
+      }
+      if (securityParams_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(SecurityParams);
+      }
+      if (Host.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(Host);
+      }
+      if (Port != 0) {
+        output.WriteRawTag(32);
+        output.WriteInt32(Port);
+      }
+      if (AsyncServerThreads != 0) {
+        output.WriteRawTag(56);
+        output.WriteInt32(AsyncServerThreads);
+      }
+      if (CoreLimit != 0) {
+        output.WriteRawTag(64);
+        output.WriteInt32(CoreLimit);
+      }
+      if (payloadConfig_ != null) {
+        output.WriteRawTag(74);
+        output.WriteMessage(PayloadConfig);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerType);
+      }
+      if (securityParams_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
+      }
+      if (Host.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Host);
+      }
+      if (Port != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
+      }
+      if (AsyncServerThreads != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncServerThreads);
+      }
+      if (CoreLimit != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
+      }
+      if (payloadConfig_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ServerConfig other) {
+      if (other == null) {
+        return;
+      }
+      if (other.ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) {
+        ServerType = other.ServerType;
+      }
+      if (other.securityParams_ != null) {
+        if (securityParams_ == null) {
+          securityParams_ = new global::Grpc.Testing.SecurityParams();
+        }
+        SecurityParams.MergeFrom(other.SecurityParams);
+      }
+      if (other.Host.Length != 0) {
+        Host = other.Host;
+      }
+      if (other.Port != 0) {
+        Port = other.Port;
+      }
+      if (other.AsyncServerThreads != 0) {
+        AsyncServerThreads = other.AsyncServerThreads;
+      }
+      if (other.CoreLimit != 0) {
+        CoreLimit = other.CoreLimit;
+      }
+      if (other.payloadConfig_ != null) {
+        if (payloadConfig_ == null) {
+          payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
+        }
+        PayloadConfig.MergeFrom(other.PayloadConfig);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            serverType_ = (global::Grpc.Testing.ServerType) input.ReadEnum();
+            break;
+          }
+          case 18: {
+            if (securityParams_ == null) {
+              securityParams_ = new global::Grpc.Testing.SecurityParams();
+            }
+            input.ReadMessage(securityParams_);
+            break;
+          }
+          case 26: {
+            Host = input.ReadString();
+            break;
+          }
+          case 32: {
+            Port = input.ReadInt32();
+            break;
+          }
+          case 56: {
+            AsyncServerThreads = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            CoreLimit = input.ReadInt32();
+            break;
+          }
+          case 74: {
+            if (payloadConfig_ == null) {
+              payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
+            }
+            input.ReadMessage(payloadConfig_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ServerArgs : pb::IMessage<ServerArgs> {
+    private static readonly pb::MessageParser<ServerArgs> _parser = new pb::MessageParser<ServerArgs>(() => new ServerArgs());
+    public static pb::MessageParser<ServerArgs> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[12]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ServerArgs() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ServerArgs(ServerArgs other) : this() {
+      switch (other.ArgtypeCase) {
+        case ArgtypeOneofCase.Setup:
+          Setup = other.Setup.Clone();
+          break;
+        case ArgtypeOneofCase.Mark:
+          Mark = other.Mark.Clone();
+          break;
+      }
+
+    }
+
+    public ServerArgs Clone() {
+      return new ServerArgs(this);
+    }
+
+    public const int SetupFieldNumber = 1;
+    public global::Grpc.Testing.ServerConfig Setup {
+      get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ServerConfig) argtype_ : null; }
+      set {
+        argtype_ = value;
+        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup;
+      }
+    }
+
+    public const int MarkFieldNumber = 2;
+    public global::Grpc.Testing.Mark Mark {
+      get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; }
+      set {
+        argtype_ = value;
+        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark;
+      }
+    }
+
+    private object argtype_;
+    public enum ArgtypeOneofCase {
+      None = 0,
+      Setup = 1,
+      Mark = 2,
+    }
+    private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
+    public ArgtypeOneofCase ArgtypeCase {
+      get { return argtypeCase_; }
+    }
+
+    public void ClearArgtype() {
+      argtypeCase_ = ArgtypeOneofCase.None;
+      argtype_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ServerArgs);
+    }
+
+    public bool Equals(ServerArgs other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Setup, other.Setup)) return false;
+      if (!object.Equals(Mark, other.Mark)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
+      if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Setup);
+      }
+      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Mark);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup);
+      }
+      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ServerArgs other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.ArgtypeCase) {
+        case ArgtypeOneofCase.Setup:
+          Setup = other.Setup;
+          break;
+        case ArgtypeOneofCase.Mark:
+          Mark = other.Mark;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig();
+            if (argtypeCase_ == ArgtypeOneofCase.Setup) {
+              subBuilder.MergeFrom(Setup);
+            }
+            input.ReadMessage(subBuilder);
+            Setup = subBuilder;
+            break;
+          }
+          case 18: {
+            global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark();
+            if (argtypeCase_ == ArgtypeOneofCase.Mark) {
+              subBuilder.MergeFrom(Mark);
+            }
+            input.ReadMessage(subBuilder);
+            Mark = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ServerStatus : pb::IMessage<ServerStatus> {
+    private static readonly pb::MessageParser<ServerStatus> _parser = new pb::MessageParser<ServerStatus>(() => new ServerStatus());
+    public static pb::MessageParser<ServerStatus> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Control.Descriptor.MessageTypes[13]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ServerStatus() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ServerStatus(ServerStatus other) : this() {
+      Stats = other.stats_ != null ? other.Stats.Clone() : null;
+      port_ = other.port_;
+      cores_ = other.cores_;
+    }
+
+    public ServerStatus Clone() {
+      return new ServerStatus(this);
+    }
+
+    public const int StatsFieldNumber = 1;
+    private global::Grpc.Testing.ServerStats stats_;
+    public global::Grpc.Testing.ServerStats Stats {
+      get { return stats_; }
+      set {
+        stats_ = value;
+      }
+    }
+
+    public const int PortFieldNumber = 2;
+    private int port_;
+    public int Port {
+      get { return port_; }
+      set {
+        port_ = value;
+      }
+    }
+
+    public const int CoresFieldNumber = 3;
+    private int cores_;
+    public int Cores {
+      get { return cores_; }
+      set {
+        cores_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ServerStatus);
+    }
+
+    public bool Equals(ServerStatus other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Stats, other.Stats)) return false;
+      if (Port != other.Port) return false;
+      if (Cores != other.Cores) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (stats_ != null) hash ^= Stats.GetHashCode();
+      if (Port != 0) hash ^= Port.GetHashCode();
+      if (Cores != 0) hash ^= Cores.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (stats_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Stats);
+      }
+      if (Port != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Port);
+      }
+      if (Cores != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Cores);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (stats_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
+      }
+      if (Port != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
+      }
+      if (Cores != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ServerStatus other) {
+      if (other == null) {
+        return;
+      }
+      if (other.stats_ != null) {
+        if (stats_ == null) {
+          stats_ = new global::Grpc.Testing.ServerStats();
+        }
+        Stats.MergeFrom(other.Stats);
+      }
+      if (other.Port != 0) {
+        Port = other.Port;
+      }
+      if (other.Cores != 0) {
+        Cores = other.Cores;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (stats_ == null) {
+              stats_ = new global::Grpc.Testing.ServerStats();
+            }
+            input.ReadMessage(stats_);
+            break;
+          }
+          case 16: {
+            Port = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Cores = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 2b7530573103cc7b64f65653c8010ced96ee284a..012de45524d014d3a9bc9323c60f9092eb20e227 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -38,55 +38,46 @@
     <AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
-    </Reference>
     <Reference Include="CommandLine">
       <HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Auth, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="nunit.framework">
+      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Interactive.Async">
+      <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Net" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Net.Http.WebRequest" />
+    <Reference Include="BouncyCastle.Crypto">
+      <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
+    </Reference>
+    <Reference Include="Google.Apis.Auth">
       <HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.9.3.19383, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="Google.Apis.Auth.PlatformServices">
       <HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Apis.Core, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="Google.Apis.Core">
       <HintPath>..\packages\Google.Apis.Core.1.9.3\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
     </Reference>
-    <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="Google.Protobuf">
       <HintPath>..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
     </Reference>
-    <Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="Microsoft.Threading.Tasks">
       <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
     </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="Microsoft.Threading.Tasks.Extensions">
       <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
     </Reference>
-    <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
       <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
     </Reference>
-    <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
+    <Reference Include="Newtonsoft.Json">
       <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
-    <Reference Include="nunit.framework">
-      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.Interactive.Async">
-      <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Net" />
-    <Reference Include="System.Net.Http" />
-    <Reference Include="System.Net.Http.WebRequest" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="..\Grpc.Core\Version.cs">
@@ -104,6 +95,22 @@
     <Compile Include="TestGrpc.cs" />
     <Compile Include="SslCredentialsTest.cs" />
     <Compile Include="Test.cs" />
+    <Compile Include="IClientRunner.cs" />
+    <Compile Include="ClientRunners.cs" />
+    <Compile Include="IServerRunner.cs" />
+    <Compile Include="ServerRunners.cs" />
+    <Compile Include="RunnerClientServerTest.cs" />
+    <Compile Include="Control.cs" />
+    <Compile Include="Payloads.cs" />
+    <Compile Include="Services.cs" />
+    <Compile Include="ServicesGrpc.cs" />
+    <Compile Include="Stats.cs" />
+    <Compile Include="BenchmarkServiceImpl.cs" />
+    <Compile Include="Histogram.cs" />
+    <Compile Include="HistogramTest.cs" />
+    <Compile Include="WorkerServiceImpl.cs" />
+    <Compile Include="QpsWorker.cs" />
+    <Compile Include="WallClockStopwatch.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting/Histogram.cs b/src/csharp/Grpc.IntegrationTesting/Histogram.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7e7cb2c4de0d59fe6a971d0320072afa7504f4fe
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Histogram.cs
@@ -0,0 +1,153 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Basic implementation of histogram based on grpc/support/histogram.h.
+    /// </summary>
+    public class Histogram
+    {
+        readonly object myLock = new object();
+        readonly double multiplier;
+        readonly double oneOnLogMultiplier;
+        readonly double maxPossible;
+        readonly uint[] buckets;
+
+        int count;
+        double sum;
+        double sumOfSquares;
+        double min;
+        double max;
+
+        public Histogram(double resolution, double maxPossible)
+        {
+            Grpc.Core.Utils.Preconditions.CheckArgument(resolution > 0);
+            Grpc.Core.Utils.Preconditions.CheckArgument(maxPossible > 0);
+            this.maxPossible = maxPossible;
+            this.multiplier = 1.0 + resolution;
+            this.oneOnLogMultiplier = 1.0 / Math.Log(1.0 + resolution);
+            this.buckets = new uint[FindBucket(maxPossible) + 1];
+
+            ResetUnsafe();
+        }
+
+        public void AddObservation(double value)
+        {
+            lock (myLock)
+            {
+                AddObservationUnsafe(value);    
+            }
+        }
+
+
+        /// <summary>
+        /// Gets snapshot of stats and reset 
+        /// </summary>
+        public HistogramData GetSnapshot(bool reset = false)
+        {
+            lock (myLock)
+            {
+                return GetSnapshotUnsafe(reset);    
+            }
+        }
+
+        /// <summary>
+        /// Finds bucket index to which given observation should go.
+        /// </summary>
+        private int FindBucket(double value)
+        {
+            value = Math.Max(value, 1.0);
+            value = Math.Min(value, this.maxPossible);
+            return (int)(Math.Log(value) * oneOnLogMultiplier);
+        }
+
+        private void AddObservationUnsafe(double value)
+        {
+            this.count++;
+            this.sum += value;
+            this.sumOfSquares += value * value;
+            this.min = Math.Min(this.min, value);
+            this.max = Math.Max(this.max, value);
+
+            this.buckets[FindBucket(value)]++;
+        }
+
+        private HistogramData GetSnapshotUnsafe(bool reset)
+        {
+            var data = new HistogramData
+            {
+                Count = count,
+                Sum = sum,
+                SumOfSquares = sumOfSquares,
+                MinSeen = min,
+                MaxSeen = max,
+                Bucket = { buckets }
+            };
+
+            if (reset)
+            {
+                ResetUnsafe();
+            }
+
+            return data;
+        }
+
+        private void ResetUnsafe()
+        {
+            this.count = 0;
+            this.sum = 0;
+            this.sumOfSquares = 0;
+            this.min = double.PositiveInfinity;
+            this.max = double.NegativeInfinity;
+            for (int i = 0; i < this.buckets.Length; i++)
+            {
+                this.buckets[i] = 0;
+            }
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs b/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fa160cbd15b2161c9ce58ca4161fb206dc6057da
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs
@@ -0,0 +1,104 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+    public class HistogramTest
+    {
+        [Test]
+        public void Simple()
+        {
+            var hist = new Histogram(0.01, 60e9);
+            hist.AddObservation(10000);
+            hist.AddObservation(10000);
+            hist.AddObservation(11000);
+            hist.AddObservation(11000);
+
+            var data = hist.GetSnapshot();
+
+            Assert.AreEqual(4, data.Count);
+            Assert.AreEqual(42000.0, data.Sum, 1e-6);
+            Assert.AreEqual(10000, data.MinSeen);
+            Assert.AreEqual(11000, data.MaxSeen);
+            Assert.AreEqual(2.0*10000*10000 + 2.0*11000*11000, data.SumOfSquares, 1e-6);
+
+            // 1.01^925 < 10000 < 1.01^926
+            Assert.AreEqual(2, data.Bucket[925]);
+            Assert.AreEqual(2, data.Bucket[935]);
+        }
+
+        [Test]
+        public void ExtremeObservations()
+        {
+            var hist = new Histogram(0.01, 60e9);
+            hist.AddObservation(-0.5);  // should be in the first bucket
+            hist.AddObservation(1e12);  // should be in the last bucket 
+
+            var data = hist.GetSnapshot();
+            Assert.AreEqual(1, data.Bucket[0]);
+            Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]);
+        }
+
+        [Test]
+        public void Reset()
+        {
+            var hist = new Histogram(0.01, 60e9);
+            hist.AddObservation(10000);
+            hist.AddObservation(11000);
+
+            var data = hist.GetSnapshot(true);  // snapshot contains data before reset
+            Assert.AreEqual(2, data.Count);
+            Assert.AreEqual(10000, data.MinSeen);
+            Assert.AreEqual(11000, data.MaxSeen);
+
+            data = hist.GetSnapshot();  // snapshot contains state after reset
+            Assert.AreEqual(0, data.Count);
+            Assert.AreEqual(double.PositiveInfinity, data.MinSeen);
+            Assert.AreEqual(double.NegativeInfinity, data.MaxSeen);
+            Assert.AreEqual(0, data.Sum);
+            Assert.AreEqual(0, data.SumOfSquares);
+            CollectionAssert.AreEqual(new uint[data.Bucket.Count], data.Bucket); 
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs b/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs
new file mode 100644
index 0000000000000000000000000000000000000000..39b94f1e6d1b9e020879562ff11ee6494b13acc0
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs
@@ -0,0 +1,67 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Abstract client runner.
+    /// </summary>
+    public interface IClientRunner
+    {
+        /// <summary>
+        /// Gets stats snapshot.
+        /// </summary>
+        /// <returns>The stats.</returns>
+        ClientStats GetStats(bool reset);
+
+        /// <summary>
+        /// Asynchronously stops the client.
+        /// </summary>
+        /// <returns>Task that finishes when client has come to a full stop.</returns>
+        Task StopAsync();
+    }
+        
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs b/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs
new file mode 100644
index 0000000000000000000000000000000000000000..53a62fbf1cc4923e50bc2d3a7a32e60da0fb3dd9
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs
@@ -0,0 +1,72 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Abstract server runner.
+    /// </summary>
+    public interface IServerRunner
+    {
+        /// <summary>
+        /// Port on which the server is listening.
+        /// </summary>
+        int BoundPort { get; }
+        
+        /// <summary>
+        /// Gets server stats.
+        /// </summary>
+        /// <returns>The stats.</returns>
+        ServerStats GetStats(bool reset);
+
+        /// <summary>
+        /// Asynchronously stops the server.
+        /// </summary>
+        /// <returns>Task that finishes when server has shutdown.</returns>
+        Task StopAsync();
+    }
+        
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Payloads.cs b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a37dd9a685cf46583e1f79986ea8c6ce4013c6b4
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
@@ -0,0 +1,580 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: test/proto/benchmarks/payloads.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class Payloads {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static Payloads() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiR0ZXN0L3Byb3RvL2JlbmNobWFya3MvcGF5bG9hZHMucHJvdG8SDGdycGMu", 
+            "dGVzdGluZyI3ChBCeXRlQnVmZmVyUGFyYW1zEhAKCHJlcV9zaXplGAEgASgF", 
+            "EhEKCXJlc3Bfc2l6ZRgCIAEoBSI4ChFTaW1wbGVQcm90b1BhcmFtcxIQCghy", 
+            "ZXFfc2l6ZRgBIAEoBRIRCglyZXNwX3NpemUYAiABKAUiFAoSQ29tcGxleFBy", 
+            "b3RvUGFyYW1zIsoBCg1QYXlsb2FkQ29uZmlnEjgKDmJ5dGVidWZfcGFyYW1z", 
+            "GAEgASgLMh4uZ3JwYy50ZXN0aW5nLkJ5dGVCdWZmZXJQYXJhbXNIABI4Cg1z", 
+            "aW1wbGVfcGFyYW1zGAIgASgLMh8uZ3JwYy50ZXN0aW5nLlNpbXBsZVByb3Rv", 
+            "UGFyYW1zSAASOgoOY29tcGxleF9wYXJhbXMYAyABKAsyIC5ncnBjLnRlc3Rp", 
+            "bmcuQ29tcGxleFByb3RvUGFyYW1zSABCCQoHcGF5bG9hZGIGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ByteBufferParams), new[]{ "ReqSize", "RespSize" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleProtoParams), new[]{ "ReqSize", "RespSize" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ComplexProtoParams), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PayloadConfig), new[]{ "BytebufParams", "SimpleParams", "ComplexParams" }, new[]{ "Payload" }, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ByteBufferParams : pb::IMessage<ByteBufferParams> {
+    private static readonly pb::MessageParser<ByteBufferParams> _parser = new pb::MessageParser<ByteBufferParams>(() => new ByteBufferParams());
+    public static pb::MessageParser<ByteBufferParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ByteBufferParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ByteBufferParams(ByteBufferParams other) : this() {
+      reqSize_ = other.reqSize_;
+      respSize_ = other.respSize_;
+    }
+
+    public ByteBufferParams Clone() {
+      return new ByteBufferParams(this);
+    }
+
+    public const int ReqSizeFieldNumber = 1;
+    private int reqSize_;
+    public int ReqSize {
+      get { return reqSize_; }
+      set {
+        reqSize_ = value;
+      }
+    }
+
+    public const int RespSizeFieldNumber = 2;
+    private int respSize_;
+    public int RespSize {
+      get { return respSize_; }
+      set {
+        respSize_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ByteBufferParams);
+    }
+
+    public bool Equals(ByteBufferParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (ReqSize != other.ReqSize) return false;
+      if (RespSize != other.RespSize) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
+      if (RespSize != 0) hash ^= RespSize.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (ReqSize != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(ReqSize);
+      }
+      if (RespSize != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(RespSize);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (ReqSize != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize);
+      }
+      if (RespSize != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ByteBufferParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.ReqSize != 0) {
+        ReqSize = other.ReqSize;
+      }
+      if (other.RespSize != 0) {
+        RespSize = other.RespSize;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            ReqSize = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            RespSize = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class SimpleProtoParams : pb::IMessage<SimpleProtoParams> {
+    private static readonly pb::MessageParser<SimpleProtoParams> _parser = new pb::MessageParser<SimpleProtoParams>(() => new SimpleProtoParams());
+    public static pb::MessageParser<SimpleProtoParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public SimpleProtoParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public SimpleProtoParams(SimpleProtoParams other) : this() {
+      reqSize_ = other.reqSize_;
+      respSize_ = other.respSize_;
+    }
+
+    public SimpleProtoParams Clone() {
+      return new SimpleProtoParams(this);
+    }
+
+    public const int ReqSizeFieldNumber = 1;
+    private int reqSize_;
+    public int ReqSize {
+      get { return reqSize_; }
+      set {
+        reqSize_ = value;
+      }
+    }
+
+    public const int RespSizeFieldNumber = 2;
+    private int respSize_;
+    public int RespSize {
+      get { return respSize_; }
+      set {
+        respSize_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as SimpleProtoParams);
+    }
+
+    public bool Equals(SimpleProtoParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (ReqSize != other.ReqSize) return false;
+      if (RespSize != other.RespSize) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
+      if (RespSize != 0) hash ^= RespSize.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (ReqSize != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(ReqSize);
+      }
+      if (RespSize != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(RespSize);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (ReqSize != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize);
+      }
+      if (RespSize != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
+      }
+      return size;
+    }
+
+    public void MergeFrom(SimpleProtoParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.ReqSize != 0) {
+        ReqSize = other.ReqSize;
+      }
+      if (other.RespSize != 0) {
+        RespSize = other.RespSize;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            ReqSize = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            RespSize = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ComplexProtoParams : pb::IMessage<ComplexProtoParams> {
+    private static readonly pb::MessageParser<ComplexProtoParams> _parser = new pb::MessageParser<ComplexProtoParams>(() => new ComplexProtoParams());
+    public static pb::MessageParser<ComplexProtoParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ComplexProtoParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ComplexProtoParams(ComplexProtoParams other) : this() {
+    }
+
+    public ComplexProtoParams Clone() {
+      return new ComplexProtoParams(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ComplexProtoParams);
+    }
+
+    public bool Equals(ComplexProtoParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(ComplexProtoParams other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class PayloadConfig : pb::IMessage<PayloadConfig> {
+    private static readonly pb::MessageParser<PayloadConfig> _parser = new pb::MessageParser<PayloadConfig>(() => new PayloadConfig());
+    public static pb::MessageParser<PayloadConfig> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public PayloadConfig() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public PayloadConfig(PayloadConfig other) : this() {
+      switch (other.PayloadCase) {
+        case PayloadOneofCase.BytebufParams:
+          BytebufParams = other.BytebufParams.Clone();
+          break;
+        case PayloadOneofCase.SimpleParams:
+          SimpleParams = other.SimpleParams.Clone();
+          break;
+        case PayloadOneofCase.ComplexParams:
+          ComplexParams = other.ComplexParams.Clone();
+          break;
+      }
+
+    }
+
+    public PayloadConfig Clone() {
+      return new PayloadConfig(this);
+    }
+
+    public const int BytebufParamsFieldNumber = 1;
+    public global::Grpc.Testing.ByteBufferParams BytebufParams {
+      get { return payloadCase_ == PayloadOneofCase.BytebufParams ? (global::Grpc.Testing.ByteBufferParams) payload_ : null; }
+      set {
+        payload_ = value;
+        payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.BytebufParams;
+      }
+    }
+
+    public const int SimpleParamsFieldNumber = 2;
+    public global::Grpc.Testing.SimpleProtoParams SimpleParams {
+      get { return payloadCase_ == PayloadOneofCase.SimpleParams ? (global::Grpc.Testing.SimpleProtoParams) payload_ : null; }
+      set {
+        payload_ = value;
+        payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.SimpleParams;
+      }
+    }
+
+    public const int ComplexParamsFieldNumber = 3;
+    public global::Grpc.Testing.ComplexProtoParams ComplexParams {
+      get { return payloadCase_ == PayloadOneofCase.ComplexParams ? (global::Grpc.Testing.ComplexProtoParams) payload_ : null; }
+      set {
+        payload_ = value;
+        payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.ComplexParams;
+      }
+    }
+
+    private object payload_;
+    public enum PayloadOneofCase {
+      None = 0,
+      BytebufParams = 1,
+      SimpleParams = 2,
+      ComplexParams = 3,
+    }
+    private PayloadOneofCase payloadCase_ = PayloadOneofCase.None;
+    public PayloadOneofCase PayloadCase {
+      get { return payloadCase_; }
+    }
+
+    public void ClearPayload() {
+      payloadCase_ = PayloadOneofCase.None;
+      payload_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as PayloadConfig);
+    }
+
+    public bool Equals(PayloadConfig other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(BytebufParams, other.BytebufParams)) return false;
+      if (!object.Equals(SimpleParams, other.SimpleParams)) return false;
+      if (!object.Equals(ComplexParams, other.ComplexParams)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (payloadCase_ == PayloadOneofCase.BytebufParams) hash ^= BytebufParams.GetHashCode();
+      if (payloadCase_ == PayloadOneofCase.SimpleParams) hash ^= SimpleParams.GetHashCode();
+      if (payloadCase_ == PayloadOneofCase.ComplexParams) hash ^= ComplexParams.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (payloadCase_ == PayloadOneofCase.BytebufParams) {
+        output.WriteRawTag(10);
+        output.WriteMessage(BytebufParams);
+      }
+      if (payloadCase_ == PayloadOneofCase.SimpleParams) {
+        output.WriteRawTag(18);
+        output.WriteMessage(SimpleParams);
+      }
+      if (payloadCase_ == PayloadOneofCase.ComplexParams) {
+        output.WriteRawTag(26);
+        output.WriteMessage(ComplexParams);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (payloadCase_ == PayloadOneofCase.BytebufParams) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(BytebufParams);
+      }
+      if (payloadCase_ == PayloadOneofCase.SimpleParams) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SimpleParams);
+      }
+      if (payloadCase_ == PayloadOneofCase.ComplexParams) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ComplexParams);
+      }
+      return size;
+    }
+
+    public void MergeFrom(PayloadConfig other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.PayloadCase) {
+        case PayloadOneofCase.BytebufParams:
+          BytebufParams = other.BytebufParams;
+          break;
+        case PayloadOneofCase.SimpleParams:
+          SimpleParams = other.SimpleParams;
+          break;
+        case PayloadOneofCase.ComplexParams:
+          ComplexParams = other.ComplexParams;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            global::Grpc.Testing.ByteBufferParams subBuilder = new global::Grpc.Testing.ByteBufferParams();
+            if (payloadCase_ == PayloadOneofCase.BytebufParams) {
+              subBuilder.MergeFrom(BytebufParams);
+            }
+            input.ReadMessage(subBuilder);
+            BytebufParams = subBuilder;
+            break;
+          }
+          case 18: {
+            global::Grpc.Testing.SimpleProtoParams subBuilder = new global::Grpc.Testing.SimpleProtoParams();
+            if (payloadCase_ == PayloadOneofCase.SimpleParams) {
+              subBuilder.MergeFrom(SimpleParams);
+            }
+            input.ReadMessage(subBuilder);
+            SimpleParams = subBuilder;
+            break;
+          }
+          case 26: {
+            global::Grpc.Testing.ComplexProtoParams subBuilder = new global::Grpc.Testing.ComplexProtoParams();
+            if (payloadCase_ == PayloadOneofCase.ComplexParams) {
+              subBuilder.MergeFrom(ComplexParams);
+            }
+            input.ReadMessage(subBuilder);
+            ComplexParams = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
new file mode 100644
index 0000000000000000000000000000000000000000..686b48434537ceef3967d121f0e27d989ad9f7cb
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -0,0 +1,108 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+using CommandLine;
+using CommandLine.Text;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+    public class QpsWorker
+    {
+        private class ServerOptions
+        {
+            [Option("driver_port", DefaultValue = 0)]
+            public int DriverPort { get; set; }
+
+            [HelpOption]
+            public string GetUsage()
+            {
+                var help = new HelpText
+                {
+                    Heading = "gRPC C# performance testing worker",
+                    AddDashesToOption = true
+                };
+                help.AddPreOptionsLine("Usage:");
+                help.AddOptions(this);
+                return help;
+            }
+        }
+
+        ServerOptions options;
+
+        private QpsWorker(ServerOptions options)
+        {
+            this.options = options;
+        }
+
+        public static void Run(string[] args)
+        {
+            var options = new ServerOptions();
+            if (!Parser.Default.ParseArguments(args, options))
+            {
+                Environment.Exit(1);
+            }
+
+            var workerServer = new QpsWorker(options);
+            workerServer.Run();
+        }
+
+        private void Run()
+        {
+            string host = "0.0.0.0";
+            int port = options.DriverPort;
+
+            var server = new Server
+            {
+                Services = { WorkerService.BindService(new WorkerServiceImpl()) },
+                Ports = { new ServerPort(host, options.DriverPort, ServerCredentials.Insecure )}
+            };
+            int boundPort = server.Ports.Single().BoundPort;
+            Console.WriteLine("Running qps worker server on " + string.Format("{0}:{1}", host, boundPort));
+            server.Start();
+
+            server.ShutdownTask.Wait();
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2b51526c88fe18701332cec1455e1b072ac2ed9c
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
@@ -0,0 +1,117 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.Testing;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Runs performance tests in-process.
+    /// </summary>
+    public class RunnerClientServerTest
+    {
+        const string Host = "localhost";
+        IServerRunner serverRunner;
+
+        [TestFixtureSetUp]
+        public void Init()
+        {
+            var serverConfig = new ServerConfig
+            {
+                ServerType = ServerType.ASYNC_SERVER,
+                Host = Host,
+                PayloadConfig = new PayloadConfig
+                {
+                    SimpleParams = new SimpleProtoParams
+                    {
+                        RespSize = 100
+                    }
+                }
+            };
+            serverRunner = ServerRunners.CreateStarted(serverConfig);
+        }
+
+        [TestFixtureTearDown]
+        public void Cleanup()
+        {
+            serverRunner.StopAsync().Wait();
+        }
+
+        // Test attribute commented out to prevent running as part of the default test suite.
+        //[Test]
+        //[Category("Performance")]
+        public async Task ClientServerRunner()
+        {
+            var config = new ClientConfig
+            {
+                ServerTargets = { string.Format("{0}:{1}", Host, serverRunner.BoundPort) },
+                RpcType = RpcType.UNARY,
+                LoadParams = new LoadParams { ClosedLoop = new ClosedLoopParams() },
+                PayloadConfig = new PayloadConfig
+                {
+                    SimpleParams = new SimpleProtoParams
+                    {
+                        ReqSize = 100
+                    }
+                },
+                HistogramParams = new HistogramParams
+                {
+                    Resolution = 0.01,
+                    MaxPossible = 60e9
+                }
+            };
+
+            var runner = ClientRunners.CreateStarted(config);
+
+            System.Console.WriteLine("Warming up");
+            await Task.Delay(3000);
+            runner.GetStats(true);  // throw away warm-up data
+
+            System.Console.WriteLine("Benchmarking");
+            await Task.Delay(3000);
+            var stats = runner.GetStats(true);
+            await runner.StopAsync();
+
+            System.Console.WriteLine(stats);
+            System.Console.WriteLine("avg micros/call " + (long) (stats.Latencies.Sum / stats.Latencies.Count / 1000.0));
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e8be7758cee6f508e296a37d8ab2015e5decf42a
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
@@ -0,0 +1,124 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Helper methods to start server runners for performance testing.
+    /// </summary>
+    public static class ServerRunners
+    {
+        /// <summary>
+        /// Creates a started server runner.
+        /// </summary>
+        public static IServerRunner CreateStarted(ServerConfig config)
+        {
+            Grpc.Core.Utils.Preconditions.CheckArgument(config.ServerType == ServerType.ASYNC_SERVER);
+            var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure;
+
+            // TODO: qps_driver needs to setup payload properly...
+            int responseSize = config.PayloadConfig != null ? config.PayloadConfig.SimpleParams.RespSize : 0;
+            var server = new Server
+            {
+                Services = { BenchmarkService.BindService(new BenchmarkServiceImpl(responseSize)) },
+                Ports = { new ServerPort(config.Host, config.Port, credentials) }
+            };
+
+            server.Start();
+            return new ServerRunnerImpl(server);
+        }
+    }
+
+    /// <summary>
+    /// Server runner.
+    /// </summary>
+    public class ServerRunnerImpl : IServerRunner
+    {
+        readonly Server server;
+        readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
+
+        public ServerRunnerImpl(Server server)
+        {
+            this.server = Grpc.Core.Utils.Preconditions.CheckNotNull(server);
+        }
+
+        public int BoundPort
+        {
+            get
+            {
+                return server.Ports.Single().BoundPort;
+            }
+        }
+
+        /// <summary>
+        /// Gets server stats.
+        /// </summary>
+        /// <returns>The stats.</returns>
+        public ServerStats GetStats(bool reset)
+        {
+            var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
+
+            // TODO: populate user time and system time
+            return new ServerStats
+            {
+                TimeElapsed = secondsElapsed,
+                TimeUser = 0,
+                TimeSystem = 0
+            };
+        }
+
+        /// <summary>
+        /// Asynchronously stops the server.
+        /// </summary>
+        /// <returns>Task that finishes when server has shutdown.</returns>
+        public Task StopAsync()
+        {
+            return server.ShutdownAsync();
+        }
+    }
+        
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/Services.cs b/src/csharp/Grpc.IntegrationTesting/Services.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b648da6734f9994151aa0961617c513fdedc11a7
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Services.cs
@@ -0,0 +1,44 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: test/proto/benchmarks/services.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class Services {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static Services() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiR0ZXN0L3Byb3RvL2JlbmNobWFya3Mvc2VydmljZXMucHJvdG8SDGdycGMu", 
+            "dGVzdGluZxoZdGVzdC9wcm90by9tZXNzYWdlcy5wcm90bxojdGVzdC9wcm90", 
+            "by9iZW5jaG1hcmtzL2NvbnRyb2wucHJvdG8yqgEKEEJlbmNobWFya1NlcnZp", 
+            "Y2USRgoJVW5hcnlDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa", 
+            "HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2USTgoNU3RyZWFtaW5nQ2Fs", 
+            "bBIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5n", 
+            "LlNpbXBsZVJlc3BvbnNlKAEwATKdAQoNV29ya2VyU2VydmljZRJFCglSdW5T", 
+            "ZXJ2ZXISGC5ncnBjLnRlc3RpbmcuU2VydmVyQXJncxoaLmdycGMudGVzdGlu", 
+            "Zy5TZXJ2ZXJTdGF0dXMoATABEkUKCVJ1bkNsaWVudBIYLmdycGMudGVzdGlu", 
+            "Zy5DbGllbnRBcmdzGhouZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXR1cygBMAFi", 
+            "BnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { global::Grpc.Testing.Messages.Descriptor, global::Grpc.Testing.Control.Descriptor, },
+          new pbr::GeneratedCodeInfo(null, null));
+    }
+    #endregion
+
+  }
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ce388c6d5c6529275635d0882c6d922053d820c8
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
@@ -0,0 +1,198 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: test/proto/benchmarks/services.proto
+#region Designer generated code
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Testing {
+  public static class BenchmarkService
+  {
+    static readonly string __ServiceName = "grpc.testing.BenchmarkService";
+
+    static readonly Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom);
+
+    static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_UnaryCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+        MethodType.Unary,
+        __ServiceName,
+        "UnaryCall",
+        __Marshaller_SimpleRequest,
+        __Marshaller_SimpleResponse);
+
+    static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+        MethodType.DuplexStreaming,
+        __ServiceName,
+        "StreamingCall",
+        __Marshaller_SimpleRequest,
+        __Marshaller_SimpleResponse);
+
+    // service descriptor
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Grpc.Testing.Services.Descriptor.Services[0]; }
+    }
+
+    // client interface
+    public interface IBenchmarkServiceClient
+    {
+      global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options);
+      AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options);
+      AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options);
+    }
+
+    // server-side interface
+    public interface IBenchmarkService
+    {
+      Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context);
+      Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context);
+    }
+
+    // client stub
+    public class BenchmarkServiceClient : ClientBase, IBenchmarkServiceClient
+    {
+      public BenchmarkServiceClient(Channel channel) : base(channel)
+      {
+      }
+      public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.BlockingUnaryCall(call, request);
+      }
+      public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+      {
+        var call = CreateCall(__Method_UnaryCall, options);
+        return Calls.BlockingUnaryCall(call, request);
+      }
+      public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.AsyncUnaryCall(call, request);
+      }
+      public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
+      {
+        var call = CreateCall(__Method_UnaryCall, options);
+        return Calls.AsyncUnaryCall(call, request);
+      }
+      public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_StreamingCall, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.AsyncDuplexStreamingCall(call);
+      }
+      public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
+      {
+        var call = CreateCall(__Method_StreamingCall, options);
+        return Calls.AsyncDuplexStreamingCall(call);
+      }
+    }
+
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(IBenchmarkService serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
+          .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
+    }
+
+    // creates a new client
+    public static BenchmarkServiceClient NewClient(Channel channel)
+    {
+      return new BenchmarkServiceClient(channel);
+    }
+
+  }
+  public static class WorkerService
+  {
+    static readonly string __ServiceName = "grpc.testing.WorkerService";
+
+    static readonly Marshaller<global::Grpc.Testing.ServerArgs> __Marshaller_ServerArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerArgs.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.ServerStatus> __Marshaller_ServerStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerStatus.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.ClientArgs> __Marshaller_ClientArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientArgs.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.ClientStatus> __Marshaller_ClientStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientStatus.Parser.ParseFrom);
+
+    static readonly Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> __Method_RunServer = new Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus>(
+        MethodType.DuplexStreaming,
+        __ServiceName,
+        "RunServer",
+        __Marshaller_ServerArgs,
+        __Marshaller_ServerStatus);
+
+    static readonly Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> __Method_RunClient = new Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus>(
+        MethodType.DuplexStreaming,
+        __ServiceName,
+        "RunClient",
+        __Marshaller_ClientArgs,
+        __Marshaller_ClientStatus);
+
+    // service descriptor
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Grpc.Testing.Services.Descriptor.Services[1]; }
+    }
+
+    // client interface
+    public interface IWorkerServiceClient
+    {
+      AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options);
+      AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options);
+    }
+
+    // server-side interface
+    public interface IWorkerService
+    {
+      Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context);
+      Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context);
+    }
+
+    // client stub
+    public class WorkerServiceClient : ClientBase, IWorkerServiceClient
+    {
+      public WorkerServiceClient(Channel channel) : base(channel)
+      {
+      }
+      public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_RunServer, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.AsyncDuplexStreamingCall(call);
+      }
+      public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
+      {
+        var call = CreateCall(__Method_RunServer, options);
+        return Calls.AsyncDuplexStreamingCall(call);
+      }
+      public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_RunClient, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.AsyncDuplexStreamingCall(call);
+      }
+      public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
+      {
+        var call = CreateCall(__Method_RunClient, options);
+        return Calls.AsyncDuplexStreamingCall(call);
+      }
+    }
+
+    // creates service definition that can be registered with a server
+    public static ServerServiceDefinition BindService(IWorkerService serviceImpl)
+    {
+      return ServerServiceDefinition.CreateBuilder(__ServiceName)
+          .AddMethod(__Method_RunServer, serviceImpl.RunServer)
+          .AddMethod(__Method_RunClient, serviceImpl.RunClient).Build();
+    }
+
+    // creates a new client
+    public static WorkerServiceClient NewClient(Channel channel)
+    {
+      return new WorkerServiceClient(channel);
+    }
+
+  }
+}
+#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop b/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
index fb99cd4af1cd6f61557b16a2cedca158b689b7c3..746f2ef5ce15a855b404ca5acef4ce75651c56fb 100644
--- a/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
+++ b/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
@@ -1,7 +1,10 @@
 <StyleCopSettings Version="105">
   <SourceFileList>
-    <SourceFile>Messages.cs</SourceFile>
     <SourceFile>Empty.cs</SourceFile>
+    <SourceFile>Control.cs</SourceFile>
+    <SourceFile>Messages.cs</SourceFile>
+    <SourceFile>Payloads.cs</SourceFile>
+    <SourceFile>Stats.cs</SourceFile>
     <Settings>
     <GlobalSettings>
       <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
diff --git a/src/csharp/Grpc.IntegrationTesting/Stats.cs b/src/csharp/Grpc.IntegrationTesting/Stats.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4ae66baffa57f5a33fbed357283cbc804405e79c
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Stats.cs
@@ -0,0 +1,744 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: test/proto/benchmarks/stats.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class Stats {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static Stats() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiF0ZXN0L3Byb3RvL2JlbmNobWFya3Mvc3RhdHMucHJvdG8SDGdycGMudGVz", 
+            "dGluZyJLCgtTZXJ2ZXJTdGF0cxIUCgx0aW1lX2VsYXBzZWQYASABKAESEQoJ", 
+            "dGltZV91c2VyGAIgASgBEhMKC3RpbWVfc3lzdGVtGAMgASgBIjsKD0hpc3Rv", 
+            "Z3JhbVBhcmFtcxISCgpyZXNvbHV0aW9uGAEgASgBEhQKDG1heF9wb3NzaWJs", 
+            "ZRgCIAEoASJ3Cg1IaXN0b2dyYW1EYXRhEg4KBmJ1Y2tldBgBIAMoDRIQCght", 
+            "aW5fc2VlbhgCIAEoARIQCghtYXhfc2VlbhgDIAEoARILCgNzdW0YBCABKAES", 
+            "FgoOc3VtX29mX3NxdWFyZXMYBSABKAESDQoFY291bnQYBiABKAEiewoLQ2xp", 
+            "ZW50U3RhdHMSLgoJbGF0ZW5jaWVzGAEgASgLMhsuZ3JwYy50ZXN0aW5nLkhp", 
+            "c3RvZ3JhbURhdGESFAoMdGltZV9lbGFwc2VkGAIgASgBEhEKCXRpbWVfdXNl", 
+            "chgDIAEoARITCgt0aW1lX3N5c3RlbRgEIAEoAWIGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStats), new[]{ "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramParams), new[]{ "Resolution", "MaxPossible" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramData), new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStats), new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ServerStats : pb::IMessage<ServerStats> {
+    private static readonly pb::MessageParser<ServerStats> _parser = new pb::MessageParser<ServerStats>(() => new ServerStats());
+    public static pb::MessageParser<ServerStats> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ServerStats() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ServerStats(ServerStats other) : this() {
+      timeElapsed_ = other.timeElapsed_;
+      timeUser_ = other.timeUser_;
+      timeSystem_ = other.timeSystem_;
+    }
+
+    public ServerStats Clone() {
+      return new ServerStats(this);
+    }
+
+    public const int TimeElapsedFieldNumber = 1;
+    private double timeElapsed_;
+    public double TimeElapsed {
+      get { return timeElapsed_; }
+      set {
+        timeElapsed_ = value;
+      }
+    }
+
+    public const int TimeUserFieldNumber = 2;
+    private double timeUser_;
+    public double TimeUser {
+      get { return timeUser_; }
+      set {
+        timeUser_ = value;
+      }
+    }
+
+    public const int TimeSystemFieldNumber = 3;
+    private double timeSystem_;
+    public double TimeSystem {
+      get { return timeSystem_; }
+      set {
+        timeSystem_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ServerStats);
+    }
+
+    public bool Equals(ServerStats other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (TimeElapsed != other.TimeElapsed) return false;
+      if (TimeUser != other.TimeUser) return false;
+      if (TimeSystem != other.TimeSystem) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
+      if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
+      if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (TimeElapsed != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(TimeElapsed);
+      }
+      if (TimeUser != 0D) {
+        output.WriteRawTag(17);
+        output.WriteDouble(TimeUser);
+      }
+      if (TimeSystem != 0D) {
+        output.WriteRawTag(25);
+        output.WriteDouble(TimeSystem);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (TimeElapsed != 0D) {
+        size += 1 + 8;
+      }
+      if (TimeUser != 0D) {
+        size += 1 + 8;
+      }
+      if (TimeSystem != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(ServerStats other) {
+      if (other == null) {
+        return;
+      }
+      if (other.TimeElapsed != 0D) {
+        TimeElapsed = other.TimeElapsed;
+      }
+      if (other.TimeUser != 0D) {
+        TimeUser = other.TimeUser;
+      }
+      if (other.TimeSystem != 0D) {
+        TimeSystem = other.TimeSystem;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 9: {
+            TimeElapsed = input.ReadDouble();
+            break;
+          }
+          case 17: {
+            TimeUser = input.ReadDouble();
+            break;
+          }
+          case 25: {
+            TimeSystem = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class HistogramParams : pb::IMessage<HistogramParams> {
+    private static readonly pb::MessageParser<HistogramParams> _parser = new pb::MessageParser<HistogramParams>(() => new HistogramParams());
+    public static pb::MessageParser<HistogramParams> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public HistogramParams() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public HistogramParams(HistogramParams other) : this() {
+      resolution_ = other.resolution_;
+      maxPossible_ = other.maxPossible_;
+    }
+
+    public HistogramParams Clone() {
+      return new HistogramParams(this);
+    }
+
+    public const int ResolutionFieldNumber = 1;
+    private double resolution_;
+    public double Resolution {
+      get { return resolution_; }
+      set {
+        resolution_ = value;
+      }
+    }
+
+    public const int MaxPossibleFieldNumber = 2;
+    private double maxPossible_;
+    public double MaxPossible {
+      get { return maxPossible_; }
+      set {
+        maxPossible_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as HistogramParams);
+    }
+
+    public bool Equals(HistogramParams other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Resolution != other.Resolution) return false;
+      if (MaxPossible != other.MaxPossible) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Resolution != 0D) hash ^= Resolution.GetHashCode();
+      if (MaxPossible != 0D) hash ^= MaxPossible.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Resolution != 0D) {
+        output.WriteRawTag(9);
+        output.WriteDouble(Resolution);
+      }
+      if (MaxPossible != 0D) {
+        output.WriteRawTag(17);
+        output.WriteDouble(MaxPossible);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Resolution != 0D) {
+        size += 1 + 8;
+      }
+      if (MaxPossible != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(HistogramParams other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Resolution != 0D) {
+        Resolution = other.Resolution;
+      }
+      if (other.MaxPossible != 0D) {
+        MaxPossible = other.MaxPossible;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 9: {
+            Resolution = input.ReadDouble();
+            break;
+          }
+          case 17: {
+            MaxPossible = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class HistogramData : pb::IMessage<HistogramData> {
+    private static readonly pb::MessageParser<HistogramData> _parser = new pb::MessageParser<HistogramData>(() => new HistogramData());
+    public static pb::MessageParser<HistogramData> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public HistogramData() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public HistogramData(HistogramData other) : this() {
+      bucket_ = other.bucket_.Clone();
+      minSeen_ = other.minSeen_;
+      maxSeen_ = other.maxSeen_;
+      sum_ = other.sum_;
+      sumOfSquares_ = other.sumOfSquares_;
+      count_ = other.count_;
+    }
+
+    public HistogramData Clone() {
+      return new HistogramData(this);
+    }
+
+    public const int BucketFieldNumber = 1;
+    private static readonly pb::FieldCodec<uint> _repeated_bucket_codec
+        = pb::FieldCodec.ForUInt32(10);
+    private readonly pbc::RepeatedField<uint> bucket_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> Bucket {
+      get { return bucket_; }
+    }
+
+    public const int MinSeenFieldNumber = 2;
+    private double minSeen_;
+    public double MinSeen {
+      get { return minSeen_; }
+      set {
+        minSeen_ = value;
+      }
+    }
+
+    public const int MaxSeenFieldNumber = 3;
+    private double maxSeen_;
+    public double MaxSeen {
+      get { return maxSeen_; }
+      set {
+        maxSeen_ = value;
+      }
+    }
+
+    public const int SumFieldNumber = 4;
+    private double sum_;
+    public double Sum {
+      get { return sum_; }
+      set {
+        sum_ = value;
+      }
+    }
+
+    public const int SumOfSquaresFieldNumber = 5;
+    private double sumOfSquares_;
+    public double SumOfSquares {
+      get { return sumOfSquares_; }
+      set {
+        sumOfSquares_ = value;
+      }
+    }
+
+    public const int CountFieldNumber = 6;
+    private double count_;
+    public double Count {
+      get { return count_; }
+      set {
+        count_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as HistogramData);
+    }
+
+    public bool Equals(HistogramData other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!bucket_.Equals(other.bucket_)) return false;
+      if (MinSeen != other.MinSeen) return false;
+      if (MaxSeen != other.MaxSeen) return false;
+      if (Sum != other.Sum) return false;
+      if (SumOfSquares != other.SumOfSquares) return false;
+      if (Count != other.Count) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= bucket_.GetHashCode();
+      if (MinSeen != 0D) hash ^= MinSeen.GetHashCode();
+      if (MaxSeen != 0D) hash ^= MaxSeen.GetHashCode();
+      if (Sum != 0D) hash ^= Sum.GetHashCode();
+      if (SumOfSquares != 0D) hash ^= SumOfSquares.GetHashCode();
+      if (Count != 0D) hash ^= Count.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      bucket_.WriteTo(output, _repeated_bucket_codec);
+      if (MinSeen != 0D) {
+        output.WriteRawTag(17);
+        output.WriteDouble(MinSeen);
+      }
+      if (MaxSeen != 0D) {
+        output.WriteRawTag(25);
+        output.WriteDouble(MaxSeen);
+      }
+      if (Sum != 0D) {
+        output.WriteRawTag(33);
+        output.WriteDouble(Sum);
+      }
+      if (SumOfSquares != 0D) {
+        output.WriteRawTag(41);
+        output.WriteDouble(SumOfSquares);
+      }
+      if (Count != 0D) {
+        output.WriteRawTag(49);
+        output.WriteDouble(Count);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += bucket_.CalculateSize(_repeated_bucket_codec);
+      if (MinSeen != 0D) {
+        size += 1 + 8;
+      }
+      if (MaxSeen != 0D) {
+        size += 1 + 8;
+      }
+      if (Sum != 0D) {
+        size += 1 + 8;
+      }
+      if (SumOfSquares != 0D) {
+        size += 1 + 8;
+      }
+      if (Count != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(HistogramData other) {
+      if (other == null) {
+        return;
+      }
+      bucket_.Add(other.bucket_);
+      if (other.MinSeen != 0D) {
+        MinSeen = other.MinSeen;
+      }
+      if (other.MaxSeen != 0D) {
+        MaxSeen = other.MaxSeen;
+      }
+      if (other.Sum != 0D) {
+        Sum = other.Sum;
+      }
+      if (other.SumOfSquares != 0D) {
+        SumOfSquares = other.SumOfSquares;
+      }
+      if (other.Count != 0D) {
+        Count = other.Count;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10:
+          case 8: {
+            bucket_.AddEntriesFrom(input, _repeated_bucket_codec);
+            break;
+          }
+          case 17: {
+            MinSeen = input.ReadDouble();
+            break;
+          }
+          case 25: {
+            MaxSeen = input.ReadDouble();
+            break;
+          }
+          case 33: {
+            Sum = input.ReadDouble();
+            break;
+          }
+          case 41: {
+            SumOfSquares = input.ReadDouble();
+            break;
+          }
+          case 49: {
+            Count = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ClientStats : pb::IMessage<ClientStats> {
+    private static readonly pb::MessageParser<ClientStats> _parser = new pb::MessageParser<ClientStats>(() => new ClientStats());
+    public static pb::MessageParser<ClientStats> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ClientStats() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ClientStats(ClientStats other) : this() {
+      Latencies = other.latencies_ != null ? other.Latencies.Clone() : null;
+      timeElapsed_ = other.timeElapsed_;
+      timeUser_ = other.timeUser_;
+      timeSystem_ = other.timeSystem_;
+    }
+
+    public ClientStats Clone() {
+      return new ClientStats(this);
+    }
+
+    public const int LatenciesFieldNumber = 1;
+    private global::Grpc.Testing.HistogramData latencies_;
+    public global::Grpc.Testing.HistogramData Latencies {
+      get { return latencies_; }
+      set {
+        latencies_ = value;
+      }
+    }
+
+    public const int TimeElapsedFieldNumber = 2;
+    private double timeElapsed_;
+    public double TimeElapsed {
+      get { return timeElapsed_; }
+      set {
+        timeElapsed_ = value;
+      }
+    }
+
+    public const int TimeUserFieldNumber = 3;
+    private double timeUser_;
+    public double TimeUser {
+      get { return timeUser_; }
+      set {
+        timeUser_ = value;
+      }
+    }
+
+    public const int TimeSystemFieldNumber = 4;
+    private double timeSystem_;
+    public double TimeSystem {
+      get { return timeSystem_; }
+      set {
+        timeSystem_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ClientStats);
+    }
+
+    public bool Equals(ClientStats other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Latencies, other.Latencies)) return false;
+      if (TimeElapsed != other.TimeElapsed) return false;
+      if (TimeUser != other.TimeUser) return false;
+      if (TimeSystem != other.TimeSystem) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (latencies_ != null) hash ^= Latencies.GetHashCode();
+      if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
+      if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
+      if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (latencies_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Latencies);
+      }
+      if (TimeElapsed != 0D) {
+        output.WriteRawTag(17);
+        output.WriteDouble(TimeElapsed);
+      }
+      if (TimeUser != 0D) {
+        output.WriteRawTag(25);
+        output.WriteDouble(TimeUser);
+      }
+      if (TimeSystem != 0D) {
+        output.WriteRawTag(33);
+        output.WriteDouble(TimeSystem);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (latencies_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies);
+      }
+      if (TimeElapsed != 0D) {
+        size += 1 + 8;
+      }
+      if (TimeUser != 0D) {
+        size += 1 + 8;
+      }
+      if (TimeSystem != 0D) {
+        size += 1 + 8;
+      }
+      return size;
+    }
+
+    public void MergeFrom(ClientStats other) {
+      if (other == null) {
+        return;
+      }
+      if (other.latencies_ != null) {
+        if (latencies_ == null) {
+          latencies_ = new global::Grpc.Testing.HistogramData();
+        }
+        Latencies.MergeFrom(other.Latencies);
+      }
+      if (other.TimeElapsed != 0D) {
+        TimeElapsed = other.TimeElapsed;
+      }
+      if (other.TimeUser != 0D) {
+        TimeUser = other.TimeUser;
+      }
+      if (other.TimeSystem != 0D) {
+        TimeSystem = other.TimeSystem;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (latencies_ == null) {
+              latencies_ = new global::Grpc.Testing.HistogramData();
+            }
+            input.ReadMessage(latencies_);
+            break;
+          }
+          case 17: {
+            TimeElapsed = input.ReadDouble();
+            break;
+          }
+          case 25: {
+            TimeUser = input.ReadDouble();
+            break;
+          }
+          case 33: {
+            TimeSystem = input.ReadDouble();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs b/src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e44ae2a5ff364ad172b42cbc26372e342f2db4de
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs
@@ -0,0 +1,78 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using Grpc.Testing;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// Snapshottable wall clock stopwatch.
+    /// </summary>
+    public class WallClockStopwatch
+    {
+        long startTicks;
+
+        public WallClockStopwatch()
+        {
+            this.startTicks = DateTime.UtcNow.Ticks;
+        }
+
+        public TimeSpan GetElapsedSnapshot(bool reset)
+        {
+            var utcNow = DateTime.UtcNow;
+
+            long oldStartTicks;
+            if (reset)
+            {
+                oldStartTicks = Interlocked.Exchange(ref this.startTicks, utcNow.Ticks);
+            }
+            else
+            {
+                oldStartTicks = this.startTicks;
+            }
+            return utcNow - new DateTime(oldStartTicks, DateTimeKind.Utc);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bb2918bf463dc0e527d24b2cfd7766c285957d70
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
@@ -0,0 +1,96 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.Protobuf;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using Grpc.IntegrationTesting;
+
+namespace Grpc.Testing
+{
+    /// <summary>
+    /// Implementation of WorkerService server
+    /// </summary>
+    public class WorkerServiceImpl : WorkerService.IWorkerService
+    {
+        public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
+        {
+            Grpc.Core.Utils.Preconditions.CheckState(await requestStream.MoveNext());
+            var serverConfig = requestStream.Current.Setup;
+            var runner = ServerRunners.CreateStarted(serverConfig);
+
+            await responseStream.WriteAsync(new ServerStatus
+            {
+                Stats = runner.GetStats(false),
+                Port = runner.BoundPort,
+                Cores = 0,  // TODO: set number of cores
+            });
+                
+            while (await requestStream.MoveNext())
+            {
+                var reset = requestStream.Current.Mark.Reset;
+                await responseStream.WriteAsync(new ServerStatus
+                {
+                    Stats = runner.GetStats(reset)
+                });
+            }
+            await runner.StopAsync();
+        }
+
+        public async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
+        {
+            Grpc.Core.Utils.Preconditions.CheckState(await requestStream.MoveNext());
+            var clientConfig = requestStream.Current.Setup;
+            var runner = ClientRunners.CreateStarted(clientConfig);
+
+            await responseStream.WriteAsync(new ClientStatus
+            {
+                Stats = runner.GetStats(false)
+            });
+
+            while (await requestStream.MoveNext())
+            {
+                var reset = requestStream.Current.Mark.Reset;
+                await responseStream.WriteAsync(new ClientStatus
+                {
+                    Stats = runner.GetStats(reset)
+                });
+            }
+            await runner.StopAsync();
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/data/server1.pem b/src/csharp/Grpc.IntegrationTesting/data/server1.pem
index 8e582e571f643ca3fb6042a786c709a53f5afcf3..f3d43fcc5beadd98542abdaa32acfb555b807559 100644
--- a/src/csharp/Grpc.IntegrationTesting/data/server1.pem
+++ b/src/csharp/Grpc.IntegrationTesting/data/server1.pem
@@ -1,16 +1,16 @@
 -----BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
-MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
-MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
-BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
-c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
-JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
-RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
-3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
-BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
-b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
-KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
-wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
-aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
+MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
+MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
+BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
+ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
+LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
+zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
+9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
+CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
+em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
+CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
+hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
+y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
 -----END CERTIFICATE-----
diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln
index f19f29c6a27ccebfbdf884dde6c8d6c2040a1c63..8ff35e8c0d0193f35ad390314f467e16d8cec859 100644
--- a/src/csharp/Grpc.sln
+++ b/src/csharp/Grpc.sln
@@ -1,6 +1,6 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
+# Visual Studio 2012
 VisualStudioVersion = 12.0.31101.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples", "Grpc.Examples\Grpc.Examples.csproj", "{7DC1433E-3225-42C7-B7EA-546D56E27A4B}"
@@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck", "Grpc.He
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck.Tests", "Grpc.HealthCheck.Tests\Grpc.HealthCheck.Tests.csproj", "{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.QpsWorker", "Grpc.IntegrationTesting.QpsWorker\Grpc.IntegrationTesting.QpsWorker.csproj", "{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -39,72 +41,78 @@ Global
 		ReleaseSigned|Any CPU = ReleaseSigned|Any CPU
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.Build.0 = Release|Any CPU
-		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
-		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
-		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.Build.0 = Release|Any CPU
-		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
-		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.Build.0 = Release|Any CPU
-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
 		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.Build.0 = Release|Any CPU
 		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
 		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.Build.0 = Release|Any CPU
-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
-		{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.Build.0 = Release|Any CPU
-		{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
-		{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
 		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.Build.0 = Release|Any CPU
 		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
 		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.Build.0 = Release|Any CPU
+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
 		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.Build.0 = Release|Any CPU
 		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
 		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.Build.0 = Release|Any CPU
-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
-		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.Build.0 = Release|Any CPU
-		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
-		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.Build.0 = Release|Any CPU
 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
 		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.Build.0 = Release|Any CPU
+		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+		{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -112,6 +120,8 @@ Global
 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
 	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 679ca43d74913c570a1b1c58988aae75af092b04..183931936e764f66a2b1ad3ca81651dd0b2cc723 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -785,9 +785,10 @@ grpcsharp_call_send_initial_metadata(grpc_call *call,
                                NULL);
 }
 
-GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_set_credentials(grpc_call *call,
-                                                            grpc_credentials *creds) {
-	return grpc_call_set_credentials(call, creds);
+GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_set_credentials(
+    grpc_call *call,
+    grpc_call_credentials *creds) {
+  return grpc_call_set_credentials(call, creds);
 }
 
 /* Server */
@@ -834,7 +835,7 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq,
 
 /* Security */
 
-GPR_EXPORT grpc_credentials *GPR_CALLTYPE
+GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE
 grpcsharp_ssl_credentials_create(const char *pem_root_certs,
                                  const char *key_cert_pair_cert_chain,
                                  const char *key_cert_pair_private_key) {
@@ -850,12 +851,19 @@ grpcsharp_ssl_credentials_create(const char *pem_root_certs,
   }
 }
 
-GPR_EXPORT void GPR_CALLTYPE grpcsharp_credentials_release(grpc_credentials *creds) {
-  grpc_credentials_release(creds);
+GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_credentials_release(
+    grpc_channel_credentials *creds) {
+  grpc_channel_credentials_release(creds);
+}
+
+GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_credentials_release(
+    grpc_call_credentials *creds) {
+  grpc_call_credentials_release(creds);
 }
 
 GPR_EXPORT grpc_channel *GPR_CALLTYPE
-grpcsharp_secure_channel_create(grpc_credentials *creds, const char *target,
+grpcsharp_secure_channel_create(grpc_channel_credentials *creds,
+                                const char *target,
                                 const grpc_channel_args *args) {
   return grpc_secure_channel_create(creds, target, args, NULL);
 }
@@ -897,10 +905,16 @@ grpcsharp_server_add_secure_http2_port(grpc_server *server, const char *addr,
   return grpc_server_add_secure_http2_port(server, addr, creds);
 }
 
-GPR_EXPORT grpc_credentials *GPR_CALLTYPE grpcsharp_composite_credentials_create(
-  grpc_credentials *creds1,
-  grpc_credentials *creds2) {
-  return grpc_composite_credentials_create(creds1, creds2, NULL);
+GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE grpcsharp_composite_channel_credentials_create(
+  grpc_channel_credentials *channel_creds,
+  grpc_call_credentials *call_creds) {
+  return grpc_composite_channel_credentials_create(channel_creds, call_creds, NULL);
+}
+
+GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_composite_call_credentials_create(
+  grpc_call_credentials *creds1,
+  grpc_call_credentials *creds2) {
+  return grpc_composite_call_credentials_create(creds1, creds2, NULL);
 }
 
 /* Metadata credentials plugin */
@@ -929,7 +943,7 @@ static void grpcsharp_metadata_credentials_destroy_handler(void *state) {
   interceptor(state, NULL, NULL, NULL, 1);
 }
 
-GPR_EXPORT grpc_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin(
+GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin(
   grpcsharp_metadata_interceptor_func metadata_interceptor) {
   grpc_metadata_credentials_plugin plugin;
   plugin.get_metadata = grpcsharp_get_metadata_handler;
diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh
index f879e074aa55a21b69dfe6c5f31e29fb34fdff6d..92348d13942e4f36219eb8fba90011eb39ca57b6 100755
--- a/src/csharp/generate_proto_csharp.sh
+++ b/src/csharp/generate_proto_csharp.sh
@@ -35,14 +35,14 @@ cd $(dirname $0)
 PROTOC=../../bins/opt/protobuf/protoc
 PLUGIN=protoc-gen-grpc=../../bins/opt/grpc_csharp_plugin
 EXAMPLES_DIR=Grpc.Examples
-INTEROP_DIR=Grpc.IntegrationTesting
+TESTING_DIR=Grpc.IntegrationTesting
 HEALTHCHECK_DIR=Grpc.HealthCheck
 
 $PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \
     -I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto
 
-$PROTOC --plugin=$PLUGIN --csharp_out=$INTEROP_DIR --grpc_out=$INTEROP_DIR \
-    -I ../.. ../../test/proto/*.proto
+$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
+    -I ../.. ../../test/proto/*.proto ../../test/proto/benchmarks/*.proto
 
 $PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \
     -I $HEALTHCHECK_DIR/proto $HEALTHCHECK_DIR/proto/health.proto
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index fe11905109a9463e416d9bd3bf5e28ac0e075168..a98ae85427f53d0c3809661a881149d482e47154 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -757,7 +757,7 @@ NAN_METHOD(Call::SetCredentials) {
   Call *call = ObjectWrap::Unwrap<Call>(info.This());
   CallCredentials *creds_object = ObjectWrap::Unwrap<CallCredentials>(
       Nan::To<Object>(info[0]).ToLocalChecked());
-  grpc_credentials *creds = creds_object->GetWrappedCredentials();
+  grpc_call_credentials *creds = creds_object->GetWrappedCredentials();
   grpc_call_error error = GRPC_CALL_ERROR;
   if (creds) {
     error = grpc_call_set_credentials(call->wrapped_call, creds);
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index ff16a1f1221f99266a934f3499934eb52588ef3f..9c5d9d291b7492fbef83ff99fa518e38be19fd55 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -64,11 +64,11 @@ using v8::Value;
 Nan::Callback *CallCredentials::constructor;
 Persistent<FunctionTemplate> CallCredentials::fun_tpl;
 
-CallCredentials::CallCredentials(grpc_credentials *credentials)
+CallCredentials::CallCredentials(grpc_call_credentials *credentials)
     : wrapped_credentials(credentials) {}
 
 CallCredentials::~CallCredentials() {
-  grpc_credentials_release(wrapped_credentials);
+  grpc_call_credentials_release(wrapped_credentials);
 }
 
 void CallCredentials::Init(Local<Object> exports) {
@@ -91,7 +91,7 @@ bool CallCredentials::HasInstance(Local<Value> val) {
   return Nan::New(fun_tpl)->HasInstance(val);
 }
 
-Local<Value> CallCredentials::WrapStruct(grpc_credentials *credentials) {
+Local<Value> CallCredentials::WrapStruct(grpc_call_credentials *credentials) {
   EscapableHandleScope scope;
   const int argc = 1;
   if (credentials == NULL) {
@@ -108,7 +108,7 @@ Local<Value> CallCredentials::WrapStruct(grpc_credentials *credentials) {
   }
 }
 
-grpc_credentials *CallCredentials::GetWrappedCredentials() {
+grpc_call_credentials *CallCredentials::GetWrappedCredentials() {
   return wrapped_credentials;
 }
 
@@ -119,8 +119,8 @@ NAN_METHOD(CallCredentials::New) {
           "CallCredentials can only be created with the provided functions");
     }
     Local<External> ext = info[0].As<External>();
-    grpc_credentials *creds_value =
-        reinterpret_cast<grpc_credentials *>(ext->Value());
+    grpc_call_credentials *creds_value =
+        reinterpret_cast<grpc_call_credentials *>(ext->Value());
     CallCredentials *credentials = new CallCredentials(creds_value);
     credentials->Wrap(info.This());
     info.GetReturnValue().Set(info.This());
@@ -144,7 +144,7 @@ NAN_METHOD(CallCredentials::Compose) {
   CallCredentials *self = ObjectWrap::Unwrap<CallCredentials>(info.This());
   CallCredentials *other = ObjectWrap::Unwrap<CallCredentials>(
       Nan::To<Object>(info[0]).ToLocalChecked());
-  grpc_credentials *creds = grpc_composite_credentials_create(
+  grpc_call_credentials *creds = grpc_composite_call_credentials_create(
       self->wrapped_credentials, other->wrapped_credentials, NULL);
   info.GetReturnValue().Set(WrapStruct(creds));
 }
@@ -162,8 +162,8 @@ NAN_METHOD(CallCredentials::CreateFromPlugin) {
   plugin.get_metadata = plugin_get_metadata;
   plugin.destroy = plugin_destroy_state;
   plugin.state = reinterpret_cast<void*>(state);
-  grpc_credentials *creds = grpc_metadata_credentials_create_from_plugin(plugin,
-                                                                         NULL);
+  grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(
+      plugin, NULL);
   info.GetReturnValue().Set(WrapStruct(creds));
 }
 
diff --git a/src/node/ext/call_credentials.h b/src/node/ext/call_credentials.h
index 618292d19e8b9b040f529e22b186b49da3fa3b7f..1cd8d8dd5d52451b6afa31d9e4d0de24a7884079 100644
--- a/src/node/ext/call_credentials.h
+++ b/src/node/ext/call_credentials.h
@@ -45,14 +45,14 @@ class CallCredentials : public Nan::ObjectWrap {
  public:
   static void Init(v8::Local<v8::Object> exports);
   static bool HasInstance(v8::Local<v8::Value> val);
-  /* Wrap a grpc_credentials struct in a javascript object */
-  static v8::Local<v8::Value> WrapStruct(grpc_credentials *credentials);
+  /* Wrap a grpc_call_credentials struct in a javascript object */
+  static v8::Local<v8::Value> WrapStruct(grpc_call_credentials *credentials);
 
-  /* Returns the grpc_credentials struct that this object wraps */
-  grpc_credentials *GetWrappedCredentials();
+  /* Returns the grpc_call_credentials struct that this object wraps */
+  grpc_call_credentials *GetWrappedCredentials();
 
  private:
-  explicit CallCredentials(grpc_credentials *credentials);
+  explicit CallCredentials(grpc_call_credentials *credentials);
   ~CallCredentials();
 
   // Prevent copying
@@ -68,7 +68,7 @@ class CallCredentials : public Nan::ObjectWrap {
   // Used for typechecking instances of this javascript class
   static Nan::Persistent<v8::FunctionTemplate> fun_tpl;
 
-  grpc_credentials *wrapped_credentials;
+  grpc_call_credentials *wrapped_credentials;
 };
 
 /* Auth metadata plugin functionality */
diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc
index 584a0cf8abfc8e81eaa480ae487daa096daea58e..00fcca6dc8417ca0f0a882be7412994e24ccb8d3 100644
--- a/src/node/ext/channel.cc
+++ b/src/node/ext/channel.cc
@@ -82,7 +82,7 @@ bool ParseChannelArgs(Local<Value> args_val,
     return false;
   }
   grpc_channel_args *channel_args = reinterpret_cast<grpc_channel_args*>(
-      malloc(sizeof(channel_args)));
+      malloc(sizeof(grpc_channel_args)));
   *channel_args_ptr = channel_args;
   Local<Object> args_hash = Nan::To<Object>(args_val).ToLocalChecked();
   Local<Array> keys = Nan::GetOwnPropertyNames(args_hash).ToLocalChecked();
@@ -177,7 +177,7 @@ NAN_METHOD(Channel::New) {
     grpc_channel *wrapped_channel;
     // Owned by the Channel object
     Utf8String host(info[0]);
-    grpc_credentials *creds;
+    grpc_channel_credentials *creds;
     if (!ChannelCredentials::HasInstance(info[1])) {
       return Nan::ThrowTypeError(
           "Channel's second argument must be a ChannelCredentials");
diff --git a/src/node/ext/channel_credentials.cc b/src/node/ext/channel_credentials.cc
index 7ca3b9816cfce9578e33d86b708e7f45846fe8d2..b77ff80af275f22f5b1c9f5966964f0f3455aa67 100644
--- a/src/node/ext/channel_credentials.cc
+++ b/src/node/ext/channel_credentials.cc
@@ -65,11 +65,11 @@ using v8::Value;
 Nan::Callback *ChannelCredentials::constructor;
 Persistent<FunctionTemplate> ChannelCredentials::fun_tpl;
 
-ChannelCredentials::ChannelCredentials(grpc_credentials *credentials)
+ChannelCredentials::ChannelCredentials(grpc_channel_credentials *credentials)
     : wrapped_credentials(credentials) {}
 
 ChannelCredentials::~ChannelCredentials() {
-  grpc_credentials_release(wrapped_credentials);
+  grpc_channel_credentials_release(wrapped_credentials);
 }
 
 void ChannelCredentials::Init(Local<Object> exports) {
@@ -95,7 +95,8 @@ bool ChannelCredentials::HasInstance(Local<Value> val) {
   return Nan::New(fun_tpl)->HasInstance(val);
 }
 
-Local<Value> ChannelCredentials::WrapStruct(grpc_credentials *credentials) {
+Local<Value> ChannelCredentials::WrapStruct(
+    grpc_channel_credentials *credentials) {
   EscapableHandleScope scope;
   const int argc = 1;
   Local<Value> argv[argc] = {
@@ -109,7 +110,7 @@ Local<Value> ChannelCredentials::WrapStruct(grpc_credentials *credentials) {
   }
 }
 
-grpc_credentials *ChannelCredentials::GetWrappedCredentials() {
+grpc_channel_credentials *ChannelCredentials::GetWrappedCredentials() {
   return wrapped_credentials;
 }
 
@@ -120,8 +121,8 @@ NAN_METHOD(ChannelCredentials::New) {
           "ChannelCredentials can only be created with the provided functions");
     }
     Local<External> ext = info[0].As<External>();
-    grpc_credentials *creds_value =
-        reinterpret_cast<grpc_credentials *>(ext->Value());
+    grpc_channel_credentials *creds_value =
+        reinterpret_cast<grpc_channel_credentials *>(ext->Value());
     ChannelCredentials *credentials = new ChannelCredentials(creds_value);
     credentials->Wrap(info.This());
     info.GetReturnValue().Set(info.This());
@@ -153,7 +154,7 @@ NAN_METHOD(ChannelCredentials::CreateSsl) {
     return Nan::ThrowTypeError(
         "createSSl's third argument must be a Buffer if provided");
   }
-  grpc_credentials *creds = grpc_ssl_credentials_create(
+  grpc_channel_credentials *creds = grpc_ssl_credentials_create(
       root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair,
       NULL);
   if (creds == NULL) {
@@ -180,7 +181,7 @@ NAN_METHOD(ChannelCredentials::Compose) {
   }
   CallCredentials *other = ObjectWrap::Unwrap<CallCredentials>(
       Nan::To<Object>(info[0]).ToLocalChecked());
-  grpc_credentials *creds = grpc_composite_credentials_create(
+  grpc_channel_credentials *creds = grpc_composite_channel_credentials_create(
       self->wrapped_credentials, other->GetWrappedCredentials(), NULL);
   if (creds == NULL) {
     info.GetReturnValue().SetNull();
diff --git a/src/node/ext/channel_credentials.h b/src/node/ext/channel_credentials.h
index 31ea0987bc659b7330b7bc851e9f3a0df1fbac68..89b115267f33e806ff8bb0d7154f152ba62773ad 100644
--- a/src/node/ext/channel_credentials.h
+++ b/src/node/ext/channel_credentials.h
@@ -42,19 +42,19 @@
 namespace grpc {
 namespace node {
 
-/* Wrapper class for grpc_credentials structs */
+/* Wrapper class for grpc_channel_credentials structs */
 class ChannelCredentials : public Nan::ObjectWrap {
  public:
   static void Init(v8::Local<v8::Object> exports);
   static bool HasInstance(v8::Local<v8::Value> val);
-  /* Wrap a grpc_credentials struct in a javascript object */
-  static v8::Local<v8::Value> WrapStruct(grpc_credentials *credentials);
+  /* Wrap a grpc_channel_credentials struct in a javascript object */
+  static v8::Local<v8::Value> WrapStruct(grpc_channel_credentials *credentials);
 
-  /* Returns the grpc_credentials struct that this object wraps */
-  grpc_credentials *GetWrappedCredentials();
+  /* Returns the grpc_channel_credentials struct that this object wraps */
+  grpc_channel_credentials *GetWrappedCredentials();
 
  private:
-  explicit ChannelCredentials(grpc_credentials *credentials);
+  explicit ChannelCredentials(grpc_channel_credentials *credentials);
   ~ChannelCredentials();
 
   // Prevent copying
@@ -70,7 +70,7 @@ class ChannelCredentials : public Nan::ObjectWrap {
   // Used for typechecking instances of this javascript class
   static Nan::Persistent<v8::FunctionTemplate> fun_tpl;
 
-  grpc_credentials *wrapped_credentials;
+  grpc_channel_credentials *wrapped_credentials;
 };
 
 }  // namespace node
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 3cdd55075242c750df019ff1936533d294cecd5e..d57826781d391d6872e6f00b757ee380ffa8a134 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -612,7 +612,15 @@ exports.makeClientConstructor = function(methods, serviceName) {
     if (!options) {
       options = {};
     }
-    options['grpc.primary_user_agent'] = 'grpc-node/' + version;
+    /* Append the grpc-node user agent string after the application user agent
+     * string, and put the combination at the beginning of the user agent string
+     */
+    if (options['grpc.primary_user_agent']) {
+      options['grpc.primary_user_agent'] += ' ';
+    } else {
+      options['grpc.primary_user_agent'] = '';
+    }
+    options['grpc.primary_user_agent'] += 'grpc-node/' + version;
     /* Private fields use $ as a prefix instead of _ because it is an invalid
      * prefix of a method name */
     this.$channel = new grpc.Channel(address, credentials, options);
diff --git a/src/node/test/credentials_test.js b/src/node/test/credentials_test.js
index 3e01b62cf49fd067c651b01388d84b7563084192..647f648ca93eb08332b58e879589a22d9160a5c0 100644
--- a/src/node/test/credentials_test.js
+++ b/src/node/test/credentials_test.js
@@ -71,7 +71,7 @@ var fakeSuccessfulGoogleCredentials = {
 var fakeFailingGoogleCredentials = {
   getRequestMetadata: function(service_url, callback) {
     setTimeout(function() {
-      callback(new Error('Authorization failure'));
+      callback(new Error('Authentication failure'));
     }, 0);
   }
 };
@@ -218,6 +218,25 @@ describe('client credentials', function() {
       done();
     });
   });
+  it('Should not add metadata with just SSL credentials', function(done) {
+    // Tests idempotency of credentials composition
+    var metadataUpdater = function(service_url, callback) {
+      var metadata = new grpc.Metadata();
+      metadata.set('plugin_key', 'plugin_value');
+      callback(null, metadata);
+    };
+    var creds = grpc.credentials.createFromMetadataGenerator(metadataUpdater);
+    grpc.credentials.combineChannelCredentials(client_ssl_creds, creds);
+    var client = new Client('localhost:' + port, client_ssl_creds,
+                            client_options);
+    var call = client.unary({}, function(err, data) {
+      assert.ifError(err);
+    });
+    call.on('metadata', function(metadata) {
+      assert.deepEqual(metadata.get('plugin_key'), []);
+      done();
+    });
+  });
   it.skip('should get an error from a Google credential', function(done) {
     var creds = grpc.credentials.createFromGoogleCredential(
         fakeFailingGoogleCredentials);
@@ -227,7 +246,7 @@ describe('client credentials', function() {
                             client_options);
     client.unary({}, function(err, data) {
       assert(err);
-      assert.strictEqual(err.message, 'Authorization failure');
+      assert.strictEqual(err.message, 'Authentication failure');
       done();
     });
   });
diff --git a/src/node/test/data/server1.pem b/src/node/test/data/server1.pem
index 8e582e571f643ca3fb6042a786c709a53f5afcf3..f3d43fcc5beadd98542abdaa32acfb555b807559 100644
--- a/src/node/test/data/server1.pem
+++ b/src/node/test/data/server1.pem
@@ -1,16 +1,16 @@
 -----BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
-MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
-MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
-BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
-c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
-JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
-RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
-3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
-BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
-b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
-KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
-wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
-aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
+MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
+MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
+BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
+ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
+LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
+zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
+9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
+CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
+em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
+CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
+hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
+y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
 -----END CERTIFICATE-----
diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannel.h b/src/objective-c/GRPCClient/private/GRPCSecureChannel.h
index 4e0881e5a2a32b3c2a3787743026103e823f3dca..b82b9fe35acd90d4cb38802eca886f5ac8297a16 100644
--- a/src/objective-c/GRPCClient/private/GRPCSecureChannel.h
+++ b/src/objective-c/GRPCClient/private/GRPCSecureChannel.h
@@ -35,7 +35,7 @@
 
 #import "GRPCChannel.h"
 
-struct grpc_credentials;
+struct grpc_channel_credentials;
 
 @interface GRPCSecureChannel : GRPCChannel
 - (instancetype)initWithHost:(NSString *)host;
@@ -50,6 +50,6 @@ struct grpc_credentials;
 
 /** The passed arguments aren't required to be valid beyond the invocation of this initializer. */
 - (instancetype)initWithHost:(NSString *)host
-                 credentials:(struct grpc_credentials *)credentials
+                 credentials:(struct grpc_channel_credentials *)credentials
                         args:(grpc_channel_args *)args NS_DESIGNATED_INITIALIZER;
 @end
diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannel.m b/src/objective-c/GRPCClient/private/GRPCSecureChannel.m
index ce166553300e5f2a5bd9d69c8c4deba91e301943..a573c171e93ec6b1f900d5225a1c42543f300cb6 100644
--- a/src/objective-c/GRPCClient/private/GRPCSecureChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCSecureChannel.m
@@ -37,7 +37,7 @@
 
 // Returns NULL if the file at path couldn't be read. In that case, if errorPtr isn't NULL,
 // *errorPtr will be an object describing what went wrong.
-static grpc_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr) {
+static grpc_channel_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr) {
   // Files in PEM format can have non-ASCII characters in their comments (e.g. for the name of the
   // issuer). Load them as UTF8 and produce an ASCII equivalent.
   NSString *contentInUTF8 = [NSString stringWithContentsOfFile:path
@@ -62,7 +62,7 @@ static grpc_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr)
           pathToCertificates:(NSString *)path
             hostNameOverride:(NSString *)hostNameOverride {
   // Load default SSL certificates once.
-  static grpc_credentials *kDefaultCertificates;
+  static grpc_channel_credentials *kDefaultCertificates;
   static dispatch_once_t loading;
   dispatch_once(&loading, ^{
     NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem
@@ -79,7 +79,9 @@ static grpc_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr)
   });
 
   //TODO(jcanizales): Add NSError** parameter to the initializer.
-  grpc_credentials *certificates = path ? CertificatesAtPath(path, NULL) : kDefaultCertificates;
+  grpc_channel_credentials *certificates = path
+      ? CertificatesAtPath(path, NULL)
+      : kDefaultCertificates;
   if (!certificates) {
     return nil;
   }
@@ -99,7 +101,7 @@ static grpc_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr)
 }
 
 - (instancetype)initWithHost:(NSString *)host
-                 credentials:(grpc_credentials *)credentials
+                 credentials:(grpc_channel_credentials *)credentials
                         args:(grpc_channel_args *)args {
   return (self = [super
               initWithChannel:grpc_secure_channel_create(
diff --git a/src/objective-c/examples/Sample/Podfile b/src/objective-c/examples/Sample/Podfile
index 72308c1619294e04d890374d72fbbf4e3c3f621d..3b2f41256940c4931638bf5b422d03e08adf72f2 100644
--- a/src/objective-c/examples/Sample/Podfile
+++ b/src/objective-c/examples/Sample/Podfile
@@ -1,8 +1,9 @@
 source 'https://github.com/CocoaPods/Specs.git'
 platform :ios, '8.0'
 
+pod 'Protobuf', :path => "../../../../third_party/protobuf"
 pod 'gRPC', :path => "../../../.."
-pod 'RemoteTest', :path => "../../generated_libraries/RemoteTestClient"
+pod 'RemoteTest', :path => "../RemoteTestClient"
 
 target 'Sample' do
 end
diff --git a/src/objective-c/examples/Sample/Sample/ViewController.m b/src/objective-c/examples/Sample/Sample/ViewController.m
index 05bd6fa2dbc5c5ba8be85cfc8e2c7a9c89f39952..3d634a340df6dad79715fc9a91f7d0216262bf71 100644
--- a/src/objective-c/examples/Sample/Sample/ViewController.m
+++ b/src/objective-c/examples/Sample/Sample/ViewController.m
@@ -34,7 +34,7 @@
 #import "ViewController.h"
 
 #import <GRPCClient/GRPCCall.h>
-#import <GRPCClient/GRPCMethodName.h>
+#import <ProtoRPC/ProtoMethod.h>
 #import <RemoteTest/Messages.pbobjc.h>
 #import <RemoteTest/Test.pbrpc.h>
 #import <RxLibrary/GRXWriter+Immediate.h>
@@ -66,14 +66,14 @@
 
   // Same example call using the generic gRPC client library:
 
-  GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing"
-                                                         interface:@"TestService"
-                                                            method:@"UnaryCall"];
+  ProtoMethod *method = [[ProtoMethod alloc] initWithPackage:@"grpc.testing"
+                                                     service:@"TestService"
+                                                      method:@"UnaryCall"];
 
-  id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[request data]];
+  GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
 
   GRPCCall *call = [[GRPCCall alloc] initWithHost:kRemoteHost
-                                           method:method
+                                             path:method.HTTPPath
                                    requestsWriter:requestsWriter];
 
   id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
diff --git a/src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.podspec b/src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.podspec
deleted file mode 100644
index 23ccffe69dacd61f397e99b5b12734b6fb4ee14b..0000000000000000000000000000000000000000
--- a/src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.podspec
+++ /dev/null
@@ -1,31 +0,0 @@
-Pod::Spec.new do |s|
-  s.name     = "RouteGuide"
-  s.version  = "0.0.1"
-  s.license  = "New BSD"
-
-  s.ios.deployment_target = "6.0"
-  s.osx.deployment_target = "10.8"
-
-  # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
-  s.prepare_command = <<-CMD
-    BINDIR=../../../../bins/$CONFIG
-    PROTOC=$BINDIR/protobuf/protoc
-    PLUGIN=$BINDIR/grpc_objective_c_plugin
-    $PROTOC --plugin=protoc-gen-grpc=$PLUGIN --objc_out=. --grpc_out=. *.proto
-  CMD
-
-  s.subspec "Messages" do |ms|
-    ms.source_files = "*.pbobjc.{h,m}"
-    ms.header_mappings_dir = "."
-    ms.requires_arc = false
-    ms.dependency "Protobuf", "~> 3.0.0-alpha-3"
-  end
-
-  s.subspec "Services" do |ss|
-    ss.source_files = "*.pbrpc.{h,m}"
-    ss.header_mappings_dir = "."
-    ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.5"
-    ss.dependency "#{s.name}/Messages"
-  end
-end
diff --git a/src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto b/src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto
deleted file mode 100644
index 19592e2ebdd6fa88fb384a0305a790a8a0d4218e..0000000000000000000000000000000000000000
--- a/src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto3";
-
-package routeguide;
-
-option objc_class_prefix = "RGD";
-
-// Interface exported by the server.
-service RouteGuide {
-  // A simple RPC.
-  //
-  // Obtains the feature at a given position.
-  rpc GetFeature(Point) returns (Feature) {}
-
-  // A server-to-client streaming RPC.
-  //
-  // Obtains the Features available within the given Rectangle.  Results are
-  // streamed rather than returned at once (e.g. in a response message with a
-  // repeated field), as the rectangle may cover a large area and contain a
-  // huge number of features.
-  rpc ListFeatures(Rectangle) returns (stream Feature) {}
-
-  // A client-to-server streaming RPC.
-  //
-  // Accepts a stream of Points on a route being traversed, returning a
-  // RouteSummary when traversal is completed.
-  rpc RecordRoute(stream Point) returns (RouteSummary) {}
-
-  // A Bidirectional streaming RPC.
-  //
-  // Accepts a stream of RouteNotes sent while a route is being traversed,
-  // while receiving other RouteNotes (e.g. from other users).
-  rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
-}
-
-// Points are represented as latitude-longitude pairs in the E7 representation
-// (degrees multiplied by 10**7 and rounded to the nearest integer).
-// Latitudes should be in the range +/- 90 degrees and longitude should be in
-// the range +/- 180 degrees (inclusive).
-message Point {
-  int32 latitude = 1;
-  int32 longitude = 2;
-}
-
-// A latitude-longitude rectangle, represented as two diagonally opposite
-// points "lo" and "hi".
-message Rectangle {
-  // One corner of the rectangle.
-  Point lo = 1;
-
-  // The other corner of the rectangle.
-  Point hi = 2;
-}
-
-// A feature names something at a given point.
-//
-// If a feature could not be named, the name is empty.
-message Feature {
-  // The name of the feature.
-  string name = 1;
-
-  // The point where the feature is detected.
-  Point location = 2;
-}
-
-// A RouteNote is a message sent while at a given point.
-message RouteNote {
-  // The location from which the message is sent.
-  Point location = 1;
-
-  // The message to be sent.
-  string message = 2;
-}
-
-// A RouteSummary is received in response to a RecordRoute rpc.
-//
-// It contains the number of individual points received, the number of
-// detected features, and the total distance covered as the cumulative sum of
-// the distance between each point.
-message RouteSummary {
-  // The number of points received.
-  int32 point_count = 1;
-
-  // The number of known features passed while traversing the route.
-  int32 feature_count = 2;
-
-  // The distance covered in metres.
-  int32 distance = 3;
-
-  // The duration of the traversal in seconds.
-  int32 elapsed_time = 4;
-}
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index 2a9b894cf631c8a46b19543e69ae8809ab7b522b..cab608d37fee7df15ad461ffe08a6501f9ea3b3c 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -3,8 +3,7 @@ platform :ios, '8.0'
 
 pod 'Protobuf', :path => "../../../third_party/protobuf"
 pod 'gRPC', :path => "../../.."
-pod 'RemoteTest', :path => "../generated_libraries/RemoteTestClient"
-pod 'RouteGuide', :path => "../generated_libraries/RouteGuideClient"
+pod 'RemoteTest', :path => "RemoteTestClient"
 
 link_with 'AllTests',
           'RxLibraryUnitTests',
diff --git a/src/objective-c/generated_libraries/RemoteTestClient/RemoteTest.podspec b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
similarity index 100%
rename from src/objective-c/generated_libraries/RemoteTestClient/RemoteTest.podspec
rename to src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
diff --git a/src/objective-c/generated_libraries/RemoteTestClient/empty.proto b/src/objective-c/tests/RemoteTestClient/empty.proto
similarity index 100%
rename from src/objective-c/generated_libraries/RemoteTestClient/empty.proto
rename to src/objective-c/tests/RemoteTestClient/empty.proto
diff --git a/src/objective-c/generated_libraries/RemoteTestClient/messages.proto b/src/objective-c/tests/RemoteTestClient/messages.proto
similarity index 100%
rename from src/objective-c/generated_libraries/RemoteTestClient/messages.proto
rename to src/objective-c/tests/RemoteTestClient/messages.proto
diff --git a/src/objective-c/generated_libraries/RemoteTestClient/test.proto b/src/objective-c/tests/RemoteTestClient/test.proto
similarity index 100%
rename from src/objective-c/generated_libraries/RemoteTestClient/test.proto
rename to src/objective-c/tests/RemoteTestClient/test.proto
diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c
new file mode 100644
index 0000000000000000000000000000000000000000..17f167befb09e78e34777f3ce4b1444297f658bf
--- /dev/null
+++ b/src/php/ext/grpc/call_credentials.c
@@ -0,0 +1,138 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "channel_credentials.h"
+#include "call_credentials.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <php.h>
+#include <php_ini.h>
+#include <ext/standard/info.h>
+#include <ext/spl/spl_exceptions.h>
+#include "php_grpc.h"
+
+#include <zend_exceptions.h>
+#include <zend_hash.h>
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+
+zend_class_entry *grpc_ce_call_credentials;
+
+/* Frees and destroys an instance of wrapped_grpc_call_credentials */
+void free_wrapped_grpc_call_credentials(void *object TSRMLS_DC) {
+  wrapped_grpc_call_credentials *creds =
+      (wrapped_grpc_call_credentials *)object;
+  if (creds->wrapped != NULL) {
+    grpc_call_credentials_release(creds->wrapped);
+  }
+  efree(creds);
+}
+
+/* Initializes an instance of wrapped_grpc_call_credentials to be
+ * associated with an object of a class specified by class_type */
+zend_object_value create_wrapped_grpc_call_credentials(
+    zend_class_entry *class_type TSRMLS_DC) {
+  zend_object_value retval;
+  wrapped_grpc_call_credentials *intern;
+
+  intern = (wrapped_grpc_call_credentials *)emalloc(
+      sizeof(wrapped_grpc_call_credentials));
+  memset(intern, 0, sizeof(wrapped_grpc_call_credentials));
+
+  zend_object_std_init(&intern->std, class_type TSRMLS_CC);
+  object_properties_init(&intern->std, class_type);
+  retval.handle = zend_objects_store_put(
+      intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
+      free_wrapped_grpc_call_credentials, NULL TSRMLS_CC);
+  retval.handlers = zend_get_std_object_handlers();
+  return retval;
+}
+
+zval *grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped) {
+  zval *credentials_object;
+  MAKE_STD_ZVAL(credentials_object);
+  object_init_ex(credentials_object, grpc_ce_call_credentials);
+  wrapped_grpc_call_credentials *credentials =
+      (wrapped_grpc_call_credentials *)zend_object_store_get_object(
+          credentials_object TSRMLS_CC);
+  credentials->wrapped = wrapped;
+  return credentials_object;
+}
+
+/**
+ * Create composite credentials from two existing credentials.
+ * @param CallCredentials cred1 The first credential
+ * @param CallCredentials cred2 The second credential
+ * @return CallCredentials The new composite credentials object
+ */
+PHP_METHOD(CallCredentials, createComposite) {
+  zval *cred1_obj;
+  zval *cred2_obj;
+
+  /* "OO" == 3 Objects */
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj,
+                            grpc_ce_call_credentials, &cred2_obj,
+                            grpc_ce_call_credentials) == FAILURE) {
+    zend_throw_exception(spl_ce_InvalidArgumentException,
+                         "createComposite expects 2 CallCredentials",
+                         1 TSRMLS_CC);
+    return;
+  }
+  wrapped_grpc_call_credentials *cred1 =
+      (wrapped_grpc_call_credentials *)zend_object_store_get_object(
+          cred1_obj TSRMLS_CC);
+  wrapped_grpc_call_credentials *cred2 =
+      (wrapped_grpc_call_credentials *)zend_object_store_get_object(
+          cred2_obj TSRMLS_CC);
+  grpc_call_credentials *creds =
+      grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped,
+                                             NULL);
+  zval *creds_object = grpc_php_wrap_call_credentials(creds);
+  RETURN_DESTROY_ZVAL(creds_object);
+}
+
+static zend_function_entry call_credentials_methods[] = {
+  PHP_ME(CallCredentials, createComposite, NULL,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_FE_END};
+
+void grpc_init_call_credentials(TSRMLS_D) {
+  zend_class_entry ce;
+  INIT_CLASS_ENTRY(ce, "Grpc\\CallCredentials", call_credentials_methods);
+  ce.create_object = create_wrapped_grpc_call_credentials;
+  grpc_ce_call_credentials = zend_register_internal_class(&ce TSRMLS_CC);
+}
diff --git a/src/php/ext/grpc/credentials.h b/src/php/ext/grpc/call_credentials.h
similarity index 76%
rename from src/php/ext/grpc/credentials.h
rename to src/php/ext/grpc/call_credentials.h
index 86d7ae5b144c983726a861674bbb7a0414f00e31..8f35ac68bc1b7e10543e712e2e5c8d6faf8f3eb5 100755
--- a/src/php/ext/grpc/credentials.h
+++ b/src/php/ext/grpc/call_credentials.h
@@ -31,8 +31,8 @@
  *
  */
 
-#ifndef NET_GRPC_PHP_GRPC_CREDENTIALS_H_
-#define NET_GRPC_PHP_GRPC_CREDENTIALS_H_
+#ifndef NET_GRPC_PHP_GRPC_CALL_CREDENTIALS_H_
+#define NET_GRPC_PHP_GRPC_CALL_CREDENTIALS_H_
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -46,18 +46,18 @@
 #include "grpc/grpc.h"
 #include "grpc/grpc_security.h"
 
-/* Class entry for the Credentials PHP class */
-extern zend_class_entry *grpc_ce_credentials;
+/* Class entry for the CallCredentials PHP class */
+extern zend_class_entry *grpc_ce_call_credentials;
 
-/* Wrapper struct for grpc_credentials that can be associated with a PHP
- * object */
-typedef struct wrapped_grpc_credentials {
+/* Wrapper struct for grpc_call_credentials that can be associated
+ * with a PHP object */
+typedef struct wrapped_grpc_call_credentials {
   zend_object std;
 
-  grpc_credentials *wrapped;
-} wrapped_grpc_credentials;
+  grpc_call_credentials *wrapped;
+} wrapped_grpc_call_credentials;
 
-/* Initializes the Credentials PHP class */
-void grpc_init_credentials(TSRMLS_D);
+/* Initializes the CallCredentials PHP class */
+void grpc_init_call_credentials(TSRMLS_D);
 
-#endif /* NET_GRPC_PHP_GRPC_CREDENTIALS_H_ */
+#endif /* NET_GRPC_PHP_GRPC_CALL_CREDENTIALS_H_ */
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index a4313b6bd4c0b563d347cd91fa68816815d6b85e..f8c4f0423f2660012ac155ca2f76f5685a5e7a31 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -52,7 +52,7 @@
 #include <grpc/grpc_security.h>
 
 #include "completion_queue.h"
-#include "credentials.h"
+#include "channel_credentials.h"
 #include "server.h"
 #include "timeval.h"
 
@@ -125,21 +125,22 @@ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args) {
 
 /**
  * Construct an instance of the Channel class. If the $args array contains a
- * "credentials" key mapping to a Credentials object, a secure channel will be
- * created with those credentials.
+ * "credentials" key mapping to a ChannelCredentials object, a secure channel
+ * will be created with those credentials.
  * @param string $target The hostname to associate with this channel
  * @param array $args The arguments to pass to the Channel (optional)
  */
 PHP_METHOD(Channel, __construct) {
   wrapped_grpc_channel *channel =
-      (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
+      (wrapped_grpc_channel *)zend_object_store_get_object(
+          getThis() TSRMLS_CC);
   char *target;
   int target_length;
   zval *args_array = NULL;
   grpc_channel_args args;
   HashTable *array_hash;
   zval **creds_obj = NULL;
-  wrapped_grpc_credentials *creds = NULL;
+  wrapped_grpc_channel_credentials *creds = NULL;
   /* "s|a" == 1 string, 1 optional array */
   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a", &target,
                             &target_length, &args_array) == FAILURE) {
@@ -153,13 +154,14 @@ PHP_METHOD(Channel, __construct) {
     array_hash = Z_ARRVAL_P(args_array);
     if (zend_hash_find(array_hash, "credentials", sizeof("credentials"),
                        (void **)&creds_obj) == SUCCESS) {
-      if (zend_get_class_entry(*creds_obj TSRMLS_CC) != grpc_ce_credentials) {
+      if (zend_get_class_entry(*creds_obj TSRMLS_CC) !=
+          grpc_ce_channel_credentials) {
         zend_throw_exception(spl_ce_InvalidArgumentException,
-                             "credentials must be a Credentials object",
+                             "credentials must be a ChannelCredentials object",
                              1 TSRMLS_CC);
         return;
       }
-      creds = (wrapped_grpc_credentials *)zend_object_store_get_object(
+      creds = (wrapped_grpc_channel_credentials *)zend_object_store_get_object(
           *creds_obj TSRMLS_CC);
       zend_hash_del(array_hash, "credentials", 12);
     }
diff --git a/src/php/ext/grpc/credentials.c b/src/php/ext/grpc/channel_credentials.c
similarity index 55%
rename from src/php/ext/grpc/credentials.c
rename to src/php/ext/grpc/channel_credentials.c
index e413070b4531cc2e0218d4796d014e88b8d89c6a..df4a5d516246829bd02ffdaf6cf49f53039361c3 100644
--- a/src/php/ext/grpc/credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -31,7 +31,8 @@
  *
  */
 
-#include "credentials.h"
+#include "channel_credentials.h"
+#include "call_credentials.h"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -49,55 +50,56 @@
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
 
-zend_class_entry *grpc_ce_credentials;
+zend_class_entry *grpc_ce_channel_credentials;
 
-/* Frees and destroys an instance of wrapped_grpc_credentials */
-void free_wrapped_grpc_credentials(void *object TSRMLS_DC) {
-  wrapped_grpc_credentials *creds = (wrapped_grpc_credentials *)object;
+/* Frees and destroys an instance of wrapped_grpc_channel_credentials */
+void free_wrapped_grpc_channel_credentials(void *object TSRMLS_DC) {
+  wrapped_grpc_channel_credentials *creds =
+      (wrapped_grpc_channel_credentials *)object;
   if (creds->wrapped != NULL) {
-    grpc_credentials_release(creds->wrapped);
+    grpc_channel_credentials_release(creds->wrapped);
   }
   efree(creds);
 }
 
-/* Initializes an instance of wrapped_grpc_credentials to be associated with an
- * object of a class specified by class_type */
-zend_object_value create_wrapped_grpc_credentials(zend_class_entry *class_type
-                                                      TSRMLS_DC) {
+/* Initializes an instance of wrapped_grpc_channel_credentials to be
+ * associated with an object of a class specified by class_type */
+zend_object_value create_wrapped_grpc_channel_credentials(
+    zend_class_entry *class_type TSRMLS_DC) {
   zend_object_value retval;
-  wrapped_grpc_credentials *intern;
+  wrapped_grpc_channel_credentials *intern;
 
-  intern =
-      (wrapped_grpc_credentials *)emalloc(sizeof(wrapped_grpc_credentials));
-  memset(intern, 0, sizeof(wrapped_grpc_credentials));
+  intern = (wrapped_grpc_channel_credentials *)emalloc(
+      sizeof(wrapped_grpc_channel_credentials));
+  memset(intern, 0, sizeof(wrapped_grpc_channel_credentials));
 
   zend_object_std_init(&intern->std, class_type TSRMLS_CC);
   object_properties_init(&intern->std, class_type);
   retval.handle = zend_objects_store_put(
       intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
-      free_wrapped_grpc_credentials, NULL TSRMLS_CC);
+      free_wrapped_grpc_channel_credentials, NULL TSRMLS_CC);
   retval.handlers = zend_get_std_object_handlers();
   return retval;
 }
 
-zval *grpc_php_wrap_credentials(grpc_credentials *wrapped) {
+zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped) {
   zval *credentials_object;
   MAKE_STD_ZVAL(credentials_object);
-  object_init_ex(credentials_object, grpc_ce_credentials);
-  wrapped_grpc_credentials *credentials =
-      (wrapped_grpc_credentials *)zend_object_store_get_object(
+  object_init_ex(credentials_object, grpc_ce_channel_credentials);
+  wrapped_grpc_channel_credentials *credentials =
+      (wrapped_grpc_channel_credentials *)zend_object_store_get_object(
           credentials_object TSRMLS_CC);
   credentials->wrapped = wrapped;
   return credentials_object;
 }
 
 /**
- * Create a default credentials object.
- * @return Credentials The new default credentials object
+ * Create a default channel credentials object.
+ * @return ChannelCredentials The new default channel credentials object
  */
-PHP_METHOD(Credentials, createDefault) {
-  grpc_credentials *creds = grpc_google_default_credentials_create();
-  zval *creds_object = grpc_php_wrap_credentials(creds);
+PHP_METHOD(ChannelCredentials, createDefault) {
+  grpc_channel_credentials *creds = grpc_google_default_credentials_create();
+  zval *creds_object = grpc_php_wrap_channel_credentials(creds);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
@@ -108,9 +110,9 @@ PHP_METHOD(Credentials, createDefault) {
  *     (optional)
  * @param string pem_cert_chain PEM encoding of the client's certificate chain
  *     (optional)
- * @return Credentials The new SSL credentials object
+ * @return ChannelCredentials The new SSL credentials object
  */
-PHP_METHOD(Credentials, createSsl) {
+PHP_METHOD(ChannelCredentials, createSsl) {
   char *pem_root_certs = NULL;
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
 
@@ -121,71 +123,65 @@ PHP_METHOD(Credentials, createSsl) {
   /* "|s!s!s! == 3 optional nullable strings */
   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!",
                             &pem_root_certs, &root_certs_length,
-                            &pem_key_cert_pair.private_key, &private_key_length,
+                            &pem_key_cert_pair.private_key,
+                            &private_key_length,
                             &pem_key_cert_pair.cert_chain,
                             &cert_chain_length) == FAILURE) {
     zend_throw_exception(spl_ce_InvalidArgumentException,
                          "createSsl expects 3 optional strings", 1 TSRMLS_CC);
     return;
   }
-  grpc_credentials *creds = grpc_ssl_credentials_create(
+  grpc_channel_credentials *creds = grpc_ssl_credentials_create(
       pem_root_certs,
       pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
-  zval *creds_object = grpc_php_wrap_credentials(creds);
+  zval *creds_object = grpc_php_wrap_channel_credentials(creds);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
 /**
  * Create composite credentials from two existing credentials.
- * @param Credentials cred1 The first credential
- * @param Credentials cred2 The second credential
- * @return Credentials The new composite credentials object
+ * @param ChannelCredentials cred1 The first credential
+ * @param CallCredentials cred2 The second credential
+ * @return ChannelCredentials The new composite credentials object
  */
-PHP_METHOD(Credentials, createComposite) {
+PHP_METHOD(ChannelCredentials, createComposite) {
   zval *cred1_obj;
   zval *cred2_obj;
 
   /* "OO" == 3 Objects */
   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj,
-                            grpc_ce_credentials, &cred2_obj,
-                            grpc_ce_credentials) == FAILURE) {
+                            grpc_ce_channel_credentials, &cred2_obj,
+                            grpc_ce_call_credentials) == FAILURE) {
     zend_throw_exception(spl_ce_InvalidArgumentException,
                          "createComposite expects 2 Credentials", 1 TSRMLS_CC);
     return;
   }
-  wrapped_grpc_credentials *cred1 =
-      (wrapped_grpc_credentials *)zend_object_store_get_object(
+  wrapped_grpc_channel_credentials *cred1 =
+      (wrapped_grpc_channel_credentials *)zend_object_store_get_object(
           cred1_obj TSRMLS_CC);
-  wrapped_grpc_credentials *cred2 =
-      (wrapped_grpc_credentials *)zend_object_store_get_object(
+  wrapped_grpc_call_credentials *cred2 =
+      (wrapped_grpc_call_credentials *)zend_object_store_get_object(
           cred2_obj TSRMLS_CC);
-  grpc_credentials *creds =
-      grpc_composite_credentials_create(cred1->wrapped, cred2->wrapped, NULL);
-  zval *creds_object = grpc_php_wrap_credentials(creds);
+  grpc_channel_credentials *creds =
+      grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped,
+                                                NULL);
+  zval *creds_object = grpc_php_wrap_channel_credentials(creds);
   RETURN_DESTROY_ZVAL(creds_object);
 }
 
-/**
- * Create Google Compute Engine credentials
- * @return Credentials The new GCE credentials object
- */
-PHP_METHOD(Credentials, createGce) {
-  grpc_credentials *creds = grpc_google_compute_engine_credentials_create(NULL);
-  zval *creds_object = grpc_php_wrap_credentials(creds);
-  RETURN_DESTROY_ZVAL(creds_object);
-}
-
-static zend_function_entry credentials_methods[] = {
-    PHP_ME(Credentials, createDefault, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-    PHP_ME(Credentials, createSsl, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-    PHP_ME(Credentials, createComposite, NULL,
-           ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-    PHP_ME(Credentials, createGce, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-    PHP_FE_END};
+static zend_function_entry channel_credentials_methods[] = {
+  PHP_ME(ChannelCredentials, createDefault, NULL,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(ChannelCredentials, createSsl, NULL,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_ME(ChannelCredentials, createComposite, NULL,
+         ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+  PHP_FE_END};
 
-void grpc_init_credentials(TSRMLS_D) {
+void grpc_init_channel_credentials(TSRMLS_D) {
   zend_class_entry ce;
-  INIT_CLASS_ENTRY(ce, "Grpc\\Credentials", credentials_methods);
-  ce.create_object = create_wrapped_grpc_credentials;
-  grpc_ce_credentials = zend_register_internal_class(&ce TSRMLS_CC);
+  INIT_CLASS_ENTRY(ce, "Grpc\\ChannelCredentials",
+                   channel_credentials_methods);
+  ce.create_object = create_wrapped_grpc_channel_credentials;
+  grpc_ce_channel_credentials = zend_register_internal_class(&ce TSRMLS_CC);
 }
diff --git a/src/php/ext/grpc/channel_credentials.h b/src/php/ext/grpc/channel_credentials.h
new file mode 100755
index 0000000000000000000000000000000000000000..d89984ce604076ee41a8a2b97e05391857e15060
--- /dev/null
+++ b/src/php/ext/grpc/channel_credentials.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef NET_GRPC_PHP_GRPC_CHANNEL_CREDENTIALS_H_
+#define NET_GRPC_PHP_GRPC_CHANNEL_CREDENTIALS_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_grpc.h"
+
+#include "grpc/grpc.h"
+#include "grpc/grpc_security.h"
+
+/* Class entry for the ChannelCredentials PHP class */
+extern zend_class_entry *grpc_ce_channel_credentials;
+
+/* Wrapper struct for grpc_channel_credentials that can be associated
+ * with a PHP object */
+typedef struct wrapped_grpc_channel_credentials {
+  zend_object std;
+
+  grpc_channel_credentials *wrapped;
+} wrapped_grpc_channel_credentials;
+
+/* Initializes the ChannelCredentials PHP class */
+void grpc_init_channel_credentials(TSRMLS_D);
+
+#endif /* NET_GRPC_PHP_GRPC_CHANNEL_CREDENTIALS_H_ */
diff --git a/src/php/ext/grpc/config.m4 b/src/php/ext/grpc/config.m4
index 8bacdfbfecac1ea6537d266896ad85947ec4ec09..792868794315323c1b454ceb87b1ad80c93eb81c 100755
--- a/src/php/ext/grpc/config.m4
+++ b/src/php/ext/grpc/config.m4
@@ -71,5 +71,7 @@ if test "$PHP_GRPC" != "no"; then
 
   PHP_SUBST(GRPC_SHARED_LIBADD)
 
-  PHP_NEW_EXTENSION(grpc, byte_buffer.c call.c channel.c completion_queue.c credentials.c timeval.c server.c server_credentials.c php_grpc.c, $ext_shared, , -Wall -Werror -std=c11)
+  PHP_NEW_EXTENSION(grpc, byte_buffer.c call.c call_credentials.c channel.c \
+    channel_credentials.c completion_queue.c timeval.c server.c \
+    server_credentials.c php_grpc.c, $ext_shared, , -Wall -Werror -std=c11)
 fi
diff --git a/src/php/ext/grpc/package.xml b/src/php/ext/grpc/package.xml
index 921cfc6ae68d085120331c0de9db36ff4f2f7d69..a2e3e2826a77441e92947c42f0f2ec0c39063f0c 100644
--- a/src/php/ext/grpc/package.xml
+++ b/src/php/ext/grpc/package.xml
@@ -10,8 +10,8 @@
   <email>grpc-packages@google.com</email>
   <active>yes</active>
  </lead>
- <date>2015-10-07</date>
- <time>13:40:54</time>
+ <date>2015-10-21</date>
+ <time>17:04:32</time>
  <version>
   <release>0.6.1</release>
   <api>0.6.0</api>
@@ -30,16 +30,18 @@
    <file baseinstalldir="/" md5sum="c8de0f819499c48adfc8d7f472c0196b" name="byte_buffer.h" role="src" />
    <file baseinstalldir="/" md5sum="d64c9005993de02abac55664b0b9e0b2" name="call.c" role="src" />
    <file baseinstalldir="/" md5sum="26acbf04c30162c2d2aca4688bb2aec8" name="call.h" role="src" />
-   <file baseinstalldir="/" md5sum="15e56239b32c803f073e8a2b9f96e8c3" name="channel.c" role="src" />
+   <file baseinstalldir="/" md5sum="6fa13d260dfde216f795225644f04e7a" name="call_credentials.c" role="src" />
+   <file baseinstalldir="/" md5sum="e45269975f9a30fd349a90daf6b31aa2" name="call_credentials.h" role="src" />
+   <file baseinstalldir="/" md5sum="0779db3b196c98081b2260ceec22cd4d" name="channel.c" role="src" />
    <file baseinstalldir="/" md5sum="ed4b00c0cf3702b115d0cfa87450dc09" name="channel.h" role="src" />
+   <file baseinstalldir="/" md5sum="1b40f50fa6184ad7d24a961ac76151ff" name="channel_credentials.c" role="src" />
+   <file baseinstalldir="/" md5sum="a86250e03f610ce6c2c7595a84e08821" name="channel_credentials.h" role="src" />
    <file baseinstalldir="/" md5sum="55ab7a42f9dd9bfc7e28a61cfc5fca63" name="completion_queue.c" role="src" />
    <file baseinstalldir="/" md5sum="f10b5bb232d74a6878e829e2e76cdaa2" name="completion_queue.h" role="src" />
-   <file baseinstalldir="/" md5sum="a22f8eac0164761058cc4d9eb2ceb069" name="config.m4" role="src" />
-   <file baseinstalldir="/" md5sum="588752c908f7bc1663f7b8fc922ae661" name="credentials.c" role="src" />
-   <file baseinstalldir="/" md5sum="6988d6e97c19c8f8e3eb92371cf8246b" name="credentials.h" role="src" />
+   <file baseinstalldir="/" md5sum="c7bba7f0f00d1b1483de457d55311382" name="config.m4" role="src" />
    <file baseinstalldir="/" md5sum="38a1bc979d810c36ebc2a52d4b7b5319" name="CREDITS" role="doc" />
    <file baseinstalldir="/" md5sum="3f35b472bbdef5a788cd90617d7d0847" name="LICENSE" role="doc" />
-   <file baseinstalldir="/" md5sum="b77f1f3941aaf7a21090b493e9f26037" name="php_grpc.c" role="src" />
+   <file baseinstalldir="/" md5sum="3131a8af38fe5918e5409016b89d6cdb" name="php_grpc.c" role="src" />
    <file baseinstalldir="/" md5sum="673b07859d9f69232f8a754c56780686" name="php_grpc.h" role="src" />
    <file baseinstalldir="/" md5sum="7533a6d3ea02c78cad23a9651de0825d" name="README.md" role="doc" />
    <file baseinstalldir="/" md5sum="3e4e960454ebb2fc7b78a840493f5315" name="server.c" role="src" />
@@ -122,7 +124,7 @@ Update to wrap gRPC C Core version 0.10.0
     <release>beta</release>
     <api>beta</api>
    </stability>
-   <date>2015-10-07</date>
+   <date>2015-10-21</date>
    <license>BSD</license>
    <notes>
 - fixed undefined constant fatal error when run with apache/nginx #2275
diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c
index fcd94a6306230db39d60f2ede6305c950978931c..762c01385c95fae2a894986f953b8c9d07f59526 100644
--- a/src/php/ext/grpc/php_grpc.c
+++ b/src/php/ext/grpc/php_grpc.c
@@ -35,7 +35,8 @@
 #include "channel.h"
 #include "server.h"
 #include "timeval.h"
-#include "credentials.h"
+#include "channel_credentials.h"
+#include "call_credentials.h"
 #include "server_credentials.h"
 #include "completion_queue.h"
 
@@ -233,7 +234,8 @@ PHP_MINIT_FUNCTION(grpc) {
   grpc_init_channel(TSRMLS_C);
   grpc_init_server(TSRMLS_C);
   grpc_init_timeval(TSRMLS_C);
-  grpc_init_credentials(TSRMLS_C);
+  grpc_init_channel_credentials(TSRMLS_C);
+  grpc_init_call_credentials(TSRMLS_C);
   grpc_init_server_credentials(TSRMLS_C);
   grpc_php_init_completion_queue(TSRMLS_C);
   return SUCCESS;
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index c26be607ffc98bb618fbdfac6e2b9e7cfd2a39c4..aa4de349ea7f60b3f8ae41c8ac292f8b5aa05ef6 100755
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -51,6 +51,7 @@ class BaseStub
      * @param $opts array
      *  - 'update_metadata': (optional) a callback function which takes in a
      * metadata array, and returns an updated metadata array
+     *  - 'grpc.primary_user_agent': (optional) a user-agent string
      */
     public function __construct($hostname, $opts)
     {
@@ -64,7 +65,12 @@ class BaseStub
         }
         $package_config = json_decode(
             file_get_contents(dirname(__FILE__).'/../../composer.json'), true);
-        $opts['grpc.primary_user_agent'] =
+        if (!empty($opts['grpc.primary_user_agent'])) {
+            $opts['grpc.primary_user_agent'] .= ' ';
+        } else {
+            $opts['grpc.primary_user_agent'] = '';
+        }
+        $opts['grpc.primary_user_agent'] .=
             'grpc-php/'.$package_config['version'];
         $this->channel = new Channel($hostname, $opts);
     }
diff --git a/src/php/tests/data/server1.pem b/src/php/tests/data/server1.pem
index 8e582e571f643ca3fb6042a786c709a53f5afcf3..f3d43fcc5beadd98542abdaa32acfb555b807559 100755
--- a/src/php/tests/data/server1.pem
+++ b/src/php/tests/data/server1.pem
@@ -1,16 +1,16 @@
 -----BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
-MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
-MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
-BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
-c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
-JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
-RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
-3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
-BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
-b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
-KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
-wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
-aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
+MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
+MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
+BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
+ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
+LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
+zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
+9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
+CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
+em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
+CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
+hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
+y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
 -----END CERTIFICATE-----
diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php
index 3019866561e3fa11f9ec58636b66d2a7b433029e..9aab5c966c728615da4852ecc52db1e5d59c08b3 100755
--- a/src/php/tests/interop/interop_client.php
+++ b/src/php/tests/interop/interop_client.php
@@ -423,10 +423,10 @@ $opts = [];
 
 if ($use_tls) {
     if ($use_test_ca) {
-        $ssl_credentials = Grpc\Credentials::createSsl(
-        file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
+        $ssl_credentials = Grpc\ChannelCredentials::createSsl(
+            file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
     } else {
-        $ssl_credentials = Grpc\Credentials::createSsl();
+        $ssl_credentials = Grpc\ChannelCredentials::createSsl();
     }
     $opts['credentials'] = $ssl_credentials;
     $opts['grpc.ssl_target_name_override'] = $host_override;
diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php
index e66bde376c7a8d45fe17ca469bce7c1a73610c4c..c388ee5031ba66e66035cbba7cbc3637f6dbabac 100755
--- a/src/php/tests/unit_tests/SecureEndToEndTest.php
+++ b/src/php/tests/unit_tests/SecureEndToEndTest.php
@@ -35,7 +35,7 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase
 {
     public function setUp()
     {
-        $credentials = Grpc\Credentials::createSsl(
+        $credentials = Grpc\ChannelCredentials::createSsl(
             file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
         $server_credentials = Grpc\ServerCredentials::createSsl(
             null,
diff --git a/src/python/grpcio/grpc/_adapter/_c/types.c b/src/python/grpcio/grpc/_adapter/_c/types.c
index 8855c32ca6d4e859a3dd9632912fa4fd27af660f..8dedf5902b32d47cf41d9ff5bf97a233d16bfd98 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types.c
+++ b/src/python/grpcio/grpc/_adapter/_c/types.c
@@ -40,7 +40,8 @@
 int pygrpc_module_add_types(PyObject *module) {
   int i;
   PyTypeObject *types[] = {
-      &pygrpc_ClientCredentials_type,
+      &pygrpc_CallCredentials_type,
+      &pygrpc_ChannelCredentials_type,
       &pygrpc_ServerCredentials_type,
       &pygrpc_CompletionQueue_type,
       &pygrpc_Call_type,
diff --git a/src/python/grpcio/grpc/_adapter/_c/types.h b/src/python/grpcio/grpc/_adapter/_c/types.h
index 31fd470d36a967473bd28bd26eae53b4c251bc7e..9ab415d216b41497a5e54ab0c851b6aadfde8b5b 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types.h
+++ b/src/python/grpcio/grpc/_adapter/_c/types.h
@@ -44,27 +44,35 @@
 /* Client-side credentials */
 /*=========================*/
 
-typedef struct ClientCredentials {
+typedef struct ChannelCredentials {
   PyObject_HEAD
-  grpc_credentials *c_creds;
-} ClientCredentials;
-void pygrpc_ClientCredentials_dealloc(ClientCredentials *self);
-ClientCredentials *pygrpc_ClientCredentials_google_default(
+  grpc_channel_credentials *c_creds;
+} ChannelCredentials;
+void pygrpc_ChannelCredentials_dealloc(ChannelCredentials *self);
+ChannelCredentials *pygrpc_ChannelCredentials_google_default(
     PyTypeObject *type, PyObject *ignored);
-ClientCredentials *pygrpc_ClientCredentials_ssl(
+ChannelCredentials *pygrpc_ChannelCredentials_ssl(
     PyTypeObject *type, PyObject *args, PyObject *kwargs);
-ClientCredentials *pygrpc_ClientCredentials_composite(
+ChannelCredentials *pygrpc_ChannelCredentials_composite(
     PyTypeObject *type, PyObject *args, PyObject *kwargs);
-ClientCredentials *pygrpc_ClientCredentials_compute_engine(
+extern PyTypeObject pygrpc_ChannelCredentials_type;
+
+typedef struct CallCredentials {
+  PyObject_HEAD
+  grpc_call_credentials *c_creds;
+} CallCredentials;
+void pygrpc_CallCredentials_dealloc(CallCredentials *self);
+CallCredentials *pygrpc_CallCredentials_composite(
+    PyTypeObject *type, PyObject *args, PyObject *kwargs);
+CallCredentials *pygrpc_CallCredentials_compute_engine(
     PyTypeObject *type, PyObject *ignored);
-ClientCredentials *pygrpc_ClientCredentials_jwt(
+CallCredentials *pygrpc_CallCredentials_jwt(
     PyTypeObject *type, PyObject *args, PyObject *kwargs);
-ClientCredentials *pygrpc_ClientCredentials_refresh_token(
+CallCredentials *pygrpc_CallCredentials_refresh_token(
     PyTypeObject *type, PyObject *args, PyObject *kwargs);
-ClientCredentials *pygrpc_ClientCredentials_iam(
+CallCredentials *pygrpc_CallCredentials_iam(
     PyTypeObject *type, PyObject *args, PyObject *kwargs);
-extern PyTypeObject pygrpc_ClientCredentials_type;
-
+extern PyTypeObject pygrpc_CallCredentials_type;
 
 /*=========================*/
 /* Server-side credentials */
diff --git a/src/python/grpcio/grpc/_adapter/_c/types/call.c b/src/python/grpcio/grpc/_adapter/_c/types/call.c
index 5604aba39d506bbf053a0e27d60ee800d5865fb9..04ec871880086a8a87a9d161c7af98ea99a83d06 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types/call.c
+++ b/src/python/grpcio/grpc/_adapter/_c/types/call.c
@@ -173,12 +173,12 @@ PyObject *pygrpc_Call_peer(Call *self) {
 }
 PyObject *pygrpc_Call_set_credentials(Call *self, PyObject *args,
                                       PyObject *kwargs) {
-  ClientCredentials *creds;
+  CallCredentials *creds;
   grpc_call_error errcode;
   static char *keywords[] = {"creds", NULL};
   if (!PyArg_ParseTupleAndKeywords(
       args, kwargs, "O!:set_credentials", keywords,
-      &pygrpc_ClientCredentials_type, &creds)) {
+      &pygrpc_CallCredentials_type, &creds)) {
     return NULL;
   }
   errcode = grpc_call_set_credentials(self->c_call, creds->c_creds);
diff --git a/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c b/src/python/grpcio/grpc/_adapter/_c/types/call_credentials.c
similarity index 65%
rename from src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c
rename to src/python/grpcio/grpc/_adapter/_c/types/call_credentials.c
index 90652b7b475395f0fc24ebcc3e92b90563fb4a41..5a15a6e17dc37105bfe3adf93c145be5b8df507a 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c
+++ b/src/python/grpcio/grpc/_adapter/_c/types/call_credentials.c
@@ -39,31 +39,28 @@
 #include <grpc/grpc_security.h>
 
 
-PyMethodDef pygrpc_ClientCredentials_methods[] = {
-    {"google_default", (PyCFunction)pygrpc_ClientCredentials_google_default,
-     METH_CLASS|METH_NOARGS, ""},
-    {"ssl", (PyCFunction)pygrpc_ClientCredentials_ssl,
-     METH_CLASS|METH_KEYWORDS, ""},
-    {"composite", (PyCFunction)pygrpc_ClientCredentials_composite,
+PyMethodDef pygrpc_CallCredentials_methods[] = {
+    {"composite", (PyCFunction)pygrpc_CallCredentials_composite,
      METH_CLASS|METH_KEYWORDS, ""},
-    {"compute_engine", (PyCFunction)pygrpc_ClientCredentials_compute_engine,
+    {"compute_engine", (PyCFunction)pygrpc_CallCredentials_compute_engine,
      METH_CLASS|METH_NOARGS, ""},
-    {"jwt", (PyCFunction)pygrpc_ClientCredentials_jwt,
+    {"jwt", (PyCFunction)pygrpc_CallCredentials_jwt,
      METH_CLASS|METH_KEYWORDS, ""},
-    {"refresh_token", (PyCFunction)pygrpc_ClientCredentials_refresh_token,
+    {"refresh_token", (PyCFunction)pygrpc_CallCredentials_refresh_token,
      METH_CLASS|METH_KEYWORDS, ""},
-    {"iam", (PyCFunction)pygrpc_ClientCredentials_iam,
+    {"iam", (PyCFunction)pygrpc_CallCredentials_iam,
      METH_CLASS|METH_KEYWORDS, ""},
     {NULL}
 };
-const char pygrpc_ClientCredentials_doc[] = "";
-PyTypeObject pygrpc_ClientCredentials_type = {
+
+const char pygrpc_CallCredentials_doc[] = "";
+PyTypeObject pygrpc_CallCredentials_type = {
     PyObject_HEAD_INIT(NULL)
     0,                                        /* ob_size */
-    "ClientCredentials",                      /* tp_name */
-    sizeof(ClientCredentials),                /* tp_basicsize */
+    "CallCredentials",                        /* tp_name */
+    sizeof(CallCredentials),                  /* tp_basicsize */
     0,                                        /* tp_itemsize */
-    (destructor)pygrpc_ClientCredentials_dealloc, /* tp_dealloc */
+    (destructor)pygrpc_CallCredentials_dealloc, /* tp_dealloc */
     0,                                        /* tp_print */
     0,                                        /* tp_getattr */
     0,                                        /* tp_setattr */
@@ -79,14 +76,14 @@ PyTypeObject pygrpc_ClientCredentials_type = {
     0,                                        /* tp_setattro */
     0,                                        /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
-    pygrpc_ClientCredentials_doc,             /* tp_doc */
+    pygrpc_CallCredentials_doc,             /* tp_doc */
     0,                                        /* tp_traverse */
     0,                                        /* tp_clear */
     0,                                        /* tp_richcompare */
     0,                                        /* tp_weaklistoffset */
     0,                                        /* tp_iter */
     0,                                        /* tp_iternext */
-    pygrpc_ClientCredentials_methods,         /* tp_methods */
+    pygrpc_CallCredentials_methods,         /* tp_methods */
     0,                                        /* tp_members */
     0,                                        /* tp_getset */
     0,                                        /* tp_base */
@@ -99,67 +96,26 @@ PyTypeObject pygrpc_ClientCredentials_type = {
     0                                         /* tp_new */
 };
 
-void pygrpc_ClientCredentials_dealloc(ClientCredentials *self) {
-  grpc_credentials_release(self->c_creds);
+void pygrpc_CallCredentials_dealloc(CallCredentials *self) {
+  grpc_call_credentials_release(self->c_creds);
   self->ob_type->tp_free((PyObject *)self);
 }
 
-ClientCredentials *pygrpc_ClientCredentials_google_default(
-    PyTypeObject *type, PyObject *ignored) {
-  ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0);
-  self->c_creds = grpc_google_default_credentials_create();
-  if (!self->c_creds) {
-    Py_DECREF(self);
-    PyErr_SetString(PyExc_RuntimeError,
-                    "couldn't create Google default credentials");
-    return NULL;
-  }
-  return self;
-}
-
-ClientCredentials *pygrpc_ClientCredentials_ssl(
-    PyTypeObject *type, PyObject *args, PyObject *kwargs) {
-  ClientCredentials *self;
-  const char *root_certs;
-  const char *private_key = NULL;
-  const char *cert_chain = NULL;
-  grpc_ssl_pem_key_cert_pair key_cert_pair;
-  static char *keywords[] = {"root_certs", "private_key", "cert_chain", NULL};
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|zz:ssl", keywords,
-        &root_certs, &private_key, &cert_chain)) {
-    return NULL;
-  }
-  self = (ClientCredentials *)type->tp_alloc(type, 0);
-  if (private_key && cert_chain) {
-    key_cert_pair.private_key = private_key;
-    key_cert_pair.cert_chain = cert_chain;
-    self->c_creds =
-        grpc_ssl_credentials_create(root_certs, &key_cert_pair, NULL);
-  } else {
-    self->c_creds = grpc_ssl_credentials_create(root_certs, NULL, NULL);
-  }
-  if (!self->c_creds) {
-    Py_DECREF(self);
-    PyErr_SetString(PyExc_RuntimeError, "couldn't create ssl credentials");
-    return NULL;
-  }
-  return self;
-}
-
-ClientCredentials *pygrpc_ClientCredentials_composite(
+CallCredentials *pygrpc_CallCredentials_composite(
     PyTypeObject *type, PyObject *args, PyObject *kwargs) {
-  ClientCredentials *self;
-  ClientCredentials *creds1;
-  ClientCredentials *creds2;
+  CallCredentials *self;
+  CallCredentials *creds1;
+  CallCredentials *creds2;
   static char *keywords[] = {"creds1", "creds2", NULL};
   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O!:composite", keywords,
-        &pygrpc_ClientCredentials_type, &creds1,
-        &pygrpc_ClientCredentials_type, &creds2)) {
+        &pygrpc_CallCredentials_type, &creds1,
+        &pygrpc_CallCredentials_type, &creds2)) {
     return NULL;
   }
-  self = (ClientCredentials *)type->tp_alloc(type, 0);
+  self = (CallCredentials *)type->tp_alloc(type, 0);
   self->c_creds =
-      grpc_composite_credentials_create(creds1->c_creds, creds2->c_creds, NULL);
+      grpc_composite_call_credentials_create(
+          creds1->c_creds, creds2->c_creds, NULL);
   if (!self->c_creds) {
     Py_DECREF(self);
     PyErr_SetString(PyExc_RuntimeError, "couldn't create composite credentials");
@@ -168,9 +124,9 @@ ClientCredentials *pygrpc_ClientCredentials_composite(
   return self;
 }
 
-ClientCredentials *pygrpc_ClientCredentials_compute_engine(
+CallCredentials *pygrpc_CallCredentials_compute_engine(
     PyTypeObject *type, PyObject *ignored) {
-  ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0);
+  CallCredentials *self = (CallCredentials *)type->tp_alloc(type, 0);
   self->c_creds = grpc_google_compute_engine_credentials_create(NULL);
   if (!self->c_creds) {
     Py_DECREF(self);
@@ -182,9 +138,9 @@ ClientCredentials *pygrpc_ClientCredentials_compute_engine(
 }
 
 /* TODO: Rename this credentials to something like service_account_jwt_access */
-ClientCredentials *pygrpc_ClientCredentials_jwt(
+CallCredentials *pygrpc_CallCredentials_jwt(
     PyTypeObject *type, PyObject *args, PyObject *kwargs) {
-  ClientCredentials *self;
+  CallCredentials *self;
   const char *json_key;
   double lifetime;
   static char *keywords[] = {"json_key", "token_lifetime", NULL};
@@ -192,7 +148,7 @@ ClientCredentials *pygrpc_ClientCredentials_jwt(
         &json_key, &lifetime)) {
     return NULL;
   }
-  self = (ClientCredentials *)type->tp_alloc(type, 0);
+  self = (CallCredentials *)type->tp_alloc(type, 0);
   self->c_creds = grpc_service_account_jwt_access_credentials_create(
       json_key, pygrpc_cast_double_to_gpr_timespec(lifetime), NULL);
   if (!self->c_creds) {
@@ -203,16 +159,16 @@ ClientCredentials *pygrpc_ClientCredentials_jwt(
   return self;
 }
 
-ClientCredentials *pygrpc_ClientCredentials_refresh_token(
+CallCredentials *pygrpc_CallCredentials_refresh_token(
     PyTypeObject *type, PyObject *args, PyObject *kwargs) {
-  ClientCredentials *self;
+  CallCredentials *self;
   const char *json_refresh_token;
   static char *keywords[] = {"json_refresh_token", NULL};
   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:refresh_token", keywords,
         &json_refresh_token)) {
     return NULL;
   }
-  self = (ClientCredentials *)type->tp_alloc(type, 0);
+  self = (CallCredentials *)type->tp_alloc(type, 0);
   self->c_creds =
       grpc_google_refresh_token_credentials_create(json_refresh_token, NULL);
   if (!self->c_creds) {
@@ -224,9 +180,9 @@ ClientCredentials *pygrpc_ClientCredentials_refresh_token(
   return self;
 }
 
-ClientCredentials *pygrpc_ClientCredentials_iam(
+CallCredentials *pygrpc_CallCredentials_iam(
     PyTypeObject *type, PyObject *args, PyObject *kwargs) {
-  ClientCredentials *self;
+  CallCredentials *self;
   const char *authorization_token;
   const char *authority_selector;
   static char *keywords[] = {"authorization_token", "authority_selector", NULL};
@@ -234,7 +190,7 @@ ClientCredentials *pygrpc_ClientCredentials_iam(
         &authorization_token, &authority_selector)) {
     return NULL;
   }
-  self = (ClientCredentials *)type->tp_alloc(type, 0);
+  self = (CallCredentials *)type->tp_alloc(type, 0);
   self->c_creds = grpc_google_iam_credentials_create(authorization_token,
                                                      authority_selector, NULL);
   if (!self->c_creds) {
diff --git a/src/python/grpcio/grpc/_adapter/_c/types/channel.c b/src/python/grpcio/grpc/_adapter/_c/types/channel.c
index 79d39c4391dfd4eb26d513601273d6bbf49f7509..c4db2a0dfde3e9b53fe1332946716390d2676ac5 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types/channel.c
+++ b/src/python/grpcio/grpc/_adapter/_c/types/channel.c
@@ -94,11 +94,11 @@ Channel *pygrpc_Channel_new(
   Channel *self;
   const char *target;
   PyObject *py_args;
-  ClientCredentials *creds = NULL;
+  ChannelCredentials *creds = NULL;
   grpc_channel_args c_args;
   char *keywords[] = {"target", "args", "creds", NULL};
   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|O!:Channel", keywords,
-        &target, &py_args, &pygrpc_ClientCredentials_type, &creds)) {
+        &target, &py_args, &pygrpc_ChannelCredentials_type, &creds)) {
     return NULL;
   }
   if (!pygrpc_produce_channel_args(py_args, &c_args)) {
diff --git a/src/python/grpcio/grpc/_adapter/_c/types/channel_credentials.c b/src/python/grpcio/grpc/_adapter/_c/types/channel_credentials.c
new file mode 100644
index 0000000000000000000000000000000000000000..83b1fc0406af9f4f9c9240bff4790ac972b94982
--- /dev/null
+++ b/src/python/grpcio/grpc/_adapter/_c/types/channel_credentials.c
@@ -0,0 +1,165 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "grpc/_adapter/_c/types.h"
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+
+
+PyMethodDef pygrpc_ChannelCredentials_methods[] = {
+    {"google_default", (PyCFunction)pygrpc_ChannelCredentials_google_default,
+     METH_CLASS|METH_NOARGS, ""},
+    {"ssl", (PyCFunction)pygrpc_ChannelCredentials_ssl,
+     METH_CLASS|METH_KEYWORDS, ""},
+    {"composite", (PyCFunction)pygrpc_ChannelCredentials_composite,
+     METH_CLASS|METH_KEYWORDS, ""},
+    {NULL}
+};
+
+const char pygrpc_ChannelCredentials_doc[] = "";
+PyTypeObject pygrpc_ChannelCredentials_type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                        /* ob_size */
+    "ChannelCredentials",                     /* tp_name */
+    sizeof(ChannelCredentials),               /* tp_basicsize */
+    0,                                        /* tp_itemsize */
+    (destructor)pygrpc_ChannelCredentials_dealloc, /* tp_dealloc */
+    0,                                        /* tp_print */
+    0,                                        /* tp_getattr */
+    0,                                        /* tp_setattr */
+    0,                                        /* tp_compare */
+    0,                                        /* tp_repr */
+    0,                                        /* tp_as_number */
+    0,                                        /* tp_as_sequence */
+    0,                                        /* tp_as_mapping */
+    0,                                        /* tp_hash */
+    0,                                        /* tp_call */
+    0,                                        /* tp_str */
+    0,                                        /* tp_getattro */
+    0,                                        /* tp_setattro */
+    0,                                        /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+    pygrpc_ChannelCredentials_doc,             /* tp_doc */
+    0,                                        /* tp_traverse */
+    0,                                        /* tp_clear */
+    0,                                        /* tp_richcompare */
+    0,                                        /* tp_weaklistoffset */
+    0,                                        /* tp_iter */
+    0,                                        /* tp_iternext */
+    pygrpc_ChannelCredentials_methods,         /* tp_methods */
+    0,                                        /* tp_members */
+    0,                                        /* tp_getset */
+    0,                                        /* tp_base */
+    0,                                        /* tp_dict */
+    0,                                        /* tp_descr_get */
+    0,                                        /* tp_descr_set */
+    0,                                        /* tp_dictoffset */
+    0,                                        /* tp_init */
+    0,                                        /* tp_alloc */
+    0                                         /* tp_new */
+};
+
+void pygrpc_ChannelCredentials_dealloc(ChannelCredentials *self) {
+  grpc_channel_credentials_release(self->c_creds);
+  self->ob_type->tp_free((PyObject *)self);
+}
+
+ChannelCredentials *pygrpc_ChannelCredentials_google_default(
+    PyTypeObject *type, PyObject *ignored) {
+  ChannelCredentials *self = (ChannelCredentials *)type->tp_alloc(type, 0);
+  self->c_creds = grpc_google_default_credentials_create();
+  if (!self->c_creds) {
+    Py_DECREF(self);
+    PyErr_SetString(PyExc_RuntimeError,
+                    "couldn't create Google default credentials");
+    return NULL;
+  }
+  return self;
+}
+
+ChannelCredentials *pygrpc_ChannelCredentials_ssl(
+    PyTypeObject *type, PyObject *args, PyObject *kwargs) {
+  ChannelCredentials *self;
+  const char *root_certs;
+  const char *private_key = NULL;
+  const char *cert_chain = NULL;
+  grpc_ssl_pem_key_cert_pair key_cert_pair;
+  static char *keywords[] = {"root_certs", "private_key", "cert_chain", NULL};
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|zz:ssl", keywords,
+        &root_certs, &private_key, &cert_chain)) {
+    return NULL;
+  }
+  self = (ChannelCredentials *)type->tp_alloc(type, 0);
+  if (private_key && cert_chain) {
+    key_cert_pair.private_key = private_key;
+    key_cert_pair.cert_chain = cert_chain;
+    self->c_creds =
+        grpc_ssl_credentials_create(root_certs, &key_cert_pair, NULL);
+  } else {
+    self->c_creds = grpc_ssl_credentials_create(root_certs, NULL, NULL);
+  }
+  if (!self->c_creds) {
+    Py_DECREF(self);
+    PyErr_SetString(PyExc_RuntimeError, "couldn't create ssl credentials");
+    return NULL;
+  }
+  return self;
+}
+
+ChannelCredentials *pygrpc_ChannelCredentials_composite(
+    PyTypeObject *type, PyObject *args, PyObject *kwargs) {
+  ChannelCredentials *self;
+  ChannelCredentials *creds1;
+  CallCredentials *creds2;
+  static char *keywords[] = {"creds1", "creds2", NULL};
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O!:composite", keywords,
+        &pygrpc_ChannelCredentials_type, &creds1,
+        &pygrpc_CallCredentials_type, &creds2)) {
+    return NULL;
+  }
+  self = (ChannelCredentials *)type->tp_alloc(type, 0);
+  self->c_creds =
+      grpc_composite_channel_credentials_create(
+          creds1->c_creds, creds2->c_creds, NULL);
+  if (!self->c_creds) {
+    Py_DECREF(self);
+    PyErr_SetString(
+        PyExc_RuntimeError, "couldn't create composite credentials");
+    return NULL;
+  }
+  return self;
+}
+
diff --git a/src/python/grpcio/grpc/_adapter/_intermediary_low.py b/src/python/grpcio/grpc/_adapter/_intermediary_low.py
index e2feec6ffba1fa89161d20bbcff2703f90c71e9e..5634c2024d350f6d19d5f28ead406a2746f540e9 100644
--- a/src/python/grpcio/grpc/_adapter/_intermediary_low.py
+++ b/src/python/grpcio/grpc/_adapter/_intermediary_low.py
@@ -253,10 +253,10 @@ class Server(object):
 
 
 class ClientCredentials(object):
-  """Adapter from old _low.ClientCredentials interface to new _low.ClientCredentials."""
+  """Adapter from old _low.ClientCredentials interface to new _low.ChannelCredentials."""
 
   def __init__(self, root_certificates, private_key, certificate_chain):
-    self._internal = _low.ClientCredentials.ssl(root_certificates, private_key, certificate_chain)
+    self._internal = _low.ChannelCredentials.ssl(root_certificates, private_key, certificate_chain)
 
 
 class ServerCredentials(object):
diff --git a/src/python/grpcio/grpc/_adapter/_low.py b/src/python/grpcio/grpc/_adapter/_low.py
index 70ceb2a9113af0a1863bf8adbe49303c9b764d58..57146aaefe8020933548c6803cbefa37f60510f2 100644
--- a/src/python/grpcio/grpc/_adapter/_low.py
+++ b/src/python/grpcio/grpc/_adapter/_low.py
@@ -33,7 +33,8 @@ from grpc._adapter import _types
 
 _USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__)
 
-ClientCredentials = _c.ClientCredentials
+ChannelCredentials = _c.ChannelCredentials
+CallCredentials = _c.CallCredentials
 ServerCredentials = _c.ServerCredentials
 
 
diff --git a/src/python/grpcio/grpc/_adapter/_types.py b/src/python/grpcio/grpc/_adapter/_types.py
index 5470d2de4a3d671a05ad5895e99ecc378c81a6e0..ca0fa066bc8e7d6bf005acde6898c4d6304276a8 100644
--- a/src/python/grpcio/grpc/_adapter/_types.py
+++ b/src/python/grpcio/grpc/_adapter/_types.py
@@ -323,6 +323,14 @@ class Call:
     """
     return None
 
+  def set_credentials(self, creds):
+    """Set per-call credentials.
+
+    Args:
+      creds (CallCredentials): Credentials to be set for this call.
+    """
+    return None
+
 
 class Channel:
   __metaclass__ = abc.ABCMeta
@@ -334,7 +342,7 @@ class Channel:
     Args:
       target (str): ...
       args (sequence of 2-sequence of str, (str|integer)): ...
-      credentials (ClientCredentials): If None, create an insecure channel,
+      credentials (ChannelCredentials): If None, create an insecure channel,
         else create a secure channel using the client credentials.
     """
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx
index ed037b660a24b90a28466f46345fbc328fc7ee9f..51c46681388f43e6ed720d2da557fce7f8101167 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx
@@ -29,6 +29,7 @@
 
 cimport cpython
 
+from grpc._cython._cygrpc cimport credentials
 from grpc._cython._cygrpc cimport grpc
 from grpc._cython._cygrpc cimport records
 
@@ -73,6 +74,11 @@ cdef class Call:
     else:
       return grpc.grpc_call_cancel(self.c_call, NULL)
 
+  def set_credentials(
+      self, credentials.CallCredentials call_credentials not None):
+    return grpc.grpc_call_set_credentials(
+        self.c_call, call_credentials.c_credentials)
+
   def __dealloc__(self):
     if self.c_call != NULL:
       grpc.grpc_call_destroy(self.c_call)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx
index b52ddb6bcd4de4b4c28eb034c556a12b1cfb45fd..e25db3e2a442095aec7c367afcc6b262e6a0474d 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx
@@ -37,7 +37,7 @@ from grpc._cython._cygrpc cimport records
 cdef class Channel:
 
   def __cinit__(self, target, records.ChannelArgs arguments=None,
-                credentials.ClientCredentials client_credentials=None):
+                credentials.ChannelCredentials channel_credentials=None):
     cdef grpc.grpc_channel_args *c_arguments = NULL
     self.c_channel = NULL
     self.references = []
@@ -49,13 +49,13 @@ cdef class Channel:
       target = target.encode()
     else:
       raise TypeError("expected target to be str or bytes")
-    if client_credentials is None:
+    if channel_credentials is None:
       self.c_channel = grpc.grpc_insecure_channel_create(target, c_arguments,
                                                          NULL)
     else:
       self.c_channel = grpc.grpc_secure_channel_create(
-          client_credentials.c_credentials, target, c_arguments, NULL)
-      self.references.append(client_credentials)
+          channel_credentials.c_credentials, target, c_arguments, NULL)
+      self.references.append(channel_credentials)
     self.references.append(target)
     self.references.append(arguments)
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd
index 6b74a267e0bb9ad568d80e203902d7f0e0f27d26..7a9fa7b76d01b3b3596be369fe77ac3481818a6b 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd
@@ -30,13 +30,19 @@
 from grpc._cython._cygrpc cimport grpc
 
 
-cdef class ClientCredentials:
+cdef class ChannelCredentials:
 
-  cdef grpc.grpc_credentials *c_credentials
+  cdef grpc.grpc_channel_credentials *c_credentials
   cdef grpc.grpc_ssl_pem_key_cert_pair c_ssl_pem_key_cert_pair
   cdef list references
 
 
+cdef class CallCredentials:
+
+  cdef grpc.grpc_call_credentials *c_credentials
+  cdef list references
+
+
 cdef class ServerCredentials:
 
   cdef grpc.grpc_server_credentials *c_credentials
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx
index 608207f0a2234ad22d6c9b48efc10c5424892174..e9836fec2cf7ed08446373d67634a56d4e57dafd 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx
@@ -31,7 +31,7 @@ from grpc._cython._cygrpc cimport grpc
 from grpc._cython._cygrpc cimport records
 
 
-cdef class ClientCredentials:
+cdef class ChannelCredentials:
 
   def __cinit__(self):
     self.c_credentials = NULL
@@ -47,7 +47,24 @@ cdef class ClientCredentials:
 
   def __dealloc__(self):
     if self.c_credentials != NULL:
-      grpc.grpc_credentials_release(self.c_credentials)
+      grpc.grpc_channel_credentials_release(self.c_credentials)
+
+
+cdef class CallCredentials:
+
+  def __cinit__(self):
+    self.c_credentials = NULL
+    self.references = []
+
+  # The object *can* be invalid in Python if we fail to make the credentials
+  # (and the core thus returns NULL credentials). Used primarily for debugging.
+  @property
+  def is_valid(self):
+    return self.c_credentials != NULL
+
+  def __dealloc__(self):
+    if self.c_credentials != NULL:
+      grpc.grpc_call_credentials_release(self.c_credentials)
 
 
 cdef class ServerCredentials:
@@ -60,12 +77,12 @@ cdef class ServerCredentials:
       grpc.grpc_server_credentials_release(self.c_credentials)
 
 
-def client_credentials_google_default():
-  cdef ClientCredentials credentials = ClientCredentials();
+def channel_credentials_google_default():
+  cdef ChannelCredentials credentials = ChannelCredentials();
   credentials.c_credentials = grpc.grpc_google_default_credentials_create()
   return credentials
 
-def client_credentials_ssl(pem_root_certificates,
+def channel_credentials_ssl(pem_root_certificates,
                            records.SslPemKeyCertPair ssl_pem_key_cert_pair):
   if pem_root_certificates is None:
     pass
@@ -75,7 +92,7 @@ def client_credentials_ssl(pem_root_certificates,
     pem_root_certificates = pem_root_certificates.encode()
   else:
     raise TypeError("expected str or bytes for pem_root_certificates")
-  cdef ClientCredentials credentials = ClientCredentials()
+  cdef ChannelCredentials credentials = ChannelCredentials()
   cdef const char *c_pem_root_certificates = NULL
   if pem_root_certificates is not None:
     c_pem_root_certificates = pem_root_certificates
@@ -88,26 +105,38 @@ def client_credentials_ssl(pem_root_certificates,
     credentials.c_credentials = grpc.grpc_ssl_credentials_create(
       c_pem_root_certificates, NULL, NULL)
 
-def client_credentials_composite_credentials(
-    ClientCredentials credentials_1 not None,
-    ClientCredentials credentials_2 not None):
+def channel_credentials_composite(
+    ChannelCredentials credentials_1 not None,
+    CallCredentials credentials_2 not None):
+  if not credentials_1.is_valid or not credentials_2.is_valid:
+    raise ValueError("passed credentials must both be valid")
+  cdef ChannelCredentials credentials = ChannelCredentials()
+  credentials.c_credentials = grpc.grpc_composite_channel_credentials_create(
+      credentials_1.c_credentials, credentials_2.c_credentials, NULL)
+  credentials.references.append(credentials_1)
+  credentials.references.append(credentials_2)
+  return credentials
+
+def call_credentials_composite(
+    CallCredentials credentials_1 not None,
+    CallCredentials credentials_2 not None):
   if not credentials_1.is_valid or not credentials_2.is_valid:
     raise ValueError("passed credentials must both be valid")
-  cdef ClientCredentials credentials = ClientCredentials()
-  credentials.c_credentials = grpc.grpc_composite_credentials_create(
+  cdef CallCredentials credentials = CallCredentials()
+  credentials.c_credentials = grpc.grpc_composite_call_credentials_create(
       credentials_1.c_credentials, credentials_2.c_credentials, NULL)
   credentials.references.append(credentials_1)
   credentials.references.append(credentials_2)
   return credentials
 
-def client_credentials_google_compute_engine():
-  cdef ClientCredentials credentials = ClientCredentials()
+def call_credentials_google_compute_engine():
+  cdef CallCredentials credentials = CallCredentials()
   credentials.c_credentials = (
       grpc.grpc_google_compute_engine_credentials_create(NULL))
   return credentials
 
 #TODO rename to something like client_credentials_service_account_jwt_access.
-def client_credentials_service_account_jwt_access(
+def call_credentials_service_account_jwt_access(
     json_key, records.Timespec token_lifetime not None):
   if isinstance(json_key, bytes):
     pass
@@ -115,27 +144,27 @@ def client_credentials_service_account_jwt_access(
     json_key = json_key.encode()
   else:
     raise TypeError("expected json_key to be str or bytes")
-  cdef ClientCredentials credentials = ClientCredentials()
+  cdef CallCredentials credentials = CallCredentials()
   credentials.c_credentials = (
       grpc.grpc_service_account_jwt_access_credentials_create(
           json_key, token_lifetime.c_time, NULL))
   credentials.references.append(json_key)
   return credentials
 
-def client_credentials_google_refresh_token(json_refresh_token):
+def call_credentials_google_refresh_token(json_refresh_token):
   if isinstance(json_refresh_token, bytes):
     pass
   elif isinstance(json_refresh_token, basestring):
     json_refresh_token = json_refresh_token.encode()
   else:
     raise TypeError("expected json_refresh_token to be str or bytes")
-  cdef ClientCredentials credentials = ClientCredentials()
+  cdef CallCredentials credentials = CallCredentials()
   credentials.c_credentials = grpc.grpc_google_refresh_token_credentials_create(
       json_refresh_token, NULL)
   credentials.references.append(json_refresh_token)
   return credentials
 
-def client_credentials_google_iam(authorization_token, authority_selector):
+def call_credentials_google_iam(authorization_token, authority_selector):
   if isinstance(authorization_token, bytes):
     pass
   elif isinstance(authorization_token, basestring):
@@ -148,7 +177,7 @@ def client_credentials_google_iam(authorization_token, authority_selector):
     authority_selector = authority_selector.encode()
   else:
     raise TypeError("expected authority_selector to be str or bytes")
-  cdef ClientCredentials credentials = ClientCredentials()
+  cdef CallCredentials credentials = CallCredentials()
   credentials.c_credentials = grpc.grpc_google_iam_credentials_create(
       authorization_token, authority_selector, NULL)
   credentials.references.append(authorization_token)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd
index 62d40e7a58e6e71d675169317b97e8f2fc2620e1..36aea81a6c0d8de77d6a187426d9b096c76f7638 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd
@@ -316,32 +316,40 @@ cdef extern from "grpc/grpc_security.h":
     const char *private_key
     const char *certificate_chain "cert_chain"
 
-  ctypedef struct grpc_credentials:
+  ctypedef struct grpc_channel_credentials:
     # We don't care about the internals (and in fact don't know them)
     pass
 
-  grpc_credentials *grpc_google_default_credentials_create()
-  grpc_credentials *grpc_ssl_credentials_create(
+  ctypedef struct grpc_call_credentials:
+    # We don't care about the internals (and in fact don't know them)
+    pass
+
+  grpc_channel_credentials *grpc_google_default_credentials_create()
+  grpc_channel_credentials *grpc_ssl_credentials_create(
       const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
       void *reserved)
+  grpc_channel_credentials *grpc_composite_channel_credentials_create(
+      grpc_channel_credentials *creds1, grpc_call_credentials *creds2,
+      void *reserved)
+  void grpc_channel_credentials_release(grpc_channel_credentials *creds)
 
-  grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
-                                                      grpc_credentials *creds2,
-                                                      void *reserved)
-  grpc_credentials *grpc_google_compute_engine_credentials_create(
+  grpc_call_credentials *grpc_composite_call_credentials_create(
+      grpc_call_credentials *creds1, grpc_call_credentials *creds2,
+      void *reserved)
+  grpc_call_credentials *grpc_google_compute_engine_credentials_create(
       void *reserved)
-  grpc_credentials *grpc_service_account_jwt_access_credentials_create(
+  grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
       const char *json_key,
       gpr_timespec token_lifetime, void *reserved)
-  grpc_credentials *grpc_google_refresh_token_credentials_create(
+  grpc_call_credentials *grpc_google_refresh_token_credentials_create(
       const char *json_refresh_token, void *reserved)
-  grpc_credentials *grpc_google_iam_credentials_create(
+  grpc_call_credentials *grpc_google_iam_credentials_create(
       const char *authorization_token, const char *authority_selector,
       void *reserved)
-  void grpc_credentials_release(grpc_credentials *creds)
+  void grpc_call_credentials_release(grpc_call_credentials *creds)
 
   grpc_channel *grpc_secure_channel_create(
-      grpc_credentials *creds, const char *target,
+      grpc_channel_credentials *creds, const char *target,
       const grpc_channel_args *args, void *reserved)
 
   ctypedef struct grpc_server_credentials:
@@ -358,4 +366,4 @@ cdef extern from "grpc/grpc_security.h":
                                         grpc_server_credentials *creds)
 
   grpc_call_error grpc_call_set_credentials(grpc_call *call,
-                                            grpc_credentials *creds)
+                                            grpc_call_credentials *creds)
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx
index 1ef2997db5162324696acef184efc124364049d4..b20dda8a95875dcfdf66687ae52a00967f7037fb 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
@@ -70,21 +70,24 @@ operation_receive_close_on_server = records.operation_receive_close_on_server
 
 Operations = records.Operations
 
-ClientCredentials = credentials.ClientCredentials
+CallCredentials = credentials.CallCredentials
+ChannelCredentials = credentials.ChannelCredentials
 ServerCredentials = credentials.ServerCredentials
 
-client_credentials_google_default = (
-    credentials.client_credentials_google_default)
-client_credentials_ssl = credentials.client_credentials_ssl
-client_credentials_composite_credentials = (
-    credentials.client_credentials_composite_credentials)
-client_credentials_google_compute_engine = (
-    credentials.client_credentials_google_compute_engine)
-client_credentials_jwt_access = (
-    credentials.client_credentials_service_account_jwt_access)
-client_credentials_refresh_token = (
-    credentials.client_credentials_google_refresh_token)
-client_credentials_google_iam = credentials.client_credentials_google_iam
+channel_credentials_google_default = (
+    credentials.channel_credentials_google_default)
+channel_credentials_ssl = credentials.channel_credentials_ssl
+channel_credentials_composite = (
+    credentials.channel_credentials_composite)
+call_credentials_composite = (
+    credentials.call_credentials_composite)
+call_credentials_google_compute_engine = (
+    credentials.call_credentials_google_compute_engine)
+call_credentials_jwt_access = (
+    credentials.call_credentials_service_account_jwt_access)
+call_credentials_refresh_token = (
+    credentials.call_credentials_google_refresh_token)
+call_credentials_google_iam = credentials.call_credentials_google_iam
 server_credentials_ssl = credentials.server_credentials_ssl
 
 CompletionQueue = completion_queue.CompletionQueue
diff --git a/src/python/grpcio/grpc/beta/interfaces.py b/src/python/grpcio/grpc/beta/interfaces.py
index 07c8618f70ccc8110e36d3b43e861f4364f2b626..d4ca56500ffd488c4856afe59e29096d7f479757 100644
--- a/src/python/grpcio/grpc/beta/interfaces.py
+++ b/src/python/grpcio/grpc/beta/interfaces.py
@@ -100,8 +100,11 @@ def grpc_call_options(disable_compression=False, credentials=None):
     disable_compression: A boolean indicating whether or not compression should
       be disabled for the request object of the RPC. Only valid for
       request-unary RPCs.
-    credentials: A ClientCredentials object to use for the invoked RPC.
+    credentials: Reserved for gRPC per-call credentials. The type for this does
+      not exist yet at the Python level.
   """
+  if credentials is not None:
+    raise ValueError('`credentials` is a reserved argument')
   return GRPCCallOptions(disable_compression, None, credentials)
 
 
diff --git a/src/python/grpcio/grpc/framework/interfaces/face/face.py b/src/python/grpcio/grpc/framework/interfaces/face/face.py
index bc9a434a760bd923afbb12c41bec4e5ee3ca9735..3b402356d2d0722312229a271c7b5c5ac569335d 100644
--- a/src/python/grpcio/grpc/framework/interfaces/face/face.py
+++ b/src/python/grpcio/grpc/framework/interfaces/face/face.py
@@ -117,6 +117,10 @@ class AbortionError(Exception):
     self.code = code
     self.details = details
 
+  def __str__(self):
+    return '%s(code=%s, details="%s")' % (
+        self.__class__.__name__, self.code, self.details)
+
 
 class CancellationError(AbortionError):
   """Indicates that an RPC has been cancelled."""
diff --git a/src/python/grpcio/setup.py b/src/python/grpcio/setup.py
index 97fa4fe6b3ffc5db3805271570c6b762a07c6dc9..ec68eb67555c5c9b530f9d0f0a9e7476e17b6f92 100644
--- a/src/python/grpcio/setup.py
+++ b/src/python/grpcio/setup.py
@@ -52,7 +52,8 @@ _C_EXTENSION_SOURCES = (
     'grpc/_adapter/_c/module.c',
     'grpc/_adapter/_c/types.c',
     'grpc/_adapter/_c/utility.c',
-    'grpc/_adapter/_c/types/client_credentials.c',
+    'grpc/_adapter/_c/types/call_credentials.c',
+    'grpc/_adapter/_c/types/channel_credentials.c',
     'grpc/_adapter/_c/types/server_credentials.c',
     'grpc/_adapter/_c/types/completion_queue.c',
     'grpc/_adapter/_c/types/call.c',
diff --git a/src/python/grpcio_test/grpc_interop/credentials/server1.pem b/src/python/grpcio_test/grpc_interop/credentials/server1.pem
index 8e582e571f643ca3fb6042a786c709a53f5afcf3..f3d43fcc5beadd98542abdaa32acfb555b807559 100755
--- a/src/python/grpcio_test/grpc_interop/credentials/server1.pem
+++ b/src/python/grpcio_test/grpc_interop/credentials/server1.pem
@@ -1,16 +1,16 @@
 -----BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
-MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
-MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
-BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
-c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
-JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
-RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
-3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
-BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
-b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
-KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
-wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
-aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
+MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
+MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
+BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
+ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
+LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
+zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
+9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
+CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
+em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
+CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
+hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
+y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
 -----END CERTIFICATE-----
diff --git a/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py b/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py
index fad57da9d069813b85084ab362fbf96fefe4195f..5916a9e3eaef288efc083b4d1325f9f6a09a5036 100644
--- a/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py
+++ b/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py
@@ -181,24 +181,21 @@ class BetaFeaturesTest(unittest.TestCase):
     self._server.stop(test_constants.SHORT_TIMEOUT).wait()
 
   def test_unary_unary(self):
-    call_options = interfaces.grpc_call_options(
-        disable_compression=True, credentials=self._client_credentials)
+    call_options = interfaces.grpc_call_options(disable_compression=True)
     response = getattr(self._dynamic_stub, _UNARY_UNARY)(
         _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options)
     self.assertEqual(_RESPONSE, response)
     self.assertIsNotNone(self._servicer.peer())
 
   def test_unary_stream(self):
-    call_options = interfaces.grpc_call_options(
-        disable_compression=True, credentials=self._client_credentials)
+    call_options = interfaces.grpc_call_options(disable_compression=True)
     response_iterator = getattr(self._dynamic_stub, _UNARY_STREAM)(
         _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options)
     self._servicer.block_until_serviced()
     self.assertIsNotNone(self._servicer.peer())
 
   def test_stream_unary(self):
-    call_options = interfaces.grpc_call_options(
-        credentials=self._client_credentials)
+    call_options = interfaces.grpc_call_options()
     request_iterator = _BlockingIterator(iter((_REQUEST,)))
     response_future = getattr(self._dynamic_stub, _STREAM_UNARY).future(
         request_iterator, test_constants.LONG_TIMEOUT,
@@ -212,8 +209,7 @@ class BetaFeaturesTest(unittest.TestCase):
     self.assertEqual(_RESPONSE, response_future.result())
 
   def test_stream_stream(self):
-    call_options = interfaces.grpc_call_options(
-        credentials=self._client_credentials)
+    call_options = interfaces.grpc_call_options()
     request_iterator = _BlockingIterator(iter((_REQUEST,)))
     response_iterator = getattr(self._dynamic_stub, _STREAM_STREAM)(
         request_iterator, test_constants.SHORT_TIMEOUT,
diff --git a/src/python/grpcio_test/grpc_test/credentials/server1.pem b/src/python/grpcio_test/grpc_test/credentials/server1.pem
index 8e582e571f643ca3fb6042a786c709a53f5afcf3..f3d43fcc5beadd98542abdaa32acfb555b807559 100755
--- a/src/python/grpcio_test/grpc_test/credentials/server1.pem
+++ b/src/python/grpcio_test/grpc_test/credentials/server1.pem
@@ -1,16 +1,16 @@
 -----BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
-MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
-MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
-BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
-c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
-JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
-RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
-3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
-BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
-b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
-KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
-wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
-aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
+MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
+MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
+BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
+ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
+LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
+zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
+9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
+CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
+em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
+CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
+hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
+y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
 -----END CERTIFICATE-----
diff --git a/src/ruby/bin/apis/pubsub_demo.rb b/src/ruby/bin/apis/pubsub_demo.rb
index a039d036ace8d6749ec96c75a85289b961ed8e2b..003e91a6b34b0dd2fefc0173c8b93d84bc2b1a49 100755
--- a/src/ruby/bin/apis/pubsub_demo.rb
+++ b/src/ruby/bin/apis/pubsub_demo.rb
@@ -66,7 +66,7 @@ end
 
 # creates a SSL Credentials from the production certificates.
 def ssl_creds
-  GRPC::Core::Credentials.new(load_prod_cert)
+  GRPC::Core::ChannelCredentials.new(load_prod_cert)
 end
 
 # Builds the metadata authentication update proc.
diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb
index 0ebd26f7806480d9b03091e95871ef223c2f3402..d7e00e429384f01bd475f8858a74f1ee4eb09ce7 100755
--- a/src/ruby/bin/math_client.rb
+++ b/src/ruby/bin/math_client.rb
@@ -102,7 +102,7 @@ end
 
 def test_creds
   certs = load_test_certs
-  GRPC::Core::Credentials.new(certs[0])
+  GRPC::Core::ChannelCredentials.new(certs[0])
 end
 
 def main
diff --git a/src/ruby/bin/noproto_client.rb b/src/ruby/bin/noproto_client.rb
index 390a9c59c3b66d9104a468270d630a3e224f4688..3aa11870c081ec3f5fb2ed541aedced9cf7025a3 100755
--- a/src/ruby/bin/noproto_client.rb
+++ b/src/ruby/bin/noproto_client.rb
@@ -68,7 +68,7 @@ end
 
 def test_creds
   certs = load_test_certs
-  GRPC::Core::Credentials.new(certs[0])
+  GRPC::Core::ChannelCredentials.new(certs[0])
 end
 
 def main
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 6b5beb6f5d74294566a5922dae5145ce2afdb16e..40364328ee8d9a3b0209de537daf2d18348c945e 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -139,7 +139,15 @@ static const rb_data_type_t grpc_rb_md_ary_data_type = {
      {NULL, NULL}},
     NULL,
     NULL,
-    0};
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+    /* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because
+     * grpc_rb_call_destroy
+     * touches a hash object.
+     * TODO(yugui) Directly use st_table and call the free function earlier?
+     */
+    0,
+#endif
+};
 
 /* Describes grpc_call struct for RTypedData */
 static const rb_data_type_t grpc_call_data_type = {
@@ -148,12 +156,15 @@ static const rb_data_type_t grpc_call_data_type = {
      {NULL, NULL}},
     NULL,
     NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     /* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because
      * grpc_rb_call_destroy
      * touches a hash object.
      * TODO(yugui) Directly use st_table and call the free function earlier?
      */
-    0};
+    0,
+#endif
+};
 
 /* Error code details is a hash containing text strings describing errors */
 VALUE rb_error_code_details;
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 90afdc3fe112e9b65cc1f4073a930f34206987db..d5d82421f59188fd693474114354d6dee236f800 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -41,8 +41,8 @@
 #include "rb_grpc.h"
 #include "rb_call.h"
 #include "rb_channel_args.h"
+#include "rb_channel_credentials.h"
 #include "rb_completion_queue.h"
-#include "rb_credentials.h"
 #include "rb_server.h"
 
 /* id_channel is the name of the hidden ivar that preserves a reference to the
@@ -111,7 +111,9 @@ static rb_data_type_t grpc_channel_data_type = {
     {grpc_rb_channel_mark, grpc_rb_channel_free, GRPC_RB_MEMSIZE_UNAVAILABLE,
      {NULL, NULL}},
     NULL, NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     RUBY_TYPED_FREE_IMMEDIATELY
+#endif
 };
 
 /* Allocates grpc_rb_channel instances. */
@@ -134,8 +136,8 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
   VALUE credentials = Qnil;
   VALUE target = Qnil;
   grpc_rb_channel *wrapper = NULL;
-  grpc_credentials *creds = NULL;
   grpc_channel *ch = NULL;
+  grpc_channel_credentials *creds = NULL;
   char *target_chars = NULL;
   grpc_channel_args args;
   MEMZERO(&args, grpc_channel_args, 1);
@@ -149,7 +151,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
   if (credentials == Qnil) {
     ch = grpc_insecure_channel_create(target_chars, &args, NULL);
   } else {
-    creds = grpc_rb_get_wrapped_credentials(credentials);
+    creds = grpc_rb_get_wrapped_channel_credentials(credentials);
     ch = grpc_secure_channel_create(creds, target_chars, &args, NULL);
   }
   if (args.args != NULL) {
diff --git a/src/ruby/ext/grpc/rb_channel_args.c b/src/ruby/ext/grpc/rb_channel_args.c
index 1ba30b69aa2dd653e2baa88b38d782b1354e0c5c..37dd981925ad5ee19b038b672feda8fa69c320a9 100644
--- a/src/ruby/ext/grpc/rb_channel_args.c
+++ b/src/ruby/ext/grpc/rb_channel_args.c
@@ -44,7 +44,9 @@ static rb_data_type_t grpc_rb_channel_args_data_type = {
     {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE,
      {NULL, NULL}},
     NULL, NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     RUBY_TYPED_FREE_IMMEDIATELY
+#endif
 };
 
 /* A callback the processes the hash key values in channel_args hash */
diff --git a/src/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c
similarity index 50%
rename from src/ruby/ext/grpc/rb_credentials.c
rename to src/ruby/ext/grpc/rb_channel_credentials.c
index ae757f698666c9327d191b4c438908e9e4dc7c28..072a6f54ab87482b04667b5ad3fd920aa561bdb5 100644
--- a/src/ruby/ext/grpc/rb_credentials.c
+++ b/src/ruby/ext/grpc/rb_channel_credentials.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "rb_credentials.h"
+#include "rb_channel_credentials.h"
 
 #include <ruby/ruby.h>
 
@@ -40,32 +40,33 @@
 
 #include "rb_grpc.h"
 
-/* grpc_rb_cCredentials is the ruby class that proxies grpc_credentials. */
-static VALUE grpc_rb_cCredentials = Qnil;
+/* grpc_rb_cChannelCredentials is the ruby class that proxies
+   grpc_channel_credentials. */
+static VALUE grpc_rb_cChannelCredentials = Qnil;
 
-/* grpc_rb_credentials wraps a grpc_credentials.  It provides a
+/* grpc_rb_channel_credentials wraps a grpc_channel_credentials.  It provides a
  * peer ruby object, 'mark' to minimize copying when a credential is
  * created from ruby. */
-typedef struct grpc_rb_credentials {
+typedef struct grpc_rb_channel_credentials {
   /* Holder of ruby objects involved in constructing the credentials */
   VALUE mark;
 
   /* The actual credentials */
-  grpc_credentials *wrapped;
-} grpc_rb_credentials;
+  grpc_channel_credentials *wrapped;
+} grpc_rb_channel_credentials;
 
 /* Destroys the credentials instances. */
-static void grpc_rb_credentials_free(void *p) {
-  grpc_rb_credentials *wrapper = NULL;
+static void grpc_rb_channel_credentials_free(void *p) {
+  grpc_rb_channel_credentials *wrapper = NULL;
   if (p == NULL) {
     return;
   };
-  wrapper = (grpc_rb_credentials *)p;
+  wrapper = (grpc_rb_channel_credentials *)p;
 
   /* Delete the wrapped object if the mark object is Qnil, which indicates that
    * no other object is the actual owner. */
   if (wrapper->wrapped != NULL && wrapper->mark == Qnil) {
-    grpc_credentials_release(wrapper->wrapped);
+    grpc_channel_credentials_release(wrapper->wrapped);
     wrapper->wrapped = NULL;
   }
 
@@ -73,12 +74,12 @@ static void grpc_rb_credentials_free(void *p) {
 }
 
 /* Protects the mark object from GC */
-static void grpc_rb_credentials_mark(void *p) {
-  grpc_rb_credentials *wrapper = NULL;
+static void grpc_rb_channel_credentials_mark(void *p) {
+  grpc_rb_channel_credentials *wrapper = NULL;
   if (p == NULL) {
     return;
   }
-  wrapper = (grpc_rb_credentials *)p;
+  wrapper = (grpc_rb_channel_credentials *)p;
 
   /* If it's not already cleaned up, mark the mark object */
   if (wrapper->mark != Qnil) {
@@ -86,29 +87,32 @@ static void grpc_rb_credentials_mark(void *p) {
   }
 }
 
-static rb_data_type_t grpc_rb_credentials_data_type = {
-    "grpc_credentials",
-    {grpc_rb_credentials_mark, grpc_rb_credentials_free,
+static rb_data_type_t grpc_rb_channel_credentials_data_type = {
+    "grpc_channel_credentials",
+    {grpc_rb_channel_credentials_mark, grpc_rb_channel_credentials_free,
      GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
     NULL,
     NULL,
-    RUBY_TYPED_FREE_IMMEDIATELY};
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+    RUBY_TYPED_FREE_IMMEDIATELY
+#endif
+};
 
-/* Allocates Credential instances.
+/* Allocates ChannelCredential instances.
    Provides safe initial defaults for the instance fields. */
-static VALUE grpc_rb_credentials_alloc(VALUE cls) {
-  grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials);
+static VALUE grpc_rb_channel_credentials_alloc(VALUE cls) {
+  grpc_rb_channel_credentials *wrapper = ALLOC(grpc_rb_channel_credentials);
   wrapper->wrapped = NULL;
   wrapper->mark = Qnil;
-  return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper);
+  return TypedData_Wrap_Struct(cls, &grpc_rb_channel_credentials_data_type, wrapper);
 }
 
-/* Clones Credentials instances.
-   Gives Credentials a consistent implementation of Ruby's object copy/dup
+/* Clones ChannelCredentials instances.
+   Gives ChannelCredentials a consistent implementation of Ruby's object copy/dup
    protocol. */
-static VALUE grpc_rb_credentials_init_copy(VALUE copy, VALUE orig) {
-  grpc_rb_credentials *orig_cred = NULL;
-  grpc_rb_credentials *copy_cred = NULL;
+static VALUE grpc_rb_channel_credentials_init_copy(VALUE copy, VALUE orig) {
+  grpc_rb_channel_credentials *orig_cred = NULL;
+  grpc_rb_channel_credentials *copy_cred = NULL;
 
   if (copy == orig) {
     return copy;
@@ -116,83 +120,22 @@ static VALUE grpc_rb_credentials_init_copy(VALUE copy, VALUE orig) {
 
   /* Raise an error if orig is not a credentials object or a subclass. */
   if (TYPE(orig) != T_DATA ||
-      RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_credentials_free) {
-    rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(grpc_rb_cCredentials));
+      RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_channel_credentials_free) {
+    rb_raise(rb_eTypeError, "not a %s",
+             rb_obj_classname(grpc_rb_cChannelCredentials));
   }
 
-  TypedData_Get_Struct(orig, grpc_rb_credentials,
-                       &grpc_rb_credentials_data_type, orig_cred);
-  TypedData_Get_Struct(copy, grpc_rb_credentials,
-                       &grpc_rb_credentials_data_type, copy_cred);
+  TypedData_Get_Struct(orig, grpc_rb_channel_credentials,
+                       &grpc_rb_channel_credentials_data_type, orig_cred);
+  TypedData_Get_Struct(copy, grpc_rb_channel_credentials,
+                       &grpc_rb_channel_credentials_data_type, copy_cred);
 
   /* use ruby's MEMCPY to make a byte-for-byte copy of the credentials
    * wrapper object. */
-  MEMCPY(copy_cred, orig_cred, grpc_rb_credentials, 1);
+  MEMCPY(copy_cred, orig_cred, grpc_rb_channel_credentials, 1);
   return copy;
 }
 
-/*
-  call-seq:
-    creds = Credentials.default()
-    Creates the default credential instances. */
-static VALUE grpc_rb_default_credentials_create(VALUE cls) {
-  grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials);
-  wrapper->wrapped = grpc_google_default_credentials_create();
-  if (wrapper->wrapped == NULL) {
-    rb_raise(rb_eRuntimeError,
-             "could not create default credentials, not sure why");
-    return Qnil;
-  }
-
-  wrapper->mark = Qnil;
-  return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper);
-}
-
-/*
-  call-seq:
-    creds = Credentials.compute_engine()
-    Creates the default credential instances. */
-static VALUE grpc_rb_compute_engine_credentials_create(VALUE cls) {
-  grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials);
-  wrapper->wrapped = grpc_google_compute_engine_credentials_create(NULL);
-  if (wrapper->wrapped == NULL) {
-    rb_raise(rb_eRuntimeError,
-             "could not create composite engine credentials, not sure why");
-    return Qnil;
-  }
-
-  wrapper->mark = Qnil;
-  return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper);
-}
-
-/*
-  call-seq:
-    creds1 = ...
-    creds2 = ...
-    creds3 = creds1.add(creds2)
-    Creates the default credential instances. */
-static VALUE grpc_rb_composite_credentials_create(VALUE self, VALUE other) {
-  grpc_rb_credentials *self_wrapper = NULL;
-  grpc_rb_credentials *other_wrapper = NULL;
-  grpc_rb_credentials *wrapper = NULL;
-
-  TypedData_Get_Struct(self, grpc_rb_credentials,
-                       &grpc_rb_credentials_data_type, self_wrapper);
-  TypedData_Get_Struct(other, grpc_rb_credentials,
-                       &grpc_rb_credentials_data_type, other_wrapper);
-  wrapper = ALLOC(grpc_rb_credentials);
-  wrapper->wrapped = grpc_composite_credentials_create(
-      self_wrapper->wrapped, other_wrapper->wrapped, NULL);
-  if (wrapper->wrapped == NULL) {
-    rb_raise(rb_eRuntimeError,
-             "could not create composite credentials, not sure why");
-    return Qnil;
-  }
-
-  wrapper->mark = Qnil;
-  return TypedData_Wrap_Struct(grpc_rb_cCredentials,
-                               &grpc_rb_credentials_data_type, wrapper);
-}
 
 /* The attribute used on the mark object to hold the pem_root_certs. */
 static ID id_pem_root_certs;
@@ -213,12 +156,12 @@ static ID id_pem_cert_chain;
     pem_private_key: (optional) PEM encoding of the client's private key
     pem_cert_chain: (optional) PEM encoding of the client's cert chain
     Initializes Credential instances. */
-static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
+static VALUE grpc_rb_channel_credentials_init(int argc, VALUE *argv, VALUE self) {
   VALUE pem_root_certs = Qnil;
   VALUE pem_private_key = Qnil;
   VALUE pem_cert_chain = Qnil;
-  grpc_rb_credentials *wrapper = NULL;
-  grpc_credentials *creds = NULL;
+  grpc_rb_channel_credentials *wrapper = NULL;
+  grpc_channel_credentials *creds = NULL;
   grpc_ssl_pem_key_cert_pair key_cert_pair;
   MEMZERO(&key_cert_pair, grpc_ssl_pem_key_cert_pair, 1);
   /* TODO: Remove mandatory arg when we support default roots. */
@@ -226,8 +169,8 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
   rb_scan_args(argc, argv, "12", &pem_root_certs, &pem_private_key,
                &pem_cert_chain);
 
-  TypedData_Get_Struct(self, grpc_rb_credentials,
-                       &grpc_rb_credentials_data_type, wrapper);
+  TypedData_Get_Struct(self, grpc_rb_channel_credentials,
+                       &grpc_rb_channel_credentials_data_type, wrapper);
   if (pem_root_certs == Qnil) {
     rb_raise(rb_eRuntimeError,
              "could not create a credential: nil pem_root_certs");
@@ -256,39 +199,30 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) {
   return self;
 }
 
-void Init_grpc_credentials() {
-  grpc_rb_cCredentials =
-      rb_define_class_under(grpc_rb_mGrpcCore, "Credentials", rb_cObject);
+void Init_grpc_channel_credentials() {
+  grpc_rb_cChannelCredentials =
+      rb_define_class_under(grpc_rb_mGrpcCore, "ChannelCredentials", rb_cObject);
 
   /* Allocates an object managed by the ruby runtime */
-  rb_define_alloc_func(grpc_rb_cCredentials, grpc_rb_credentials_alloc);
+  rb_define_alloc_func(grpc_rb_cChannelCredentials,
+                       grpc_rb_channel_credentials_alloc);
 
   /* Provides a ruby constructor and support for dup/clone. */
-  rb_define_method(grpc_rb_cCredentials, "initialize", grpc_rb_credentials_init,
-                   -1);
-  rb_define_method(grpc_rb_cCredentials, "initialize_copy",
-                   grpc_rb_credentials_init_copy, 1);
-
-  /* Provide static funcs that create new special instances. */
-  rb_define_singleton_method(grpc_rb_cCredentials, "default",
-                             grpc_rb_default_credentials_create, 0);
-
-  rb_define_singleton_method(grpc_rb_cCredentials, "compute_engine",
-                             grpc_rb_compute_engine_credentials_create, 0);
-
-  /* Provide other methods. */
-  rb_define_method(grpc_rb_cCredentials, "compose",
-                   grpc_rb_composite_credentials_create, 1);
+  rb_define_method(grpc_rb_cChannelCredentials, "initialize",
+                   grpc_rb_channel_credentials_init, -1);
+  rb_define_method(grpc_rb_cChannelCredentials, "initialize_copy",
+                   grpc_rb_channel_credentials_init_copy, 1);
 
   id_pem_cert_chain = rb_intern("__pem_cert_chain");
   id_pem_private_key = rb_intern("__pem_private_key");
   id_pem_root_certs = rb_intern("__pem_root_certs");
 }
 
-/* Gets the wrapped grpc_credentials from the ruby wrapper */
-grpc_credentials *grpc_rb_get_wrapped_credentials(VALUE v) {
-  grpc_rb_credentials *wrapper = NULL;
-  TypedData_Get_Struct(v, grpc_rb_credentials, &grpc_rb_credentials_data_type,
+/* Gets the wrapped grpc_channel_credentials from the ruby wrapper */
+grpc_channel_credentials *grpc_rb_get_wrapped_channel_credentials(VALUE v) {
+  grpc_rb_channel_credentials *wrapper = NULL;
+  TypedData_Get_Struct(v, grpc_rb_channel_credentials,
+                       &grpc_rb_channel_credentials_data_type,
                        wrapper);
   return wrapper->wrapped;
 }
diff --git a/src/ruby/ext/grpc/rb_credentials.h b/src/ruby/ext/grpc/rb_channel_credentials.h
similarity index 91%
rename from src/ruby/ext/grpc/rb_credentials.h
rename to src/ruby/ext/grpc/rb_channel_credentials.h
index 840f7d5f9cfcac3fda595ff53ec7e3589b54c122..15229de93215c124840e37485a8f74607c6e82bc 100644
--- a/src/ruby/ext/grpc/rb_credentials.h
+++ b/src/ruby/ext/grpc/rb_channel_credentials.h
@@ -38,10 +38,10 @@
 
 #include <grpc/grpc_security.h>
 
-/* Initializes the ruby Credentials class. */
-void Init_grpc_credentials();
+/* Initializes the ruby ChannelCredentials class. */
+void Init_grpc_channel_credentials();
 
 /* Gets the wrapped credentials from the ruby wrapper */
-grpc_credentials* grpc_rb_get_wrapped_credentials(VALUE v);
+grpc_channel_credentials* grpc_rb_get_wrapped_channel_credentials(VALUE v);
 
 #endif /* GRPC_RB_CREDENTIALS_H_ */
diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c
index 0bc9eb2a97ae67bd7112dae70c4ea660fd81f4c1..a7de96d71893f61cd5bce0ce636f4df857032566 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.c
+++ b/src/ruby/ext/grpc/rb_completion_queue.c
@@ -121,9 +121,11 @@ static rb_data_type_t grpc_rb_completion_queue_data_type = {
     {GRPC_RB_GC_NOT_MARKED, grpc_rb_completion_queue_destroy,
      GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
     NULL, NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     /* cannot immediately free because grpc_rb_completion_queue_shutdown_drain
      * calls rb_thread_call_without_gvl. */
-    0
+    0,
+#endif
 };
 
 /* Allocates a completion queue. */
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index 327fd1a4fc1b82afc8f5903d9b7b337a3f251b5c..7c7c2d344044c374b5f4bae352224dac419dc3d0 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -42,9 +42,9 @@
 #include <grpc/support/time.h>
 #include "rb_call.h"
 #include "rb_channel.h"
+#include "rb_channel_credentials.h"
 #include "rb_completion_queue.h"
 #include "rb_server.h"
-#include "rb_credentials.h"
 #include "rb_server_credentials.h"
 
 static VALUE grpc_rb_cTimeVal = Qnil;
@@ -55,7 +55,10 @@ static rb_data_type_t grpc_rb_timespec_data_type = {
      {NULL, NULL}},
     NULL,
     NULL,
-    RUBY_TYPED_FREE_IMMEDIATELY};
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+    RUBY_TYPED_FREE_IMMEDIATELY
+#endif
+};
 
 /* Alloc func that blocks allocation of a given object by raising an
  * exception. */
@@ -262,10 +265,20 @@ static void Init_grpc_time_consts() {
   id_tv_nsec = rb_intern("tv_nsec");
 }
 
+/*
+   TODO: find an alternative to ruby_vm_at_exit that is ok in Ruby 2.0 where
+   RUBY_TYPED_FREE_IMMEDIATELY is not defined.
+
+   At the moment, registering a function using ruby_vm_at_exit segfaults in Ruby
+   2.0.  This is not an issue with the gRPC handler.  More likely, this was an
+   in issue with 2.0 that got resolved in 2.1 and has not been backported.
+*/
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
 static void grpc_rb_shutdown(ruby_vm_t *vm) {
   (void)vm;
   grpc_shutdown();
 }
+#endif
 
 /* Initialize the GRPC module structs */
 
@@ -285,7 +298,12 @@ VALUE sym_metadata = Qundef;
 
 void Init_grpc() {
   grpc_init();
+
+/* TODO: find alternative to ruby_vm_at_exit that is ok in Ruby 2.0 */
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
   ruby_vm_at_exit(grpc_rb_shutdown);
+#endif
+
   grpc_rb_mGRPC = rb_define_module("GRPC");
   grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
   grpc_rb_sNewServerRpc =
@@ -300,7 +318,7 @@ void Init_grpc() {
   Init_grpc_channel();
   Init_grpc_completion_queue();
   Init_grpc_call();
-  Init_grpc_credentials();
+  Init_grpc_channel_credentials();
   Init_grpc_server();
   Init_grpc_server_credentials();
   Init_grpc_status_codes();
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index 446965886968b3779e919f14cef529d13140a4ab..ebdd7e1a346a2b49374ef533e5f4b6872d2a1d0b 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -101,11 +101,14 @@ static const rb_data_type_t grpc_rb_server_data_type = {
      {NULL, NULL}},
     NULL,
     NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     /* It is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because the free function would block
      * and we might want to unlock GVL
      * TODO(yugui) Unlock GVL?
      */
-    0};
+    0,
+#endif
+};
 
 /* Allocates grpc_rb_server instances. */
 static VALUE grpc_rb_server_alloc(VALUE cls) {
diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c
index ea4d0d864ecf7c3233eae43b4ce47bfe155342f4..de57585e0baecef5185f8128eee3a46b34e5cccd 100644
--- a/src/ruby/ext/grpc/rb_server_credentials.c
+++ b/src/ruby/ext/grpc/rb_server_credentials.c
@@ -91,7 +91,9 @@ static const rb_data_type_t grpc_rb_server_credentials_data_type = {
     {grpc_rb_server_credentials_mark, grpc_rb_server_credentials_free,
      GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
     NULL, NULL,
+#ifdef RUBY_TYPED_FREE_IMMEDIATELY
     RUBY_TYPED_FREE_IMMEDIATELY
+#endif
 };
 
 /* Allocates ServerCredential instances.
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index d9cb924735610396ac610d50a4fd451d0d4743a4..e80d24edc9b487993c368ee693d61b8685d91c64 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -199,11 +199,7 @@ module GRPC
     # marshalled.
     def remote_send(req, marshalled = false)
       GRPC.logger.debug("sending #{req}, marshalled? #{marshalled}")
-      if marshalled
-        payload = req
-      else
-        payload = @marshal.call(req)
-      end
+      payload = marshalled ? req : @marshal.call(req)
       @call.run_batch(@cq, self, INFINITE_FUTURE, SEND_MESSAGE => payload)
     end
 
@@ -417,7 +413,9 @@ module GRPC
     # @return [Enumerator, nil] a response Enumerator
     def bidi_streamer(requests, **kw, &blk)
       start_call(**kw) unless @started
-      bd = BidiCall.new(@call, @cq, @marshal, @unmarshal)
+      bd = BidiCall.new(@call, @cq, @marshal, @unmarshal,
+                        metadata_tag: @metadata_tag)
+      @metadata_tag = nil  # run_on_client ensures metadata is read
       bd.run_on_client(requests, @op_notifier, &blk)
     end
 
diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb
index 9dbbb74caff191cce3fcf31cdf52d1b949f4a0be..6b9b7856933cb94dd86144b4f80ad9cc0b904f43 100644
--- a/src/ruby/lib/grpc/generic/bidi_call.rb
+++ b/src/ruby/lib/grpc/generic/bidi_call.rb
@@ -56,7 +56,8 @@ module GRPC
     #          the call
     # @param marshal [Function] f(obj)->string that marshal requests
     # @param unmarshal [Function] f(string)->obj that unmarshals responses
-    def initialize(call, q, marshal, unmarshal)
+    # @param metadata_tag [Object] tag object used to collect metadata
+    def initialize(call, q, marshal, unmarshal, metadata_tag: nil)
       fail(ArgumentError, 'not a call') unless call.is_a? Core::Call
       unless q.is_a? Core::CompletionQueue
         fail(ArgumentError, 'not a CompletionQueue')
@@ -67,6 +68,7 @@ module GRPC
       @op_notifier = nil  # signals completion on clients
       @readq = Queue.new
       @unmarshal = unmarshal
+      @metadata_tag = metadata_tag
     end
 
     # Begins orchestration of the Bidi stream for a client sending requests.
@@ -113,6 +115,18 @@ module GRPC
       @op_notifier.notify(self)
     end
 
+    # performs a read using @call.run_batch, ensures metadata is set up
+    def read_using_run_batch
+      ops = { RECV_MESSAGE => nil }
+      ops[RECV_INITIAL_METADATA] = nil unless @metadata_tag.nil?
+      batch_result = @call.run_batch(@cq, self, INFINITE_FUTURE, ops)
+      unless @metadata_tag.nil?
+        @call.metadata = batch_result.metadata
+        @metadata_tag = nil
+      end
+      batch_result
+    end
+
     # each_queued_msg yields each message on this instances readq
     #
     # - messages are added to the readq by #read_loop
@@ -169,9 +183,7 @@ module GRPC
           loop do
             GRPC.logger.debug("bidi-read-loop: #{count}")
             count += 1
-            # TODO: ensure metadata is read if available, currently it's not
-            batch_result = @call.run_batch(@cq, read_tag, INFINITE_FUTURE,
-                                           RECV_MESSAGE => nil)
+            batch_result = read_using_run_batch
 
             # handle the next message
             if batch_result.message.nil?
diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb
index b8e33ad295ab3c6e556446854346895f2df9189a..90aaa026ec46804d6964bdce990ae9b6bb3bb081 100644
--- a/src/ruby/lib/grpc/generic/client_stub.rb
+++ b/src/ruby/lib/grpc/generic/client_stub.rb
@@ -51,7 +51,9 @@ module GRPC
       end
       kw['grpc.primary_user_agent'] = "grpc-ruby/#{VERSION}"
       return Core::Channel.new(host, kw) if creds.nil?
-      fail(TypeError, '!Credentials') unless creds.is_a?(Core::Credentials)
+      unless creds.is_a?(Core::ChannelCredentials)
+        fail(TypeError, '!ChannelCredentials')
+      end
       Core::Channel.new(host, kw, creds)
     end
 
@@ -106,7 +108,7 @@ module GRPC
     # @param q [Core::CompletionQueue] used to wait for events
     # @param channel_override [Core::Channel] a pre-created channel
     # @param timeout [Number] the default timeout to use in requests
-    # @param creds [Core::Credentials] the channel
+    # @param creds [Core::ChannelCredentials] the channel credentials
     # @param update_metadata a func that updates metadata as described above
     # @param kw [KeywordArgs]the channel arguments
     def initialize(host, q,
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index 228c500672b859499596e8e769e0f40929ba71df..0e318bd53b8fb5e693a40af13cc8d35f1783ed79 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -418,11 +418,11 @@ module GRPC
           an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE)
           break if (!an_rpc.nil?) && an_rpc.call.nil?
 
-          c = new_active_server_call(an_rpc)
-          unless c.nil?
-            mth = an_rpc.method.to_sym
-            @pool.schedule(c) do |call|
-              rpc_descs[mth].run_server_method(call, rpc_handlers[mth])
+          active_call = new_active_server_call(an_rpc)
+          unless active_call.nil?
+            @pool.schedule(active_call) do |ac|
+              c, mth = ac
+              rpc_descs[mth].run_server_method(c, rpc_handlers[mth])
             end
           end
         rescue Core::CallError, RuntimeError => e
@@ -442,6 +442,7 @@ module GRPC
       # allow the metadata to be accessed from the call
       handle_call_tag = Object.new
       an_rpc.call.metadata = an_rpc.metadata  # attaches md to call for handlers
+      GRPC.logger.debug("call md is #{an_rpc.metadata}")
       connect_md = nil
       unless @connect_md_proc.nil?
         connect_md = @connect_md_proc.call(an_rpc.method, an_rpc.metadata)
@@ -454,9 +455,11 @@ module GRPC
       # Create the ActiveCall
       GRPC.logger.info("deadline is #{an_rpc.deadline}; (now=#{Time.now})")
       rpc_desc = rpc_descs[an_rpc.method.to_sym]
-      ActiveCall.new(an_rpc.call, @cq,
-                     rpc_desc.marshal_proc, rpc_desc.unmarshal_proc(:input),
-                     an_rpc.deadline)
+      c = ActiveCall.new(an_rpc.call, @cq,
+                         rpc_desc.marshal_proc, rpc_desc.unmarshal_proc(:input),
+                         an_rpc.deadline)
+      mth = an_rpc.method.to_sym
+      [c, mth]
     end
 
     protected
diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb
index 1388685734a3d51635992c6cfe3fc7aba39f02cd..30550d6cc0a7b473c4715bd0a3357b4c6385d5cf 100755
--- a/src/ruby/pb/test/client.rb
+++ b/src/ruby/pb/test/client.rb
@@ -46,6 +46,7 @@ $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
 $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
 
 require 'optparse'
+require 'logger'
 
 require 'grpc'
 require 'googleauth'
@@ -59,6 +60,22 @@ require 'signet/ssl_config'
 
 AUTH_ENV = Google::Auth::CredentialsLoader::ENV_VAR
 
+# RubyLogger defines a logger for gRPC based on the standard ruby logger.
+module RubyLogger
+  def logger
+    LOGGER
+  end
+
+  LOGGER = Logger.new(STDOUT)
+  LOGGER.level = Logger::INFO
+end
+
+# GRPC is the general RPC module
+module GRPC
+  # Inject the noop #logger if no module-level logger method has been injected.
+  extend RubyLogger
+end
+
 # AssertionError is use to indicate interop test failures.
 class AssertionError < RuntimeError; end
 
@@ -86,13 +103,13 @@ end
 # creates SSL Credentials from the test certificates.
 def test_creds
   certs = load_test_certs
-  GRPC::Core::Credentials.new(certs[0])
+  GRPC::Core::ChannelCredentials.new(certs[0])
 end
 
 # creates SSL Credentials from the production certificates.
 def prod_creds
   cert_text = load_prod_cert
-  GRPC::Core::Credentials.new(cert_text)
+  GRPC::Core::ChannelCredentials.new(cert_text)
 end
 
 # creates the SSL Credentials.
diff --git a/src/ruby/pb/test/server.rb b/src/ruby/pb/test/server.rb
index 25c1b1e9e64e7f06a5a2f60e8f6c93f61cfbe2d6..67877a191fc96505f5040cd826568235921a439a 100755
--- a/src/ruby/pb/test/server.rb
+++ b/src/ruby/pb/test/server.rb
@@ -45,6 +45,7 @@ $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
 $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
 
 require 'forwardable'
+require 'logger'
 require 'optparse'
 
 require 'grpc'
@@ -53,6 +54,60 @@ require 'test/proto/empty'
 require 'test/proto/messages'
 require 'test/proto/test_services'
 
+# DebugIsTruncated extends the default Logger to truncate debug messages
+class DebugIsTruncated < Logger
+  def debug(s)
+    super(truncate(s, 1024))
+  end
+
+  # Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
+  #
+  #   'Once upon a time in a world far far away'.truncate(27)
+  #   # => "Once upon a time in a wo..."
+  #
+  # Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
+  #
+  #   'Once upon a time in a world far far away'.truncate(27, separator: ' ')
+  #   # => "Once upon a time in a..."
+  #
+  #   'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
+  #   # => "Once upon a time in a..."
+  #
+  # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
+  # for a total length not exceeding <tt>length</tt>:
+  #
+  #   'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
+  #   # => "And they f... (continued)"
+  def truncate(s, truncate_at, options = {})
+    return s unless s.length > truncate_at
+    omission = options[:omission] || '...'
+    with_extra_room = truncate_at - omission.length
+    stop = \
+      if options[:separator]
+        rindex(options[:separator], with_extra_room) || with_extra_room
+      else
+        with_extra_room
+      end
+    "#{s[0, stop]}#{omission}"
+  end
+end
+
+# RubyLogger defines a logger for gRPC based on the standard ruby logger.
+module RubyLogger
+  def logger
+    LOGGER
+  end
+
+  LOGGER = DebugIsTruncated.new(STDOUT)
+  LOGGER.level = Logger::WARN
+end
+
+# GRPC is the general RPC module
+module GRPC
+  # Inject the noop #logger if no module-level logger method has been injected.
+  extend RubyLogger
+end
+
 # loads the certificates by the test server.
 def load_test_certs
   this_dir = File.expand_path(File.dirname(__FILE__))
@@ -113,7 +168,7 @@ class TestTarget < Grpc::Testing::TestService::Service
 
   def streaming_input_call(call)
     sizes = call.each_remote_read.map { |x| x.payload.body.length }
-    sum = sizes.inject { |s, x| s + x }
+    sum = sizes.inject(0) { |s, x| s + x }
     StreamingInputCallResponse.new(aggregated_payload_size: sum)
   end
 
diff --git a/src/ruby/spec/credentials_spec.rb b/src/ruby/spec/channel_credentials_spec.rb
similarity index 78%
rename from src/ruby/spec/credentials_spec.rb
rename to src/ruby/spec/channel_credentials_spec.rb
index b02219dfdbbf83f39aba2c52886e737baccd5b68..b2bdf7032e0882745a28d91f9491cf924da12128 100644
--- a/src/ruby/spec/credentials_spec.rb
+++ b/src/ruby/spec/channel_credentials_spec.rb
@@ -29,8 +29,8 @@
 
 require 'grpc'
 
-describe GRPC::Core::Credentials do
-  Credentials = GRPC::Core::Credentials
+describe GRPC::Core::ChannelCredentials do
+  ChannelCredentials = GRPC::Core::ChannelCredentials
 
   def load_test_certs
     test_root = File.join(File.dirname(__FILE__), 'testdata')
@@ -40,32 +40,24 @@ describe GRPC::Core::Credentials do
 
   describe '#new' do
     it 'can be constructed with fake inputs' do
-      expect { Credentials.new('root_certs', 'key', 'cert') }.not_to raise_error
+      blk = proc  { ChannelCredentials.new('root_certs', 'key', 'cert') }
+      expect(&blk).not_to raise_error
     end
 
     it 'it can be constructed using specific test certificates' do
       certs = load_test_certs
-      expect { Credentials.new(*certs) }.not_to raise_error
+      expect { ChannelCredentials.new(*certs) }.not_to raise_error
     end
 
     it 'can be constructed with server roots certs only' do
       root_cert, _, _ = load_test_certs
-      expect { Credentials.new(root_cert) }.not_to raise_error
+      expect { ChannelCredentials.new(root_cert) }.not_to raise_error
     end
 
     it 'cannot be constructed with a nil server roots' do
       _, client_key, client_chain = load_test_certs
-      blk = proc { Credentials.new(nil, client_key, client_chain) }
+      blk = proc { ChannelCredentials.new(nil, client_key, client_chain) }
       expect(&blk).to raise_error
     end
   end
-
-  describe '#compose' do
-    it 'cannot be completed OK with 2 SSL creds' do
-      certs = load_test_certs
-      cred1 = Credentials.new(*certs)
-      cred2 = Credentials.new(*certs)
-      expect { cred1.compose(cred2) }.to raise_error
-    end
-  end
 end
diff --git a/src/ruby/spec/channel_spec.rb b/src/ruby/spec/channel_spec.rb
index 25cefcdfb766b15fa5e39a53bb8c27556fc75e90..b4d2b94a819be73bafab7587a4f9d7445d0d76c5 100644
--- a/src/ruby/spec/channel_spec.rb
+++ b/src/ruby/spec/channel_spec.rb
@@ -40,7 +40,7 @@ describe GRPC::Core::Channel do
   let(:cq) { GRPC::Core::CompletionQueue.new }
 
   def create_test_cert
-    GRPC::Core::Credentials.new(load_test_certs[0])
+    GRPC::Core::ChannelCredentials.new(load_test_certs[0])
   end
 
   shared_examples '#new' do
diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb
index ad0fb26896a8c1644854a076d3e0562a1f8e7e70..734f176e941a6f5e153c02eb2b4e3f1906c94d72 100644
--- a/src/ruby/spec/client_server_spec.rb
+++ b/src/ruby/spec/client_server_spec.rb
@@ -431,7 +431,7 @@ describe 'the secure http client/server' do
     @server.start
     args = { Channel::SSL_TARGET => 'foo.test.google.fr' }
     @ch = Channel.new("0.0.0.0:#{server_port}", args,
-                      GRPC::Core::Credentials.new(certs[0], nil, nil))
+                      GRPC::Core::ChannelCredentials.new(certs[0], nil, nil))
   end
 
   after(:example) do
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index c5173aee1d59c62c2d2a462f3596abf4aedee0cf..da5bc6c9e51b7647351a68ac477ea502dabcb503 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -113,7 +113,7 @@ describe 'ClientStub' do
         opts = {
           GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr',
           a_channel_arg: 'an_arg',
-          creds: GRPC::Core::Credentials.new(certs[0], nil, nil)
+          creds: GRPC::Core::ChannelCredentials.new(certs[0], nil, nil)
         }
         GRPC::ClientStub.new(fake_host, @cq, **opts)
       end
diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb
index 9bc82638c75fd3091e655b531035ca20234951cd..322566b7842fe316a446fd228dd9b735587a9fcb 100644
--- a/src/ruby/spec/pb/health/checker_spec.rb
+++ b/src/ruby/spec/pb/health/checker_spec.rb
@@ -31,6 +31,7 @@ require 'grpc'
 require 'grpc/health/v1alpha/health'
 require 'grpc/health/checker'
 require 'open3'
+require 'tmpdir'
 
 def can_run_codegen_check
   system('which grpc_ruby_plugin') && system('which protoc')
diff --git a/src/ruby/spec/testdata/server1.pem b/src/ruby/spec/testdata/server1.pem
index 8e582e571f643ca3fb6042a786c709a53f5afcf3..f3d43fcc5beadd98542abdaa32acfb555b807559 100755
--- a/src/ruby/spec/testdata/server1.pem
+++ b/src/ruby/spec/testdata/server1.pem
@@ -1,16 +1,16 @@
 -----BEGIN CERTIFICATE-----
-MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
-MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
-MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
-BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
-c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
-JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
-RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
-3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
-BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
-b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
-KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
-wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
-aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
+MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
+MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
+BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
+ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
+LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
+zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
+9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
+CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
+em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
+CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
+hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
+y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
 -----END CERTIFICATE-----
diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template
index 52070cf6e9e6c0ac450c95321df813eca0e125f4..be80750eb7f67877fe790a08da034e608bdf5964 100644
--- a/templates/binding.gyp.template
+++ b/templates/binding.gyp.template
@@ -89,8 +89,9 @@
       ]
     },
     'targets': [
+      % for module in node_modules:
       % for lib in libs:
-      % if lib.name == 'gpr' or lib.name == 'grpc':
+      % if lib.name in module.transitive_deps:
       {
         'target_name': '${lib.name}',
         'product_prefix': 'lib',
@@ -142,22 +143,18 @@
             }
           }]
         ],
-        "target_name": "grpc_node",
+        "target_name": "${module.name}",
         "sources": [
-          "src/node/ext/byte_buffer.cc",
-          "src/node/ext/call.cc",
-          "src/node/ext/call_credentials.cc",
-          "src/node/ext/channel.cc",
-          "src/node/ext/channel_credentials.cc",
-          "src/node/ext/completion_queue_async_worker.cc",
-          "src/node/ext/node_grpc.cc",
-          "src/node/ext/server.cc",
-          "src/node/ext/server_credentials.cc",
-          "src/node/ext/timeval.cc"
+          % for source in module.src:
+          "${source}",
+          % endfor
         ],
         "dependencies": [
-          "grpc"
+          % for dep in getattr(module, 'deps', []):
+          "${dep}",
+          % endfor
         ]
-      }
+      },
+      % endfor
     ]
   }
diff --git a/test/core/client_config/lb_policies_test.c b/test/core/client_config/lb_policies_test.c
index e44930ed53512d9184ae087ba98f29aaf18cbf01..6f218e7f08be2405b13d9f82814496842e5be565 100644
--- a/test/core/client_config/lb_policies_test.c
+++ b/test/core/client_config/lb_policies_test.c
@@ -135,9 +135,8 @@ static void kill_server(const servers_fixture *f, size_t i) {
   gpr_log(GPR_INFO, "KILLING SERVER %d", i);
   GPR_ASSERT(f->servers[i] != NULL);
   grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
-  GPR_ASSERT(
-      grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000), NULL)
-          .type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000),
+                                         NULL).type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->servers[i]);
   f->servers[i] = NULL;
 }
@@ -203,8 +202,8 @@ static void teardown_servers(servers_fixture *f) {
     if (f->servers[i] == NULL) continue;
     grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
     GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000),
-                                           n_millis_time(5000), NULL)
-                   .type == GRPC_OP_COMPLETE);
+                                           n_millis_time(5000),
+                                           NULL).type == GRPC_OP_COMPLETE);
     grpc_server_destroy(f->servers[i]);
   }
   grpc_completion_queue_shutdown(f->cq);
@@ -269,8 +268,8 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
     memset(s_valid, 0, f->num_servers * sizeof(int));
 
     c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
-                                 "/foo", "foo.test.google.fr", gpr_inf_future(GPR_CLOCK_REALTIME),
-                                 NULL);
+                                 "/foo", "foo.test.google.fr",
+                                 gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
     GPR_ASSERT(c);
     completed_client = 0;
 
@@ -303,8 +302,9 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
                grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL));
 
     s_idx = -1;
-    while ((ev = grpc_completion_queue_next(f->cq, n_millis_time(s_idx == -1 ? 3000 : 200), NULL))
-               .type != GRPC_QUEUE_TIMEOUT) {
+    while ((ev = grpc_completion_queue_next(
+                f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)).type !=
+           GRPC_QUEUE_TIMEOUT) {
       GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
       read_tag = ((int)(gpr_intptr)ev.tag);
       gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%d",
@@ -315,6 +315,7 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
         s_idx = read_tag - 1000;
         s_valid[s_idx] = 1;
         connection_sequence[iter_num] = s_idx;
+        break;
       } else if (read_tag == 1) {
         gpr_log(GPR_DEBUG, "client timed out");
         GPR_ASSERT(ev.success);
@@ -453,6 +454,8 @@ void run_spec(const test_spec *spec) {
   int *actual_connection_sequence;
   request_data rdata;
   servers_fixture *f;
+  grpc_channel_args args;
+  grpc_arg arg;
   rdata.call_details =
       gpr_malloc(sizeof(grpc_call_details) * spec->num_servers);
   f = setup_servers("127.0.0.1", &rdata, spec->num_servers);
@@ -462,7 +465,14 @@ void run_spec(const test_spec *spec) {
                                           f->num_servers, ",", NULL);
   gpr_asprintf(&client_hostport, "ipv4:%s?lb_policy=round_robin",
                servers_hostports_str);
-  client = grpc_insecure_channel_create(client_hostport, NULL, NULL);
+
+  arg.type = GRPC_ARG_INTEGER;
+  arg.key = "grpc.testing.fixed_reconnect_backoff";
+  arg.value.integer = 100;
+  args.num_args = 1;
+  args.args = &arg;
+
+  client = grpc_insecure_channel_create(client_hostport, &args, NULL);
 
   gpr_log(GPR_INFO, "Testing '%s' with servers=%s client=%s", spec->description,
           servers_hostports_str, client_hostport);
diff --git a/test/core/end2end/data/server1_cert.c b/test/core/end2end/data/server1_cert.c
index d31f2e2d0ed5fd3f4ff84624a796ebf68863ad85..82d65cf551a52b237fdfabc9d6ec51d5ea7f0ef2 100644
--- a/test/core/end2end/data/server1_cert.c
+++ b/test/core/end2end/data/server1_cert.c
@@ -34,82 +34,82 @@
 const char test_server1_cert[] = {
     0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43,
     0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
-    0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x6d, 0x7a, 0x43, 0x43,
-    0x41, 0x67, 0x53, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42,
-    0x41, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47,
-    0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, 0x42, 0x57,
+    0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x6e, 0x44, 0x43, 0x43,
+    0x41, 0x67, 0x57, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42,
+    0x42, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47,
+    0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x57,
     0x4d, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47,
     0x45, 0x77, 0x4a, 0x42, 0x56, 0x54, 0x45, 0x54, 0x0a, 0x4d, 0x42, 0x45,
-    0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x41, 0x77, 0x4b, 0x55, 0x32, 0x39,
+    0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x42, 0x4d, 0x4b, 0x55, 0x32, 0x39,
     0x74, 0x5a, 0x53, 0x31, 0x54, 0x64, 0x47, 0x46, 0x30, 0x5a, 0x54, 0x45,
-    0x68, 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77,
+    0x68, 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x68, 0x4d,
     0x59, 0x53, 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, 0x75, 0x5a, 0x58, 0x51,
     0x67, 0x56, 0x32, 0x6c, 0x6b, 0x5a, 0x32, 0x6c, 0x30, 0x63, 0x79, 0x42,
     0x51, 0x0a, 0x64, 0x48, 0x6b, 0x67, 0x54, 0x48, 0x52, 0x6b, 0x4d, 0x51,
-    0x38, 0x77, 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x41,
+    0x38, 0x77, 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x77,
     0x5a, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x59, 0x32, 0x45, 0x77, 0x48, 0x68,
-    0x63, 0x4e, 0x4d, 0x54, 0x51, 0x77, 0x4e, 0x7a, 0x49, 0x79, 0x4d, 0x44,
-    0x59, 0x77, 0x4d, 0x44, 0x55, 0x33, 0x57, 0x68, 0x63, 0x4e, 0x4d, 0x6a,
-    0x51, 0x77, 0x4e, 0x7a, 0x45, 0x35, 0x0a, 0x4d, 0x44, 0x59, 0x77, 0x4d,
-    0x44, 0x55, 0x33, 0x57, 0x6a, 0x42, 0x6b, 0x4d, 0x51, 0x73, 0x77, 0x43,
+    0x63, 0x4e, 0x4d, 0x54, 0x55, 0x78, 0x4d, 0x54, 0x41, 0x30, 0x4d, 0x44,
+    0x49, 0x79, 0x4d, 0x44, 0x49, 0x30, 0x57, 0x68, 0x63, 0x4e, 0x4d, 0x6a,
+    0x55, 0x78, 0x4d, 0x54, 0x41, 0x78, 0x0a, 0x4d, 0x44, 0x49, 0x79, 0x4d,
+    0x44, 0x49, 0x30, 0x57, 0x6a, 0x42, 0x6c, 0x4d, 0x51, 0x73, 0x77, 0x43,
     0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x56, 0x55,
     0x7a, 0x45, 0x52, 0x4d, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43,
     0x42, 0x4d, 0x49, 0x53, 0x57, 0x78, 0x73, 0x61, 0x57, 0x35, 0x76, 0x61,
     0x58, 0x4d, 0x78, 0x45, 0x44, 0x41, 0x4f, 0x42, 0x67, 0x4e, 0x56, 0x0a,
     0x42, 0x41, 0x63, 0x54, 0x42, 0x30, 0x4e, 0x6f, 0x61, 0x57, 0x4e, 0x68,
-    0x5a, 0x32, 0x38, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4e, 0x56,
-    0x42, 0x41, 0x6f, 0x54, 0x43, 0x30, 0x64, 0x76, 0x62, 0x32, 0x64, 0x73,
-    0x5a, 0x53, 0x42, 0x4a, 0x62, 0x6d, 0x4d, 0x75, 0x4d, 0x52, 0x6f, 0x77,
-    0x47, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x46, 0x42, 0x45, 0x71,
-    0x4c, 0x6e, 0x52, 0x6c, 0x0a, 0x63, 0x33, 0x51, 0x75, 0x5a, 0x32, 0x39,
-    0x76, 0x5a, 0x32, 0x78, 0x6c, 0x4c, 0x6d, 0x4e, 0x76, 0x62, 0x54, 0x43,
-    0x42, 0x6e, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69,
-    0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x4f,
-    0x42, 0x6a, 0x51, 0x41, 0x77, 0x67, 0x59, 0x6b, 0x43, 0x67, 0x59, 0x45,
-    0x41, 0x34, 0x63, 0x4d, 0x56, 0x4a, 0x79, 0x67, 0x73, 0x0a, 0x4a, 0x55,
-    0x6d, 0x6c, 0x67, 0x4d, 0x4d, 0x7a, 0x67, 0x64, 0x69, 0x30, 0x68, 0x31,
-    0x58, 0x6f, 0x43, 0x52, 0x37, 0x2b, 0x77, 0x77, 0x31, 0x70, 0x6f, 0x70,
-    0x30, 0x34, 0x4f, 0x4d, 0x4d, 0x79, 0x79, 0x37, 0x48, 0x2f, 0x69, 0x30,
-    0x50, 0x4a, 0x32, 0x57, 0x36, 0x59, 0x33, 0x35, 0x2b, 0x62, 0x34, 0x43,
-    0x4d, 0x38, 0x51, 0x72, 0x6b, 0x59, 0x65, 0x45, 0x61, 0x66, 0x55, 0x47,
-    0x44, 0x4f, 0x0a, 0x52, 0x59, 0x58, 0x36, 0x79, 0x56, 0x2f, 0x63, 0x48,
-    0x47, 0x47, 0x73, 0x44, 0x2f, 0x78, 0x30, 0x32, 0x79, 0x65, 0x36, 0x65,
-    0x79, 0x31, 0x55, 0x44, 0x74, 0x6b, 0x47, 0x41, 0x44, 0x2f, 0x6d, 0x70,
-    0x44, 0x45, 0x78, 0x38, 0x59, 0x43, 0x72, 0x6a, 0x41, 0x63, 0x31, 0x56,
-    0x66, 0x76, 0x74, 0x38, 0x46, 0x6b, 0x36, 0x43, 0x6e, 0x31, 0x57, 0x56,
-    0x49, 0x78, 0x56, 0x2f, 0x4a, 0x33, 0x30, 0x0a, 0x33, 0x78, 0x6a, 0x42,
-    0x73, 0x46, 0x67, 0x42, 0x79, 0x51, 0x35, 0x35, 0x52, 0x42, 0x70, 0x31,
-    0x4f, 0x4c, 0x5a, 0x66, 0x56, 0x4c, 0x6f, 0x36, 0x41, 0x6c, 0x65, 0x42,
-    0x44, 0x53, 0x62, 0x63, 0x78, 0x61, 0x45, 0x43, 0x41, 0x77, 0x45, 0x41,
-    0x41, 0x61, 0x4e, 0x72, 0x4d, 0x47, 0x6b, 0x77, 0x43, 0x51, 0x59, 0x44,
-    0x56, 0x52, 0x30, 0x54, 0x42, 0x41, 0x49, 0x77, 0x41, 0x44, 0x41, 0x4c,
-    0x0a, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x51, 0x38, 0x45, 0x42, 0x41, 0x4d,
-    0x43, 0x42, 0x65, 0x41, 0x77, 0x54, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30,
-    0x52, 0x42, 0x45, 0x67, 0x77, 0x52, 0x6f, 0x49, 0x51, 0x4b, 0x69, 0x35,
-    0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, 0x76, 0x62, 0x32, 0x64,
-    0x73, 0x5a, 0x53, 0x35, 0x6d, 0x63, 0x6f, 0x49, 0x59, 0x64, 0x32, 0x46,
-    0x30, 0x5a, 0x58, 0x4a, 0x36, 0x0a, 0x62, 0x32, 0x39, 0x70, 0x4c, 0x6e,
-    0x52, 0x6c, 0x63, 0x33, 0x51, 0x75, 0x5a, 0x32, 0x39, 0x76, 0x5a, 0x32,
-    0x78, 0x6c, 0x4c, 0x6d, 0x4a, 0x6c, 0x67, 0x68, 0x49, 0x71, 0x4c, 0x6e,
-    0x52, 0x6c, 0x63, 0x33, 0x51, 0x75, 0x65, 0x57, 0x39, 0x31, 0x64, 0x48,
-    0x56, 0x69, 0x5a, 0x53, 0x35, 0x6a, 0x62, 0x32, 0x32, 0x48, 0x42, 0x4d,
-    0x43, 0x6f, 0x41, 0x51, 0x4d, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x0a, 0x4b,
-    0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x46, 0x42,
-    0x51, 0x41, 0x44, 0x67, 0x59, 0x45, 0x41, 0x4d, 0x32, 0x49, 0x69, 0x30,
-    0x4c, 0x67, 0x54, 0x47, 0x62, 0x4a, 0x31, 0x6a, 0x34, 0x6f, 0x71, 0x58,
-    0x39, 0x62, 0x78, 0x56, 0x63, 0x78, 0x6d, 0x2b, 0x2f, 0x52, 0x35, 0x59,
-    0x66, 0x38, 0x6f, 0x69, 0x30, 0x61, 0x5a, 0x71, 0x54, 0x4a, 0x6c, 0x6e,
-    0x4c, 0x59, 0x53, 0x0a, 0x77, 0x58, 0x63, 0x42, 0x79, 0x6b, 0x78, 0x54,
-    0x78, 0x31, 0x38, 0x31, 0x73, 0x37, 0x57, 0x79, 0x66, 0x4a, 0x34, 0x39,
-    0x57, 0x77, 0x72, 0x59, 0x58, 0x6f, 0x37, 0x38, 0x7a, 0x54, 0x44, 0x41,
-    0x6e, 0x66, 0x31, 0x6d, 0x61, 0x30, 0x66, 0x50, 0x71, 0x33, 0x65, 0x34,
-    0x6d, 0x70, 0x73, 0x70, 0x76, 0x79, 0x6e, 0x64, 0x4c, 0x68, 0x31, 0x61,
-    0x2b, 0x4f, 0x61, 0x72, 0x48, 0x61, 0x31, 0x65, 0x0a, 0x61, 0x54, 0x30,
-    0x44, 0x49, 0x49, 0x59, 0x6b, 0x37, 0x71, 0x65, 0x45, 0x61, 0x31, 0x59,
-    0x63, 0x56, 0x6c, 0x6a, 0x78, 0x32, 0x4b, 0x79, 0x4c, 0x64, 0x30, 0x72,
-    0x31, 0x42, 0x42, 0x41, 0x66, 0x72, 0x77, 0x79, 0x47, 0x61, 0x45, 0x50,
-    0x56, 0x65, 0x4a, 0x51, 0x56, 0x59, 0x57, 0x61, 0x4f, 0x4a, 0x52, 0x55,
-    0x32, 0x77, 0x65, 0x2f, 0x4b, 0x44, 0x34, 0x6f, 0x6a, 0x66, 0x39, 0x73,
-    0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43,
+    0x5a, 0x32, 0x38, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, 0x4e, 0x56,
+    0x42, 0x41, 0x6f, 0x54, 0x44, 0x45, 0x56, 0x34, 0x59, 0x57, 0x31, 0x77,
+    0x62, 0x47, 0x55, 0x73, 0x49, 0x45, 0x4e, 0x76, 0x4c, 0x6a, 0x45, 0x61,
+    0x4d, 0x42, 0x67, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x78, 0x51, 0x52,
+    0x4b, 0x69, 0x35, 0x30, 0x0a, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64,
+    0x76, 0x62, 0x32, 0x64, 0x73, 0x5a, 0x53, 0x35, 0x6a, 0x62, 0x32, 0x30,
+    0x77, 0x67, 0x5a, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a,
+    0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41,
+    0x44, 0x67, 0x59, 0x30, 0x41, 0x4d, 0x49, 0x47, 0x4a, 0x41, 0x6f, 0x47,
+    0x42, 0x41, 0x4f, 0x48, 0x44, 0x46, 0x53, 0x63, 0x6f, 0x0a, 0x4c, 0x43,
+    0x56, 0x4a, 0x70, 0x59, 0x44, 0x44, 0x4d, 0x34, 0x48, 0x59, 0x74, 0x49,
+    0x64, 0x56, 0x36, 0x41, 0x6b, 0x65, 0x2f, 0x73, 0x4d, 0x4e, 0x61, 0x61,
+    0x4b, 0x64, 0x4f, 0x44, 0x6a, 0x44, 0x4d, 0x73, 0x75, 0x78, 0x2f, 0x34,
+    0x74, 0x44, 0x79, 0x64, 0x6c, 0x75, 0x6d, 0x4e, 0x2b, 0x66, 0x6d, 0x2b,
+    0x41, 0x6a, 0x50, 0x45, 0x4b, 0x35, 0x47, 0x48, 0x68, 0x47, 0x6e, 0x31,
+    0x42, 0x67, 0x0a, 0x7a, 0x6b, 0x57, 0x46, 0x2b, 0x73, 0x6c, 0x66, 0x33,
+    0x42, 0x78, 0x68, 0x72, 0x41, 0x2f, 0x38, 0x64, 0x4e, 0x73, 0x6e, 0x75,
+    0x6e, 0x73, 0x74, 0x56, 0x41, 0x37, 0x5a, 0x42, 0x67, 0x41, 0x2f, 0x35,
+    0x71, 0x51, 0x78, 0x4d, 0x66, 0x47, 0x41, 0x71, 0x34, 0x77, 0x48, 0x4e,
+    0x56, 0x58, 0x37, 0x37, 0x66, 0x42, 0x5a, 0x4f, 0x67, 0x70, 0x39, 0x56,
+    0x6c, 0x53, 0x4d, 0x56, 0x66, 0x79, 0x64, 0x0a, 0x39, 0x4e, 0x38, 0x59,
+    0x77, 0x62, 0x42, 0x59, 0x41, 0x63, 0x6b, 0x4f, 0x65, 0x55, 0x51, 0x61,
+    0x64, 0x54, 0x69, 0x32, 0x58, 0x31, 0x53, 0x36, 0x4f, 0x67, 0x4a, 0x58,
+    0x67, 0x51, 0x30, 0x6d, 0x33, 0x4d, 0x57, 0x68, 0x41, 0x67, 0x4d, 0x42,
+    0x41, 0x41, 0x47, 0x6a, 0x61, 0x7a, 0x42, 0x70, 0x4d, 0x41, 0x6b, 0x47,
+    0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x51, 0x43, 0x4d, 0x41, 0x41, 0x77,
+    0x0a, 0x43, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x42, 0x41, 0x51,
+    0x44, 0x41, 0x67, 0x58, 0x67, 0x4d, 0x45, 0x38, 0x47, 0x41, 0x31, 0x55,
+    0x64, 0x45, 0x51, 0x52, 0x49, 0x4d, 0x45, 0x61, 0x43, 0x45, 0x43, 0x6f,
+    0x75, 0x64, 0x47, 0x56, 0x7a, 0x64, 0x43, 0x35, 0x6e, 0x62, 0x32, 0x39,
+    0x6e, 0x62, 0x47, 0x55, 0x75, 0x5a, 0x6e, 0x4b, 0x43, 0x47, 0x48, 0x64,
+    0x68, 0x64, 0x47, 0x56, 0x79, 0x0a, 0x65, 0x6d, 0x39, 0x76, 0x61, 0x53,
+    0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6d, 0x64, 0x76, 0x62, 0x32,
+    0x64, 0x73, 0x5a, 0x53, 0x35, 0x69, 0x5a, 0x59, 0x49, 0x53, 0x4b, 0x69,
+    0x35, 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6e, 0x6c, 0x76, 0x64, 0x58,
+    0x52, 0x31, 0x59, 0x6d, 0x55, 0x75, 0x59, 0x32, 0x39, 0x74, 0x68, 0x77,
+    0x54, 0x41, 0x71, 0x41, 0x45, 0x44, 0x4d, 0x41, 0x30, 0x47, 0x0a, 0x43,
+    0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43,
+    0x77, 0x55, 0x41, 0x41, 0x34, 0x47, 0x42, 0x41, 0x4a, 0x46, 0x58, 0x56,
+    0x69, 0x66, 0x51, 0x4e, 0x75, 0x62, 0x31, 0x4c, 0x55, 0x50, 0x34, 0x4a,
+    0x6c, 0x6e, 0x58, 0x35, 0x6c, 0x58, 0x4e, 0x6c, 0x6f, 0x38, 0x46, 0x78,
+    0x5a, 0x32, 0x61, 0x31, 0x32, 0x41, 0x46, 0x51, 0x73, 0x2b, 0x62, 0x7a,
+    0x6f, 0x4a, 0x36, 0x0a, 0x68, 0x4d, 0x30, 0x34, 0x34, 0x45, 0x44, 0x6a,
+    0x71, 0x79, 0x78, 0x55, 0x71, 0x53, 0x62, 0x56, 0x65, 0x50, 0x4b, 0x30,
+    0x6e, 0x69, 0x33, 0x77, 0x31, 0x66, 0x48, 0x51, 0x42, 0x35, 0x72, 0x59,
+    0x39, 0x79, 0x59, 0x43, 0x35, 0x66, 0x38, 0x47, 0x37, 0x61, 0x71, 0x71,
+    0x54, 0x59, 0x31, 0x51, 0x4f, 0x68, 0x6f, 0x55, 0x6b, 0x38, 0x5a, 0x54,
+    0x53, 0x54, 0x52, 0x70, 0x6e, 0x6b, 0x54, 0x68, 0x0a, 0x79, 0x34, 0x6a,
+    0x6a, 0x64, 0x76, 0x54, 0x5a, 0x65, 0x4c, 0x44, 0x56, 0x42, 0x6c, 0x75,
+    0x65, 0x5a, 0x55, 0x54, 0x44, 0x52, 0x6d, 0x79, 0x32, 0x66, 0x65, 0x59,
+    0x35, 0x61, 0x5a, 0x49, 0x55, 0x31, 0x38, 0x76, 0x46, 0x44, 0x4b, 0x30,
+    0x38, 0x64, 0x54, 0x47, 0x30, 0x41, 0x38, 0x37, 0x70, 0x70, 0x70, 0x75,
+    0x76, 0x31, 0x4c, 0x4e, 0x49, 0x52, 0x33, 0x6c, 0x6f, 0x76, 0x65, 0x55,
+    0x38, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43,
     0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
     0x2d, 0x2d, 0x2d, 0x0a, 0x00};
diff --git a/test/core/end2end/fixtures/h2_fakesec.c b/test/core/end2end/fixtures/h2_fakesec.c
index 3e64cc08e88becae2078069c30f5d0bccd0f980f..bc009e1df1ef26e45478dc7fb0137a761227d9f4 100644
--- a/test/core/end2end/fixtures/h2_fakesec.c
+++ b/test/core/end2end/fixtures/h2_fakesec.c
@@ -73,14 +73,14 @@ static void process_auth_failure(void *state, grpc_auth_context *ctx,
   cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
 }
 
-static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f,
-                                                grpc_channel_args *client_args,
-                                                grpc_credentials *creds) {
+static void chttp2_init_client_secure_fullstack(
+    grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
+    grpc_channel_credentials *creds) {
   fullstack_secure_fixture_data *ffd = f->fixture_data;
   f->client =
       grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL);
   GPR_ASSERT(f->client != NULL);
-  grpc_credentials_release(creds);
+  grpc_channel_credentials_release(creds);
 }
 
 static void chttp2_init_server_secure_fullstack(
@@ -106,7 +106,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
 
 static void chttp2_init_client_fake_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
-  grpc_credentials *fake_ts_creds =
+  grpc_channel_credentials *fake_ts_creds =
       grpc_fake_transport_security_credentials_create();
   chttp2_init_client_secure_fullstack(f, client_args, fake_ts_creds);
 }
diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c
index 10db6c2c6a5b4b38dbed9a7daf47a59c1d7f0e1c..7a34cc67d875a0b0f69da00cdd7b84afb7c1a117 100644
--- a/test/core/end2end/fixtures/h2_oauth2.c
+++ b/test/core/end2end/fixtures/h2_oauth2.c
@@ -118,14 +118,14 @@ static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
   return f;
 }
 
-static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f,
-                                                grpc_channel_args *client_args,
-                                                grpc_credentials *creds) {
+static void chttp2_init_client_secure_fullstack(
+    grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
+    grpc_channel_credentials *creds) {
   fullstack_secure_fixture_data *ffd = f->fixture_data;
   f->client =
       grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL);
   GPR_ASSERT(f->client != NULL);
-  grpc_credentials_release(creds);
+  grpc_channel_credentials_release(creds);
 }
 
 static void chttp2_init_server_secure_fullstack(
@@ -151,12 +151,12 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
 
 static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
-  grpc_credentials *ssl_creds =
+  grpc_channel_credentials *ssl_creds =
       grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
-  grpc_credentials *oauth2_creds =
+  grpc_call_credentials *oauth2_creds =
       grpc_md_only_test_credentials_create("Authorization", oauth2_md, 1);
-  grpc_credentials *ssl_oauth2_creds =
-      grpc_composite_credentials_create(ssl_creds, oauth2_creds, NULL);
+  grpc_channel_credentials *ssl_oauth2_creds =
+      grpc_composite_channel_credentials_create(ssl_creds, oauth2_creds, NULL);
   grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                 GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                 {"foo.test.google.fr"}};
@@ -164,8 +164,8 @@ static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
       grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);
   chttp2_init_client_secure_fullstack(f, new_client_args, ssl_oauth2_creds);
   grpc_channel_args_destroy(new_client_args);
-  grpc_credentials_release(ssl_creds);
-  grpc_credentials_release(oauth2_creds);
+  grpc_channel_credentials_release(ssl_creds);
+  grpc_call_credentials_release(oauth2_creds);
 }
 
 static int fail_server_auth_check(grpc_channel_args *server_args) {
diff --git a/test/core/end2end/fixtures/h2_ssl+poll.c b/test/core/end2end/fixtures/h2_ssl+poll.c
index c2f41f48869179bba272efc2bde547e8f7a33630..37e1758f00bcea71c53fe6a6abd2912bca99d291 100644
--- a/test/core/end2end/fixtures/h2_ssl+poll.c
+++ b/test/core/end2end/fixtures/h2_ssl+poll.c
@@ -76,14 +76,14 @@ static void process_auth_failure(void *state, grpc_auth_context *ctx,
   cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
 }
 
-static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f,
-                                                grpc_channel_args *client_args,
-                                                grpc_credentials *creds) {
+static void chttp2_init_client_secure_fullstack(
+    grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
+    grpc_channel_credentials *creds) {
   fullstack_secure_fixture_data *ffd = f->fixture_data;
   f->client =
       grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL);
   GPR_ASSERT(f->client != NULL);
-  grpc_credentials_release(creds);
+  grpc_channel_credentials_release(creds);
 }
 
 static void chttp2_init_server_secure_fullstack(
@@ -109,7 +109,8 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
 
 static void chttp2_init_client_simple_ssl_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
-  grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL);
+  grpc_channel_credentials *ssl_creds =
+      grpc_ssl_credentials_create(NULL, NULL, NULL);
   grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                 GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                 {"foo.test.google.fr"}};
diff --git a/test/core/end2end/fixtures/h2_ssl.c b/test/core/end2end/fixtures/h2_ssl.c
index 896c60c5077d50883751be9993fd7ed2b287c354..f5a006bd08606e54863e8d60c71357924ec7f4f5 100644
--- a/test/core/end2end/fixtures/h2_ssl.c
+++ b/test/core/end2end/fixtures/h2_ssl.c
@@ -76,14 +76,14 @@ static void process_auth_failure(void *state, grpc_auth_context *ctx,
   cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
 }
 
-static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f,
-                                                grpc_channel_args *client_args,
-                                                grpc_credentials *creds) {
+static void chttp2_init_client_secure_fullstack(
+    grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
+    grpc_channel_credentials *creds) {
   fullstack_secure_fixture_data *ffd = f->fixture_data;
   f->client =
       grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL);
   GPR_ASSERT(f->client != NULL);
-  grpc_credentials_release(creds);
+  grpc_channel_credentials_release(creds);
 }
 
 static void chttp2_init_server_secure_fullstack(
@@ -109,7 +109,8 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
 
 static void chttp2_init_client_simple_ssl_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
-  grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL);
+  grpc_channel_credentials *ssl_creds =
+      grpc_ssl_credentials_create(NULL, NULL, NULL);
   grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                 GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                 {"foo.test.google.fr"}};
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.c b/test/core/end2end/fixtures/h2_ssl_proxy.c
index 413a8b84cd03144293c9cf1fa3a2d5ab5c69fd34..7233cdbe2d882e5439043eca83b2ce407231d7c7 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.c
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.c
@@ -66,7 +66,8 @@ static grpc_server *create_proxy_server(const char *port) {
 
 static grpc_channel *create_proxy_client(const char *target) {
   grpc_channel *channel;
-  grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL);
+  grpc_channel_credentials *ssl_creds =
+      grpc_ssl_credentials_create(NULL, NULL, NULL);
   grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                 GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                 {"foo.test.google.fr"}};
@@ -74,7 +75,7 @@ static grpc_channel *create_proxy_client(const char *target) {
   client_args.num_args = 1;
   client_args.args = &ssl_name_override;
   channel = grpc_secure_channel_create(ssl_creds, target, &client_args, NULL);
-  grpc_credentials_release(ssl_creds);
+  grpc_channel_credentials_release(ssl_creds);
   return channel;
 }
 
@@ -104,15 +105,15 @@ static void process_auth_failure(void *state, grpc_auth_context *ctx,
   cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
 }
 
-static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f,
-                                                grpc_channel_args *client_args,
-                                                grpc_credentials *creds) {
+static void chttp2_init_client_secure_fullstack(
+    grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
+    grpc_channel_credentials *creds) {
   fullstack_secure_fixture_data *ffd = f->fixture_data;
   f->client = grpc_secure_channel_create(
       creds, grpc_end2end_proxy_get_client_target(ffd->proxy), client_args,
       NULL);
   GPR_ASSERT(f->client != NULL);
-  grpc_credentials_release(creds);
+  grpc_channel_credentials_release(creds);
 }
 
 static void chttp2_init_server_secure_fullstack(
@@ -138,7 +139,8 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
 
 static void chttp2_init_client_simple_ssl_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
-  grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL);
+  grpc_channel_credentials *ssl_creds =
+      grpc_ssl_credentials_create(NULL, NULL, NULL);
   grpc_arg ssl_name_override = {GRPC_ARG_STRING,
                                 GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
                                 {"foo.test.google.fr"}};
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index 1090ad667d124cce01985c6705607920485de335..434e75dd15ed22b9c3a80708ec91746d1f022cad 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -146,7 +146,6 @@ void grpc_end2end_proxy_destroy(grpc_end2end_proxy *proxy) {
 }
 
 static void unrefpc(proxy_call *pc, const char *reason) {
-  gpr_log(GPR_DEBUG, "PROXY UNREF %s", reason);
   if (gpr_unref(&pc->refs)) {
     grpc_call_destroy(pc->c2p);
     grpc_call_destroy(pc->p2s);
@@ -158,10 +157,7 @@ static void unrefpc(proxy_call *pc, const char *reason) {
   }
 }
 
-static void refpc(proxy_call *pc, const char *reason) {
-  gpr_log(GPR_DEBUG, "PROXY   REF %s", reason);
-  gpr_ref(&pc->refs);
-}
+static void refpc(proxy_call *pc, const char *reason) { gpr_ref(&pc->refs); }
 
 static void on_c2p_sent_initial_metadata(void *arg, int success) {
   proxy_call *pc = arg;
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 38d3b2218a37ee9af59aa3b950e9b588cf25baf1..33687b8cd4c86484605d467c7f11c2077011fd36 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -37,8 +37,8 @@ import collections
 import hashlib
 
 
-FixtureOptions = collections.namedtuple('FixtureOptions', 'fullstack includes_proxy dns_resolver secure platforms ci_mac')
-default_unsecure_fixture_options = FixtureOptions(True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True)
+FixtureOptions = collections.namedtuple('FixtureOptions', 'fullstack includes_proxy dns_resolver secure platforms ci_mac tracing')
+default_unsecure_fixture_options = FixtureOptions(True, False, True, False, ['windows', 'linux', 'mac', 'posix'], True, False)
 socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace(fullstack=False, dns_resolver=False)
 default_secure_fixture_options = default_unsecure_fixture_options._replace(secure=True)
 uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, platforms=['linux', 'mac', 'posix'])
@@ -54,7 +54,7 @@ END2END_FIXTURES = {
     'h2_proxy': default_unsecure_fixture_options._replace(includes_proxy=True, ci_mac=False),
     'h2_sockpair_1byte': socketpair_unsecure_fixture_options._replace(ci_mac=False),
     'h2_sockpair': socketpair_unsecure_fixture_options._replace(ci_mac=False),
-    'h2_sockpair+trace': socketpair_unsecure_fixture_options,
+    'h2_sockpair+trace': socketpair_unsecure_fixture_options._replace(tracing=True),
     'h2_ssl': default_secure_fixture_options,
     'h2_ssl+poll': default_secure_fixture_options._replace(platforms=['linux']),
     'h2_ssl_proxy': default_secure_fixture_options._replace(includes_proxy=True, ci_mac=False),
@@ -63,8 +63,8 @@ END2END_FIXTURES = {
     'h2_uds': uds_fixture_options,
 }
 
-TestOptions = collections.namedtuple('TestOptions', 'needs_fullstack needs_dns proxyable flaky secure')
-default_test_options = TestOptions(False, False, True, False, False)
+TestOptions = collections.namedtuple('TestOptions', 'needs_fullstack needs_dns proxyable flaky secure traceable')
+default_test_options = TestOptions(False, False, True, False, False, True)
 connectivity_test_options = default_test_options._replace(needs_fullstack=True)
 
 # maps test names to options
@@ -85,6 +85,7 @@ END2END_TESTS = {
     'disappearing_server': connectivity_test_options,
     'empty_batch': default_test_options,
     'graceful_server_shutdown': default_test_options,
+    'hpack_size': default_test_options._replace(proxyable=False, traceable=False),
     'high_initial_seqno': default_test_options,
     'invoke_large_request': default_test_options,
     'large_metadata': default_test_options,
@@ -117,6 +118,9 @@ def compatible(f, t):
   if not END2END_TESTS[t].proxyable:
     if END2END_FIXTURES[f].includes_proxy:
       return False
+  if not END2END_TESTS[t].traceable:
+    if END2END_FIXTURES[f].tracing:
+      return False
   return True
 
 
diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c
index 4aeade1336e1f6fac7a90439f0bfaa6192cd86a8..bbfad21b62e101df5348ce4cd92a4ba3536d8145 100644
--- a/test/core/end2end/tests/call_creds.c
+++ b/test/core/end2end/tests/call_creds.c
@@ -132,27 +132,6 @@ static void print_auth_context(int is_client, const grpc_auth_context *ctx) {
   }
 }
 
-static void test_call_creds_failure(grpc_end2end_test_config config) {
-  grpc_call *c;
-  grpc_credentials *creds = NULL;
-  grpc_end2end_test_fixture f =
-      begin_test(config, "test_call_creds_failure", 0);
-  gpr_timespec deadline = five_seconds_time();
-  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "foo.test.google.fr", deadline, NULL);
-  GPR_ASSERT(c);
-
-  /* Try with credentials unfit to be set on a call (channel creds). */
-  creds = grpc_fake_transport_security_credentials_create();
-  GPR_ASSERT(grpc_call_set_credentials(c, creds) != GRPC_CALL_OK);
-  grpc_credentials_release(creds);
-
-  grpc_call_destroy(c);
-
-  end_test(&f);
-  config.tear_down_data(&f);
-}
-
 static void request_response_with_payload_and_call_creds(
     const char *test_name, grpc_end2end_test_config config,
     override_mode mode) {
@@ -180,7 +159,7 @@ static void request_response_with_payload_and_call_creds(
   char *details = NULL;
   size_t details_capacity = 0;
   int was_cancelled = 2;
-  grpc_credentials *creds = NULL;
+  grpc_call_credentials *creds = NULL;
   grpc_auth_context *s_auth_context = NULL;
   grpc_auth_context *c_auth_context = NULL;
 
@@ -197,7 +176,7 @@ static void request_response_with_payload_and_call_creds(
     case NONE:
       break;
     case OVERRIDE:
-      grpc_credentials_release(creds);
+      grpc_call_credentials_release(creds);
       creds = grpc_google_iam_credentials_create(overridden_iam_token,
                                                  overridden_iam_selector, NULL);
       GPR_ASSERT(creds != NULL);
@@ -207,7 +186,7 @@ static void request_response_with_payload_and_call_creds(
       GPR_ASSERT(grpc_call_set_credentials(c, NULL) == GRPC_CALL_OK);
       break;
   }
-  grpc_credentials_release(creds);
+  grpc_call_credentials_release(creds);
 
   grpc_metadata_array_init(&initial_metadata_recv);
   grpc_metadata_array_init(&trailing_metadata_recv);
@@ -412,7 +391,7 @@ static void test_request_with_server_rejecting_client_creds(
   gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
   grpc_byte_buffer *request_payload =
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
-  grpc_credentials *creds;
+  grpc_call_credentials *creds;
 
   f = begin_test(config, "test_request_with_server_rejecting_client_creds", 1);
   cqv = cq_verifier_create(f.cq);
@@ -424,7 +403,7 @@ static void test_request_with_server_rejecting_client_creds(
   creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL);
   GPR_ASSERT(creds != NULL);
   GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK);
-  grpc_credentials_release(creds);
+  grpc_call_credentials_release(creds);
 
   grpc_metadata_array_init(&initial_metadata_recv);
   grpc_metadata_array_init(&trailing_metadata_recv);
@@ -490,7 +469,6 @@ static void test_request_with_server_rejecting_client_creds(
 
 void grpc_end2end_tests(grpc_end2end_test_config config) {
   if (config.feature_mask & FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS) {
-    test_call_creds_failure(config);
     test_request_response_with_payload_and_call_creds(config);
     test_request_response_with_payload_and_overridden_call_creds(config);
     test_request_response_with_payload_and_deleted_call_creds(config);
diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c
index eecfa83fa4858c447d43f3b9edc55f22300caa05..2005e5f8816820272a53bdda643a258314e8d097 100644
--- a/test/core/end2end/tests/cancel_with_status.c
+++ b/test/core/end2end/tests/cancel_with_status.c
@@ -166,7 +166,8 @@ static void simple_request_body(grpc_end2end_test_fixture f, size_t num_ops) {
   cq_verifier_destroy(cqv);
 }
 
-static void test_invoke_simple_request(grpc_end2end_test_config config, size_t num_ops) {
+static void test_invoke_simple_request(grpc_end2end_test_config config,
+                                       size_t num_ops) {
   grpc_end2end_test_fixture f;
 
   f = begin_test(config, "test_invoke_simple_request", NULL, NULL);
diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c
new file mode 100644
index 0000000000000000000000000000000000000000..997969d3cce2dd73dff464199b4157455d2e5502
--- /dev/null
+++ b/test/core/end2end/tests/hpack_size.c
@@ -0,0 +1,446 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/support/string.h"
+#include "test/core/end2end/cq_verifier.h"
+
+static void *tag(gpr_intptr t) { return (void *)t; }
+
+const char *hobbits[][2] = {{"Adaldrida", "Brandybuck"},
+                            {"Adamanta", "Took"},
+                            {"Adalgrim", "Took"},
+                            {"Adelard", "Took"},
+                            {"Amaranth", "Brandybuck"},
+                            {"Andwise", "Roper"},
+                            {"Angelica", "Baggins"},
+                            {"Asphodel", "Burrows"},
+                            {"Balbo", "Baggins"},
+                            {"Bandobras", "Took"},
+                            {"Belba", "Bolger"},
+                            {"Bell", "Gamgee"},
+                            {"Belladonna", "Baggins"},
+                            {"Berylla", "Baggins"},
+                            {"Bilbo", "Baggins"},
+                            {"Bilbo", "Gardner"},
+                            {"Bill", "Butcher"},
+                            {"Bingo", "Baggins"},
+                            {"Bodo", "Proudfoot"},
+                            {"Bowman", "Cotton"},
+                            {"Bungo", "Baggins"},
+                            {"Camellia", "Sackville"},
+                            {"Carl", "Cotton"},
+                            {"Celandine", "Brandybuck"},
+                            {"Chica", "Baggins"},
+                            {"Daddy", "Twofoot"},
+                            {"Daisy", "Boffin"},
+                            {"Diamond", "Took"},
+                            {"Dinodas", "Brandybuck"},
+                            {"Doderic", "Brandybuck"},
+                            {"Dodinas", "Brandybuck"},
+                            {"Donnamira", "Boffin"},
+                            {"Dora", "Baggins"},
+                            {"Drogo", "Baggins"},
+                            {"Dudo", "Baggins"},
+                            {"Eglantine", "Took"},
+                            {"Elanor", "Fairbairn"},
+                            {"Elfstan", "Fairbairn"},
+                            {"Esmeralda", "Brandybuck"},
+                            {"Estella", "Brandybuck"},
+                            {"Everard", "Took"},
+                            {"Falco", "Chubb-Baggins"},
+                            {"Faramir", "Took"},
+                            {"Farmer", "Maggot"},
+                            {"Fastolph", "Bolger"},
+                            {"Ferdibrand", "Took"},
+                            {"Ferdinand", "Took"},
+                            {"Ferumbras", "Took"},
+                            {"Ferumbras", "Took"},
+                            {"Filibert", "Bolger"},
+                            {"Firiel", "Fairbairn"},
+                            {"Flambard", "Took"},
+                            {"Folco", "Boffin"},
+                            {"Fortinbras", "Took"},
+                            {"Fortinbras", "Took"},
+                            {"Fosco", "Baggins"},
+                            {"Fredegar", "Bolger"},
+                            {"Frodo", "Baggins"},
+                            {"Frodo", "Gardner"},
+                            {"Gerontius", "Took"},
+                            {"Gilly", "Baggins"},
+                            {"Goldilocks", "Took"},
+                            {"Gorbadoc", "Brandybuck"},
+                            {"Gorbulas", "Brandybuck"},
+                            {"Gorhendad", "Brandybuck"},
+                            {"Gormadoc", "Brandybuck"},
+                            {"Griffo", "Boffin"},
+                            {"Halfast", "Gamgee"},
+                            {"Halfred", "Gamgee"},
+                            {"Halfred", "Greenhand"},
+                            {"Hanna", "Brandybuck"},
+                            {"Hamfast", "Gamgee"},
+                            {"Hamfast", "Gardner"},
+                            {"Hamson", "Gamgee"},
+                            {"Harding", "Gardner"},
+                            {"Hilda", "Brandybuck"},
+                            {"Hildibrand", "Took"},
+                            {"Hildifons", "Took"},
+                            {"Hildigard", "Took"},
+                            {"Hildigrim", "Took"},
+                            {"Hob", "Gammidge"},
+                            {"Hob", "Hayward"},
+                            {"Hobson", "Gamgee"},
+                            {"Holfast", "Gardner"},
+                            {"Holman", "Cotton"},
+                            {"Holman", "Greenhand"},
+                            {"Hugo", "Boffin"},
+                            {"Hugo", "Bracegirdle"},
+                            {"Ilberic", "Brandybuck"},
+                            {"Isembard", "Took"},
+                            {"Isembold", "Took"},
+                            {"Isengar", "Took"},
+                            {"Isengrim", "Took"},
+                            {"Isengrim", "Took"},
+                            {"Isumbras", "Took"},
+                            {"Isumbras", "Took"},
+                            {"Jolly", "Cotton"},
+                            {"Lalia", "Took"},
+                            {"Largo", "Baggins"},
+                            {"Laura", "Baggins"},
+                            {"Lily", "Goodbody"},
+                            {"Lily", "Cotton"},
+                            {"Linda", "Proudfoot"},
+                            {"Lobelia", "Sackville-Baggins"},
+                            {"Longo", "Baggins"},
+                            {"Lotho", "Sackville-Baggins"},
+                            {"Madoc", "Brandybuck"},
+                            {"Malva", "Brandybuck"},
+                            {"Marigold", "Cotton"},
+                            {"Marmadas", "Brandybuck"},
+                            {"Marmadoc", "Brandybuck"},
+                            {"Marroc", "Brandybuck"},
+                            {"May", "Gamgee"},
+                            {"Melilot", "Brandybuck"},
+                            {"Menegilda", "Brandybuck"},
+                            {"Mentha", "Brandybuck"},
+                            {"Meriadoc", "Brandybuck"},
+                            {"Merimac", "Brandybuck"},
+                            {"Merimas", "Brandybuck"},
+                            {"Merry", "Gardner"},
+                            {"Milo", "Burrows"},
+                            {"Mimosa", "Baggins"},
+                            {"Minto", "Burrows"},
+                            {"Mirabella", "Brandybuck"},
+                            {"Moro", "Burrows"},
+                            {"Mosco", "Burrows"},
+                            {"Mungo", "Baggins"},
+                            {"Myrtle", "Burrows"},
+                            {"Odo", "Proudfoot"},
+                            {"Odovacar", "Bolger"},
+                            {"Olo", "Proudfoot"},
+                            {"Orgulas", "Brandybuck"},
+                            {"Otho", "Sackville-Baggins"},
+                            {"Paladin", "Took"},
+                            {"Pansy", "Bolger"},
+                            {"Pearl", "Took"},
+                            {"Peony", "Burrows"},
+                            {"Peregrin", "Took"},
+                            {"Pervinca", "Took"},
+                            {"Pimpernel", "Took"},
+                            {"Pippin", "Gardner"},
+                            {"Polo", "Baggins"},
+                            {"Ponto", "Baggins"},
+                            {"Porto", "Baggins"},
+                            {"Posco", "Baggins"},
+                            {"Poppy", "Bolger"},
+                            {"Primrose", "Gardner"},
+                            {"Primula", "Baggins"},
+                            {"Prisca", "Bolger"},
+                            {"Reginard", "Took"},
+                            {"Robin", "Smallburrow"},
+                            {"Robin", "Gardner"},
+                            {"Rorimac", "Brandybuck"},
+                            {"Rosa", "Took"},
+                            {"Rosamunda", "Bolger"},
+                            {"Rose", "Gardner"},
+                            {"Ruby", "Baggins"},
+                            {"Ruby", "Gardner"},
+                            {"Rudigar", "Bolger"},
+                            {"Rufus", "Burrows"},
+                            {"Sadoc", "Brandybuck"},
+                            {"Salvia", "Bolger"},
+                            {"Samwise", "Gamgee"},
+                            {"Sancho", "Proudfoot"},
+                            {"Saradas", "Brandybuck"},
+                            {"Saradoc", "Brandybuck"},
+                            {"Seredic", "Brandybuck"},
+                            {"Sigismond", "Took"},
+                            {"Smeagol", "Gollum"},
+                            {"Tanta", "Baggins"},
+                            {"Ted", "Sandyman"},
+                            {"Tobold", "Hornblower"},
+                            {"Togo", "Goodbody"},
+                            {"Tolman", "Cotton"},
+                            {"Tolman", "Gardner"},
+                            {"Widow", "Rumble"},
+                            {"Wilcome", "Cotton"},
+                            {"Wilcome", "Cotton"},
+                            {"Wilibald", "Bolger"},
+                            {"Will", "Whitfoot"},
+                            {"Wiseman", "Gamwich"}};
+
+const char *dragons[] = {"Ancalagon", "Glaurung", "Scatha",
+                         "Smaug the Magnificent"};
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char *test_name,
+                                            grpc_channel_args *client_args,
+                                            grpc_channel_args *server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  config.init_client(&f, client_args);
+  config.init_server(&f, server_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_time(int n) {
+  return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n);
+}
+
+static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); }
+
+static void drain_cq(grpc_completion_queue *cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture *f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
+                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
+                                         NULL).type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = NULL;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture *f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = NULL;
+}
+
+static void end_test(grpc_end2end_test_fixture *f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+}
+
+static void simple_request_body(grpc_end2end_test_fixture f, size_t index) {
+  grpc_call *c;
+  grpc_call *s;
+  gpr_timespec deadline = five_seconds_time();
+  cq_verifier *cqv = cq_verifier_create(f.cq);
+  grpc_op ops[6];
+  grpc_op *op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  grpc_metadata extra_metadata[3];
+  char *details = NULL;
+  size_t details_capacity = 0;
+  int was_cancelled = 2;
+
+  memset(extra_metadata, 0, sizeof(extra_metadata));
+  extra_metadata[0].key = "hobbit-first-name";
+  extra_metadata[0].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][0];
+  extra_metadata[0].value_length = strlen(extra_metadata[0].value);
+  extra_metadata[1].key = "hobbit-second-name";
+  extra_metadata[1].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][1];
+  extra_metadata[1].value_length = strlen(extra_metadata[1].value);
+  extra_metadata[2].key = "dragon";
+  extra_metadata[2].value = dragons[index % GPR_ARRAY_SIZE(dragons)];
+  extra_metadata[2].value_length = strlen(extra_metadata[2].value);
+
+  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               "/foo", "foo.test.google.fr:1234", deadline,
+                               NULL);
+  GPR_ASSERT(c);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = GPR_ARRAY_SIZE(extra_metadata);
+  op->data.send_initial_metadata.metadata = extra_metadata;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  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);
+
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
+  op->data.send_status_from_server.status_details = "xyz";
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = NULL;
+  op++;
+  error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  cq_expect_completion(cqv, tag(102), 1);
+  cq_expect_completion(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
+  GPR_ASSERT(0 == strcmp(details, "xyz"));
+  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
+  GPR_ASSERT(was_cancelled == 1);
+
+  gpr_free(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  grpc_call_destroy(c);
+  grpc_call_destroy(s);
+
+  cq_verifier_destroy(cqv);
+}
+
+static void test_size(grpc_end2end_test_config config, int encode_size,
+                      int decode_size) {
+  size_t i;
+  grpc_end2end_test_fixture f;
+  grpc_arg server_arg;
+  grpc_channel_args server_args;
+  grpc_arg client_arg;
+  grpc_channel_args client_args;
+  char *name;
+
+  server_arg.type = GRPC_ARG_INTEGER;
+  server_arg.key = GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER;
+  server_arg.value.integer = decode_size;
+  server_args.num_args = 1;
+  server_args.args = &server_arg;
+
+  client_arg.type = GRPC_ARG_INTEGER;
+  client_arg.key = GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER;
+  client_arg.value.integer = encode_size;
+  client_args.num_args = 1;
+  client_args.args = &client_arg;
+
+  gpr_asprintf(&name, "test_size:e=%d:d=%d", encode_size, decode_size);
+  f = begin_test(config, name, encode_size != 4096 ? &client_args : NULL,
+                 decode_size != 4096 ? &server_args : NULL);
+  for (i = 0; i < 4 * GPR_ARRAY_SIZE(hobbits); i++) {
+    simple_request_body(f, i);
+  }
+  end_test(&f);
+  config.tear_down_data(&f);
+  gpr_free(name);
+}
+
+void grpc_end2end_tests(grpc_end2end_test_config config) {
+  static const int interesting_sizes[] = {4096, 0,     100,
+                                          1000, 32768, 4 * 1024 * 1024};
+  size_t i, j;
+
+  for (i = 0; i < GPR_ARRAY_SIZE(interesting_sizes); i++) {
+    for (j = 0; j < GPR_ARRAY_SIZE(interesting_sizes); j++) {
+      test_size(config, interesting_sizes[i], interesting_sizes[j]);
+    }
+  }
+}
diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c
index abcc1ba3584a765332d450125d0e776cb8ab5ecd..8fe9e7bcc5797571df3c4bf6323bda152f73f6dd 100644
--- a/test/core/end2end/tests/negative_deadline.c
+++ b/test/core/end2end/tests/negative_deadline.c
@@ -163,7 +163,8 @@ static void simple_request_body(grpc_end2end_test_fixture f, size_t num_ops) {
   cq_verifier_destroy(cqv);
 }
 
-static void test_invoke_simple_request(grpc_end2end_test_config config, size_t num_ops) {
+static void test_invoke_simple_request(grpc_end2end_test_config config,
+                                       size_t num_ops) {
   grpc_end2end_test_fixture f;
 
   f = begin_test(config, "test_invoke_simple_request", NULL, NULL);
diff --git a/test/core/network_benchmarks/low_level_ping_pong.c b/test/core/network_benchmarks/low_level_ping_pong.c
index 7a2d894481b16d5e375de883a33ff33c8ba2d360..dd1544c27b82307c6097ca37a14b1445ad253d0d 100644
--- a/test/core/network_benchmarks/low_level_ping_pong.c
+++ b/test/core/network_benchmarks/low_level_ping_pong.c
@@ -139,7 +139,7 @@ static int poll_read_bytes(int fd, char *buf, size_t read_size, int spin) {
       gpr_log(GPR_ERROR, "Read failed: %s", strerror(errno));
       return -1;
     }
-    bytes_read += (size_t) err2;
+    bytes_read += (size_t)err2;
   } while (bytes_read < read_size);
   return 0;
 }
@@ -174,11 +174,11 @@ static int epoll_read_bytes(struct thread_args *args, char *buf, int spin) {
     GPR_ASSERT(ev.data.fd == args->fds.read_fd);
     do {
       do {
-        err2 = read(args->fds.read_fd, buf + bytes_read,
-		    read_size - bytes_read);
+        err2 =
+            read(args->fds.read_fd, buf + bytes_read, read_size - bytes_read);
       } while (err2 < 0 && errno == EINTR);
       if (errno == EAGAIN) break;
-      bytes_read += (size_t) err2;
+      bytes_read += (size_t)err2;
       /* TODO(klempner): This should really be doing an extra call after we are
          done to ensure we see an EAGAIN */
     } while (bytes_read < read_size);
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 5c1e0f4b948750069be9c1df0539e776dd061eb1..4cfef7be7893659be065c7a79d4aa540914598ad 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -50,11 +50,24 @@
 
 #include <openssl/rsa.h>
 
+/* -- Mock channel credentials. -- */
+
+static grpc_channel_credentials *grpc_mock_channel_credentials_create(
+    const grpc_channel_credentials_vtable *vtable) {
+  grpc_channel_credentials *c = gpr_malloc(sizeof(*c));
+  memset(c, 0, sizeof(*c));
+  c->type = "mock";
+  c->vtable = vtable;
+  gpr_ref_init(&c->refcount, 1);
+  return c;
+}
+
+/* -- Constants. -- */
+
 static const char test_google_iam_authorization_token[] = "blahblahblhahb";
 static const char test_google_iam_authority_selector[] = "respectmyauthoritah";
 static const char test_oauth2_bearer_token[] =
     "Bearer blaaslkdjfaslkdfasdsfasf";
-static const char test_root_cert[] = "I am the root!";
 
 /* This JSON key was generated with the GCE console and revoked immediately.
    The identifiers have been changed as well.
@@ -113,6 +126,8 @@ static const char test_signed_jwt[] =
 static const char test_service_url[] = "https://foo.com/foo.v1";
 static const char other_test_service_url[] = "https://bar.com/bar.v1";
 
+/* -- Utils. -- */
+
 static char *test_json_key_str(void) {
   size_t result_len = strlen(test_json_key_str_part1) +
                       strlen(test_json_key_str_part2) +
@@ -141,6 +156,8 @@ static grpc_httpcli_response http_response(int status, const char *body) {
   return response;
 }
 
+/* -- Tests. -- */
+
 static void test_empty_md_store(void) {
   grpc_credentials_md_store *store = grpc_credentials_md_store_create(0);
   GPR_ASSERT(store->num_entries == 0);
@@ -219,7 +236,7 @@ static void test_oauth2_token_fetcher_creds_parsing_ok(void) {
   GPR_ASSERT(token_lifetime.tv_sec == 3599);
   GPR_ASSERT(token_lifetime.tv_nsec == 0);
   GPR_ASSERT(token_md->num_entries == 1);
-  GPR_ASSERT(gpr_slice_str_cmp(token_md->entries[0].key, "Authorization") == 0);
+  GPR_ASSERT(gpr_slice_str_cmp(token_md->entries[0].key, "authorization") == 0);
   GPR_ASSERT(gpr_slice_str_cmp(token_md->entries[0].value,
                                "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
              0);
@@ -319,7 +336,7 @@ static void check_google_iam_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
                                       grpc_credentials_md *md_elems,
                                       size_t num_md,
                                       grpc_credentials_status status) {
-  grpc_credentials *c = (grpc_credentials *)user_data;
+  grpc_call_credentials *c = (grpc_call_credentials *)user_data;
   expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
                         test_google_iam_authorization_token},
                        {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY,
@@ -327,19 +344,17 @@ static void check_google_iam_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
   GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
   GPR_ASSERT(num_md == 2);
   check_metadata(emd, md_elems, num_md);
-  grpc_credentials_unref(c);
+  grpc_call_credentials_unref(c);
 }
 
 static void test_google_iam_creds(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *creds = grpc_google_iam_credentials_create(
+  grpc_call_credentials *creds = grpc_google_iam_credentials_create(
       test_google_iam_authorization_token, test_google_iam_authority_selector,
       NULL);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(creds));
-  GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds));
-  grpc_credentials_get_request_metadata(&exec_ctx, creds, NULL,
-                                        test_service_url,
-                                        check_google_iam_metadata, creds);
+  grpc_call_credentials_get_request_metadata(&exec_ctx, creds, NULL,
+                                             test_service_url,
+                                             check_google_iam_metadata, creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -348,81 +363,58 @@ static void check_access_token_metadata(grpc_exec_ctx *exec_ctx,
                                         grpc_credentials_md *md_elems,
                                         size_t num_md,
                                         grpc_credentials_status status) {
-  grpc_credentials *c = (grpc_credentials *)user_data;
+  grpc_call_credentials *c = (grpc_call_credentials *)user_data;
   expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
   GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
   GPR_ASSERT(num_md == 1);
   check_metadata(emd, md_elems, num_md);
-  grpc_credentials_unref(c);
+  grpc_call_credentials_unref(c);
 }
 
 static void test_access_token_creds(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *creds = grpc_access_token_credentials_create("blah", NULL);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(creds));
-  GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds));
-  GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_OAUTH2) == 0);
-  grpc_credentials_get_request_metadata(&exec_ctx, creds, NULL,
-                                        test_service_url,
-                                        check_access_token_metadata, creds);
-  grpc_exec_ctx_finish(&exec_ctx);
-}
-
-static void check_ssl_oauth2_composite_metadata(
-    grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
-    size_t num_md, grpc_credentials_status status) {
-  grpc_credentials *c = (grpc_credentials *)user_data;
-  expected_md emd[] = {
-      {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token}};
-  GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
-  GPR_ASSERT(num_md == 1);
-  check_metadata(emd, md_elems, num_md);
-  grpc_credentials_unref(c);
-}
-
-static void test_ssl_oauth2_composite_creds(void) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *ssl_creds =
-      grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
-  const grpc_credentials_array *creds_array;
-  grpc_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
-      "Authorization", test_oauth2_bearer_token, 0);
-  grpc_credentials *composite_creds =
-      grpc_composite_credentials_create(ssl_creds, oauth2_creds, NULL);
-  grpc_credentials_unref(ssl_creds);
-  grpc_credentials_unref(oauth2_creds);
-  GPR_ASSERT(strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) ==
-             0);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(composite_creds));
-  GPR_ASSERT(!grpc_credentials_has_request_metadata_only(composite_creds));
-  creds_array = grpc_composite_credentials_get_credentials(composite_creds);
-  GPR_ASSERT(creds_array->num_creds == 2);
-  GPR_ASSERT(strcmp(creds_array->creds_array[0]->type,
-                    GRPC_CREDENTIALS_TYPE_SSL) == 0);
-  GPR_ASSERT(strcmp(creds_array->creds_array[1]->type,
-                    GRPC_CREDENTIALS_TYPE_OAUTH2) == 0);
-  grpc_credentials_get_request_metadata(
-      &exec_ctx, composite_creds, NULL, test_service_url,
-      check_ssl_oauth2_composite_metadata, composite_creds);
+  grpc_call_credentials *creds =
+      grpc_access_token_credentials_create("blah", NULL);
+  GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
+  grpc_call_credentials_get_request_metadata(
+      &exec_ctx, creds, NULL, test_service_url, check_access_token_metadata,
+      creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
-void test_ssl_fake_transport_security_composite_creds_failure(void) {
-  grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL);
-  grpc_credentials *fake_transport_security_creds =
-      grpc_fake_transport_security_credentials_create();
-
-  /* 2 connector credentials: should not work. */
-  GPR_ASSERT(grpc_composite_credentials_create(
-                 ssl_creds, fake_transport_security_creds, NULL) == NULL);
-  grpc_credentials_unref(ssl_creds);
-  grpc_credentials_unref(fake_transport_security_creds);
-}
-
-static void check_ssl_oauth2_google_iam_composite_metadata(
+static grpc_security_status check_channel_oauth2_create_security_connector(
+    grpc_channel_credentials *c, grpc_call_credentials *call_creds,
+    const char *target, const grpc_channel_args *args,
+    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+  GPR_ASSERT(strcmp(c->type, "mock") == 0);
+  GPR_ASSERT(call_creds != NULL);
+  GPR_ASSERT(strcmp(call_creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
+  return GRPC_SECURITY_OK;
+}
+
+static void test_channel_oauth2_composite_creds(void) {
+  grpc_channel_args *new_args;
+  grpc_channel_credentials_vtable vtable = {
+      NULL, check_channel_oauth2_create_security_connector};
+  grpc_channel_credentials *channel_creds =
+      grpc_mock_channel_credentials_create(&vtable);
+  grpc_call_credentials *oauth2_creds =
+      grpc_access_token_credentials_create("blah", NULL);
+  grpc_channel_credentials *channel_oauth2_creds =
+      grpc_composite_channel_credentials_create(channel_creds, oauth2_creds,
+                                                NULL);
+  grpc_channel_credentials_release(channel_creds);
+  grpc_call_credentials_release(oauth2_creds);
+  GPR_ASSERT(grpc_channel_credentials_create_security_connector(
+                 channel_oauth2_creds, NULL, NULL, NULL, &new_args) ==
+             GRPC_SECURITY_OK);
+  grpc_channel_credentials_release(channel_oauth2_creds);
+}
+
+static void check_oauth2_google_iam_composite_metadata(
     grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
     size_t num_md, grpc_credentials_status status) {
-  grpc_credentials *c = (grpc_credentials *)user_data;
+  grpc_call_credentials *c = (grpc_call_credentials *)user_data;
   expected_md emd[] = {
       {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token},
       {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
@@ -432,51 +424,90 @@ static void check_ssl_oauth2_google_iam_composite_metadata(
   GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
   GPR_ASSERT(num_md == 3);
   check_metadata(emd, md_elems, num_md);
-  grpc_credentials_unref(c);
+  grpc_call_credentials_unref(c);
 }
 
-static void test_ssl_oauth2_google_iam_composite_creds(void) {
+static void test_oauth2_google_iam_composite_creds(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *ssl_creds =
-      grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
-  const grpc_credentials_array *creds_array;
-  grpc_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
-      "Authorization", test_oauth2_bearer_token, 0);
-  grpc_credentials *aux_creds =
-      grpc_composite_credentials_create(ssl_creds, oauth2_creds, NULL);
-  grpc_credentials *google_iam_creds = grpc_google_iam_credentials_create(
+  const grpc_call_credentials_array *creds_array;
+  grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
+      "authorization", test_oauth2_bearer_token, 0);
+  grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create(
       test_google_iam_authorization_token, test_google_iam_authority_selector,
       NULL);
-  grpc_credentials *composite_creds =
-      grpc_composite_credentials_create(aux_creds, google_iam_creds, NULL);
-  grpc_credentials_unref(ssl_creds);
-  grpc_credentials_unref(oauth2_creds);
-  grpc_credentials_unref(aux_creds);
-  grpc_credentials_unref(google_iam_creds);
-  GPR_ASSERT(strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) ==
-             0);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(composite_creds));
-  GPR_ASSERT(!grpc_credentials_has_request_metadata_only(composite_creds));
-  creds_array = grpc_composite_credentials_get_credentials(composite_creds);
-  GPR_ASSERT(creds_array->num_creds == 3);
+  grpc_call_credentials *composite_creds =
+      grpc_composite_call_credentials_create(oauth2_creds, google_iam_creds,
+                                             NULL);
+  grpc_call_credentials_unref(oauth2_creds);
+  grpc_call_credentials_unref(google_iam_creds);
+  GPR_ASSERT(
+      strcmp(composite_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
+  creds_array =
+      grpc_composite_call_credentials_get_credentials(composite_creds);
+  GPR_ASSERT(creds_array->num_creds == 2);
   GPR_ASSERT(strcmp(creds_array->creds_array[0]->type,
-                    GRPC_CREDENTIALS_TYPE_SSL) == 0);
+                    GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
   GPR_ASSERT(strcmp(creds_array->creds_array[1]->type,
-                    GRPC_CREDENTIALS_TYPE_OAUTH2) == 0);
-  GPR_ASSERT(strcmp(creds_array->creds_array[2]->type,
-                    GRPC_CREDENTIALS_TYPE_IAM) == 0);
-  grpc_credentials_get_request_metadata(
+                    GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0);
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, composite_creds, NULL, test_service_url,
-      check_ssl_oauth2_google_iam_composite_metadata, composite_creds);
+      check_oauth2_google_iam_composite_metadata, composite_creds);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
+static grpc_security_status
+check_channel_oauth2_google_iam_create_security_connector(
+    grpc_channel_credentials *c, grpc_call_credentials *call_creds,
+    const char *target, const grpc_channel_args *args,
+    grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
+  const grpc_call_credentials_array *creds_array;
+  GPR_ASSERT(strcmp(c->type, "mock") == 0);
+  GPR_ASSERT(call_creds != NULL);
+  GPR_ASSERT(strcmp(call_creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) ==
+             0);
+  creds_array = grpc_composite_call_credentials_get_credentials(call_creds);
+  GPR_ASSERT(strcmp(creds_array->creds_array[0]->type,
+                    GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
+  GPR_ASSERT(strcmp(creds_array->creds_array[1]->type,
+                    GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0);
+  return GRPC_SECURITY_OK;
+}
+
+static void test_channel_oauth2_google_iam_composite_creds(void) {
+  grpc_channel_args *new_args;
+  grpc_channel_credentials_vtable vtable = {
+      NULL, check_channel_oauth2_google_iam_create_security_connector};
+  grpc_channel_credentials *channel_creds =
+      grpc_mock_channel_credentials_create(&vtable);
+  grpc_call_credentials *oauth2_creds =
+      grpc_access_token_credentials_create("blah", NULL);
+  grpc_channel_credentials *channel_oauth2_creds =
+      grpc_composite_channel_credentials_create(channel_creds, oauth2_creds,
+                                                NULL);
+  grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create(
+      test_google_iam_authorization_token, test_google_iam_authority_selector,
+      NULL);
+  grpc_channel_credentials *channel_oauth2_iam_creds =
+      grpc_composite_channel_credentials_create(channel_oauth2_creds,
+                                                google_iam_creds, NULL);
+  grpc_channel_credentials_release(channel_creds);
+  grpc_call_credentials_release(oauth2_creds);
+  grpc_channel_credentials_release(channel_oauth2_creds);
+  grpc_call_credentials_release(google_iam_creds);
+
+  GPR_ASSERT(grpc_channel_credentials_create_security_connector(
+                 channel_oauth2_iam_creds, NULL, NULL, NULL, &new_args) ==
+             GRPC_SECURITY_OK);
+
+  grpc_channel_credentials_release(channel_oauth2_iam_creds);
+}
+
 static void on_oauth2_creds_get_metadata_success(
     grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems,
     size_t num_md, grpc_credentials_status status) {
   GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
   GPR_ASSERT(num_md == 1);
-  GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "Authorization") == 0);
+  GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "authorization") == 0);
   GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].value,
                                "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") ==
              0);
@@ -545,15 +576,13 @@ static int httpcli_get_should_not_be_called(
 
 static void test_compute_engine_creds_success(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *compute_engine_creds =
+  grpc_call_credentials *compute_engine_creds =
       grpc_google_compute_engine_credentials_create(NULL);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds));
-  GPR_ASSERT(grpc_credentials_has_request_metadata_only(compute_engine_creds));
 
   /* First request: http get should be called. */
   grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
                             httpcli_post_should_not_be_called);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, compute_engine_creds, NULL, test_service_url,
       on_oauth2_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
@@ -561,27 +590,25 @@ static void test_compute_engine_creds_success(void) {
   /* Second request: the cached token should be served directly. */
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, compute_engine_creds, NULL, test_service_url,
       on_oauth2_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_finish(&exec_ctx);
 
-  grpc_credentials_unref(compute_engine_creds);
+  grpc_call_credentials_unref(compute_engine_creds);
   grpc_httpcli_set_override(NULL, NULL);
 }
 
 static void test_compute_engine_creds_failure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *compute_engine_creds =
+  grpc_call_credentials *compute_engine_creds =
       grpc_google_compute_engine_credentials_create(NULL);
   grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
                             httpcli_post_should_not_be_called);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds));
-  GPR_ASSERT(grpc_credentials_has_request_metadata_only(compute_engine_creds));
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, compute_engine_creds, NULL, test_service_url,
       on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
-  grpc_credentials_unref(compute_engine_creds);
+  grpc_call_credentials_unref(compute_engine_creds);
   grpc_httpcli_set_override(NULL, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -631,16 +658,14 @@ static int refresh_token_httpcli_post_failure(
 
 static void test_refresh_token_creds_success(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *refresh_token_creds =
+  grpc_call_credentials *refresh_token_creds =
       grpc_google_refresh_token_credentials_create(test_refresh_token_str,
                                                    NULL);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(refresh_token_creds));
-  GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds));
 
   /* First request: http get should be called. */
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             refresh_token_httpcli_post_success);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, refresh_token_creds, NULL, test_service_url,
       on_oauth2_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
@@ -648,29 +673,27 @@ static void test_refresh_token_creds_success(void) {
   /* Second request: the cached token should be served directly. */
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             httpcli_post_should_not_be_called);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, refresh_token_creds, NULL, test_service_url,
       on_oauth2_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
 
-  grpc_credentials_unref(refresh_token_creds);
+  grpc_call_credentials_unref(refresh_token_creds);
   grpc_httpcli_set_override(NULL, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_refresh_token_creds_failure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *refresh_token_creds =
+  grpc_call_credentials *refresh_token_creds =
       grpc_google_refresh_token_credentials_create(test_refresh_token_str,
                                                    NULL);
   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
                             refresh_token_httpcli_post_failure);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(refresh_token_creds));
-  GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds));
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, refresh_token_creds, NULL, test_service_url,
       on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
-  grpc_credentials_unref(refresh_token_creds);
+  grpc_call_credentials_unref(refresh_token_creds);
   grpc_httpcli_set_override(NULL, NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -730,7 +753,7 @@ static void on_jwt_creds_get_metadata_success(grpc_exec_ctx *exec_ctx,
   gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt);
   GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
   GPR_ASSERT(num_md == 1);
-  GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "Authorization") == 0);
+  GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "authorization") == 0);
   GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].value, expected_md_value) == 0);
   GPR_ASSERT(user_data != NULL);
   GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
@@ -751,15 +774,13 @@ static void on_jwt_creds_get_metadata_failure(grpc_exec_ctx *exec_ctx,
 static void test_jwt_creds_success(void) {
   char *json_key_string = test_json_key_str();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *jwt_creds =
+  grpc_call_credentials *jwt_creds =
       grpc_service_account_jwt_access_credentials_create(
           json_key_string, grpc_max_auth_token_lifetime, NULL);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(jwt_creds));
-  GPR_ASSERT(grpc_credentials_has_request_metadata_only(jwt_creds));
 
   /* First request: jwt_encode_and_sign should be called. */
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, jwt_creds, NULL, test_service_url,
       on_jwt_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
@@ -767,7 +788,7 @@ static void test_jwt_creds_success(void) {
   /* Second request: the cached token should be served directly. */
   grpc_jwt_encode_and_sign_set_override(
       encode_and_sign_jwt_should_not_be_called);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, jwt_creds, NULL, test_service_url,
       on_jwt_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
@@ -775,32 +796,30 @@ static void test_jwt_creds_success(void) {
   /* Third request: Different service url so jwt_encode_and_sign should be
      called again (no caching). */
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, jwt_creds, NULL, other_test_service_url,
       on_jwt_creds_get_metadata_success, (void *)test_user_data);
   grpc_exec_ctx_flush(&exec_ctx);
 
   gpr_free(json_key_string);
-  grpc_credentials_unref(jwt_creds);
+  grpc_call_credentials_unref(jwt_creds);
   grpc_jwt_encode_and_sign_set_override(NULL);
 }
 
 static void test_jwt_creds_signing_failure(void) {
   char *json_key_string = test_json_key_str();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_credentials *jwt_creds =
+  grpc_call_credentials *jwt_creds =
       grpc_service_account_jwt_access_credentials_create(
           json_key_string, grpc_max_auth_token_lifetime, NULL);
-  GPR_ASSERT(grpc_credentials_has_request_metadata(jwt_creds));
-  GPR_ASSERT(grpc_credentials_has_request_metadata_only(jwt_creds));
 
   grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, jwt_creds, NULL, test_service_url,
       on_jwt_creds_get_metadata_failure, (void *)test_user_data);
 
   gpr_free(json_key_string);
-  grpc_credentials_unref(jwt_creds);
+  grpc_call_credentials_unref(jwt_creds);
   grpc_jwt_encode_and_sign_set_override(NULL);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -818,52 +837,39 @@ static void set_google_default_creds_env_var_with_file_contents(
   gpr_free(creds_file_name);
 }
 
-static grpc_credentials *composite_inner_creds(grpc_credentials *creds,
-                                               const char *inner_creds_type) {
-  size_t i;
-  grpc_composite_credentials *composite;
-  GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0);
-  composite = (grpc_composite_credentials *)creds;
-  for (i = 0; i < composite->inner.num_creds; i++) {
-    grpc_credentials *c = composite->inner.creds_array[i];
-    if (strcmp(c->type, inner_creds_type) == 0) return c;
-  }
-  GPR_ASSERT(0); /* Not found. */
-}
-
 static void test_google_default_creds_auth_key(void) {
   grpc_service_account_jwt_access_credentials *jwt;
-  grpc_credentials *creds;
+  grpc_composite_channel_credentials *creds;
   char *json_key = test_json_key_str();
   grpc_flush_cached_google_default_credentials();
   set_google_default_creds_env_var_with_file_contents(
       "json_key_google_default_creds", json_key);
   gpr_free(json_key);
-  creds = grpc_google_default_credentials_create();
+  creds = (grpc_composite_channel_credentials *)
+      grpc_google_default_credentials_create();
   GPR_ASSERT(creds != NULL);
-  jwt = (grpc_service_account_jwt_access_credentials *)composite_inner_creds(
-      creds, GRPC_CREDENTIALS_TYPE_JWT);
+  jwt = (grpc_service_account_jwt_access_credentials *)creds->call_creds;
   GPR_ASSERT(
       strcmp(jwt->key.client_id,
              "777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent.com") ==
       0);
-  grpc_credentials_unref(creds);
+  grpc_channel_credentials_unref(&creds->base);
   gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
 }
 
 static void test_google_default_creds_access_token(void) {
   grpc_google_refresh_token_credentials *refresh;
-  grpc_credentials *creds;
+  grpc_composite_channel_credentials *creds;
   grpc_flush_cached_google_default_credentials();
   set_google_default_creds_env_var_with_file_contents(
       "refresh_token_google_default_creds", test_refresh_token_str);
-  creds = grpc_google_default_credentials_create();
+  creds = (grpc_composite_channel_credentials *)
+      grpc_google_default_credentials_create();
   GPR_ASSERT(creds != NULL);
-  refresh = (grpc_google_refresh_token_credentials *)composite_inner_creds(
-      creds, GRPC_CREDENTIALS_TYPE_OAUTH2);
+  refresh = (grpc_google_refresh_token_credentials *)creds->call_creds;
   GPR_ASSERT(strcmp(refresh->refresh_token.client_id,
                     "32555999999.apps.googleusercontent.com") == 0);
-  grpc_credentials_unref(creds);
+  grpc_channel_credentials_unref(&creds->base);
   gpr_setenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR, ""); /* Reset. */
 }
 
@@ -935,7 +941,7 @@ static void plugin_destroy(void *state) {
 }
 
 static void test_metadata_plugin_success(void) {
-  grpc_credentials *creds;
+  grpc_call_credentials *creds;
   plugin_state state = PLUGIN_INITIAL_STATE;
   grpc_metadata_credentials_plugin plugin;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -946,17 +952,17 @@ static void test_metadata_plugin_success(void) {
 
   creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
   GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, creds, NULL, test_service_url,
       on_plugin_metadata_received_success, NULL);
   GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
-  grpc_credentials_release(creds);
+  grpc_call_credentials_release(creds);
   GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void test_metadata_plugin_failure(void) {
-  grpc_credentials *creds;
+  grpc_call_credentials *creds;
   plugin_state state = PLUGIN_INITIAL_STATE;
   grpc_metadata_credentials_plugin plugin;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -967,11 +973,11 @@ static void test_metadata_plugin_failure(void) {
 
   creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
   GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
-  grpc_credentials_get_request_metadata(
+  grpc_call_credentials_get_request_metadata(
       &exec_ctx, creds, NULL, test_service_url,
       on_plugin_metadata_received_failure, NULL);
   GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
-  grpc_credentials_release(creds);
+  grpc_call_credentials_release(creds);
   GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
   grpc_exec_ctx_finish(&exec_ctx);
 }
@@ -993,8 +999,9 @@ int main(int argc, char **argv) {
   test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime();
   test_google_iam_creds();
   test_access_token_creds();
-  test_ssl_oauth2_composite_creds();
-  test_ssl_oauth2_google_iam_composite_creds();
+  test_channel_oauth2_composite_creds();
+  test_oauth2_google_iam_composite_creds();
+  test_channel_oauth2_google_iam_composite_creds();
   test_compute_engine_creds_success();
   test_compute_engine_creds_failure();
   test_refresh_token_creds_success();
diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c
index 764d8da9b607ca2fa5cf4469602e37cf1b6ac07f..ee1178cbddf1d74f75b28e4407c02f27fc83042b 100644
--- a/test/core/security/fetch_oauth2.c
+++ b/test/core/security/fetch_oauth2.c
@@ -46,7 +46,7 @@
 #include "src/core/support/file.h"
 #include "test/core/security/oauth2_utils.h"
 
-static grpc_credentials *create_refresh_token_creds(
+static grpc_call_credentials *create_refresh_token_creds(
     const char *json_refresh_token_file_path) {
   int success;
   gpr_slice refresh_token =
@@ -60,7 +60,7 @@ static grpc_credentials *create_refresh_token_creds(
 }
 
 int main(int argc, char **argv) {
-  grpc_credentials *creds = NULL;
+  grpc_call_credentials *creds = NULL;
   char *json_key_file_path = NULL;
   char *json_refresh_token_file_path = NULL;
   char *token = NULL;
@@ -115,7 +115,7 @@ int main(int argc, char **argv) {
     printf("Got token: %s.\n", token);
     gpr_free(token);
   }
-  grpc_credentials_release(creds);
+  grpc_call_credentials_release(creds);
   gpr_cmdline_destroy(cl);
   grpc_shutdown();
   return 0;
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index f99d17059256f874b9ada6d90758f4e63435461c..fcfe8a637770a28617fc1762c83bf9620e4b3f4c 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -75,7 +75,8 @@ static void on_oauth2_response(grpc_exec_ctx *exec_ctx, void *user_data,
 
 static void do_nothing(grpc_exec_ctx *exec_ctx, void *unused, int success) {}
 
-char *grpc_test_fetch_oauth2_token_with_credentials(grpc_credentials *creds) {
+char *grpc_test_fetch_oauth2_token_with_credentials(
+    grpc_call_credentials *creds) {
   oauth2_request request;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_closure do_nothing_closure;
@@ -84,8 +85,8 @@ char *grpc_test_fetch_oauth2_token_with_credentials(grpc_credentials *creds) {
 
   grpc_closure_init(&do_nothing_closure, do_nothing, NULL);
 
-  grpc_credentials_get_request_metadata(&exec_ctx, creds, &request.pollset, "",
-                                        on_oauth2_response, &request);
+  grpc_call_credentials_get_request_metadata(&exec_ctx, creds, &request.pollset,
+                                             "", on_oauth2_response, &request);
 
   grpc_exec_ctx_finish(&exec_ctx);
 
diff --git a/test/core/security/oauth2_utils.h b/test/core/security/oauth2_utils.h
index 8082351b8a0cb20ee52ee3b18cebde9c0d0380c3..b35fe7987fc1ef92e9a23a79c56eb4cd15cafdb1 100644
--- a/test/core/security/oauth2_utils.h
+++ b/test/core/security/oauth2_utils.h
@@ -42,7 +42,8 @@ extern "C" {
 
 /* Fetch oauth2 access token with a credentials object. Does not take ownership.
    Returns NULL on a failure. The caller should call gpr_free on the token. */
-char *grpc_test_fetch_oauth2_token_with_credentials(grpc_credentials *creds);
+char *grpc_test_fetch_oauth2_token_with_credentials(
+    grpc_call_credentials *creds);
 
 #ifdef __cplusplus
 }
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index f207e0579473e919014bd59d3bb4598339981249..eb6372471537ca52159fce802444c80780d0291b 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -72,7 +72,7 @@ int main(int argc, char **argv) {
   int result = 0;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   synchronizer sync;
-  grpc_credentials *creds = NULL;
+  grpc_channel_credentials *creds = NULL;
   char *service_url = "https://test.foo.google.com/Foo";
   gpr_cmdline *cl = gpr_cmdline_create("print_google_default_creds_token");
   gpr_cmdline_add_string(cl, "service_url",
@@ -91,9 +91,9 @@ int main(int argc, char **argv) {
   grpc_pollset_init(&sync.pollset);
   sync.is_done = 0;
 
-  grpc_credentials_get_request_metadata(&exec_ctx, creds, &sync.pollset,
-                                        service_url, on_metadata_response,
-                                        &sync);
+  grpc_call_credentials_get_request_metadata(
+      &exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds,
+      &sync.pollset, service_url, on_metadata_response, &sync);
 
   gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
   while (!sync.is_done) {
@@ -107,7 +107,7 @@ int main(int argc, char **argv) {
   }
   gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
 
-  grpc_credentials_release(creds);
+  grpc_channel_credentials_release(creds);
 
 end:
   gpr_cmdline_destroy(cl);
diff --git a/test/core/surface/byte_buffer_reader_test.c b/test/core/surface/byte_buffer_reader_test.c
index 7f9cd6b62b02cb1302618202f1d01a963e9c6b66..6b41698717b9ce6e146354392bfaf88b6ec82a0c 100644
--- a/test/core/surface/byte_buffer_reader_test.c
+++ b/test/core/surface/byte_buffer_reader_test.c
@@ -185,8 +185,8 @@ static void test_byte_buffer_from_reader(void) {
 }
 
 static void test_readall(void) {
-  char* lotsa_as[512];
-  char* lotsa_bs[1024];
+  char *lotsa_as[512];
+  char *lotsa_bs[1024];
   gpr_slice slices[2];
   grpc_byte_buffer *buffer;
   grpc_byte_buffer_reader reader;
diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c
index 3a313375a499ee1e882219854f088a776c44ae39..c6b35fba796df5e0e56f3228b7a0e85cb7d5d8e5 100644
--- a/test/core/transport/chttp2/hpack_parser_test.c
+++ b/test/core/transport/chttp2/hpack_parser_test.c
@@ -151,7 +151,8 @@ static void test_vectors(grpc_slice_split_mode mode) {
   grpc_chttp2_hpack_parser_destroy(&parser);
 
   grpc_chttp2_hpack_parser_init(&parser, mdctx);
-  parser.table.max_bytes = 256;
+  grpc_chttp2_hptbl_set_max_bytes(&parser.table, 256);
+  grpc_chttp2_hptbl_set_current_table_size(&parser.table, 256);
   /* D.5.1 */
   test_vector(&parser, mode,
               "4803 3330 3258 0770 7269 7661 7465 611d"
@@ -184,7 +185,8 @@ static void test_vectors(grpc_slice_split_mode mode) {
   grpc_chttp2_hpack_parser_destroy(&parser);
 
   grpc_chttp2_hpack_parser_init(&parser, mdctx);
-  parser.table.max_bytes = 256;
+  grpc_chttp2_hptbl_set_max_bytes(&parser.table, 256);
+  grpc_chttp2_hptbl_set_current_table_size(&parser.table, 256);
   /* D.6.1 */
   test_vector(&parser, mode,
               "4882 6402 5885 aec3 771a 4b61 96d0 7abe"
diff --git a/test/core/transport/chttp2/hpack_table_test.c b/test/core/transport/chttp2/hpack_table_test.c
index aa3e273a6c915f658e10239ce076a5387020f114..5eb52d6d9a952a9a25606f49b92ba25425629635 100644
--- a/test/core/transport/chttp2/hpack_table_test.c
+++ b/test/core/transport/chttp2/hpack_table_test.c
@@ -143,9 +143,12 @@ static void test_many_additions(void) {
   grpc_chttp2_hptbl_init(&tbl, mdctx);
 
   for (i = 0; i < 1000000; i++) {
+    grpc_mdelem *elem;
     gpr_asprintf(&key, "K:%d", i);
     gpr_asprintf(&value, "VALUE:%d", i);
-    grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, key, value));
+    elem = grpc_mdelem_from_strings(mdctx, key, value);
+    GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+    GRPC_MDELEM_UNREF(elem);
     assert_index(&tbl, 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value);
     gpr_free(key);
     gpr_free(value);
@@ -173,18 +176,25 @@ static grpc_chttp2_hptbl_find_result find_simple(grpc_chttp2_hptbl *tbl,
 
 static void test_find(void) {
   grpc_chttp2_hptbl tbl;
-  int i;
+  gpr_uint32 i;
   char buffer[32];
   grpc_mdctx *mdctx;
+  grpc_mdelem *elem;
   grpc_chttp2_hptbl_find_result r;
 
   LOG_TEST("test_find");
 
   mdctx = grpc_mdctx_create();
   grpc_chttp2_hptbl_init(&tbl, mdctx);
-  grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, "abc", "xyz"));
-  grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, "abc", "123"));
-  grpc_chttp2_hptbl_add(&tbl, grpc_mdelem_from_strings(mdctx, "x", "1"));
+  elem = grpc_mdelem_from_strings(mdctx, "abc", "xyz");
+  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+  GRPC_MDELEM_UNREF(elem);
+  elem = grpc_mdelem_from_strings(mdctx, "abc", "123");
+  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+  GRPC_MDELEM_UNREF(elem);
+  elem = grpc_mdelem_from_strings(mdctx, "x", "1");
+  GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+  GRPC_MDELEM_UNREF(elem);
 
   r = find_simple(&tbl, "abc", "123");
   GPR_ASSERT(r.index == 2 + GRPC_CHTTP2_LAST_STATIC_ENTRY);
@@ -233,8 +243,9 @@ static void test_find(void) {
   /* overflow the string buffer, check find still works */
   for (i = 0; i < 10000; i++) {
     gpr_ltoa(i, buffer);
-    grpc_chttp2_hptbl_add(&tbl,
-                          grpc_mdelem_from_strings(mdctx, "test", buffer));
+    elem = grpc_mdelem_from_strings(mdctx, "test", buffer);
+    GPR_ASSERT(grpc_chttp2_hptbl_add(&tbl, elem));
+    GRPC_MDELEM_UNREF(elem);
   }
 
   r = find_simple(&tbl, "abc", "123");
@@ -250,7 +261,7 @@ static void test_find(void) {
   GPR_ASSERT(r.has_value == 1);
 
   for (i = 0; i < tbl.num_ents; i++) {
-    int expect = 9999 - i;
+    gpr_uint32 expect = 9999 - i;
     gpr_ltoa(expect, buffer);
 
     r = find_simple(&tbl, "test", buffer);
diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c
index ee481ef6749b626e56d7dbc941f5769851a92350..c064fb32c6e71379cb8876b4aba49e3d07a38ddc 100644
--- a/test/core/util/reconnect_server.c
+++ b/test/core/util/reconnect_server.c
@@ -113,6 +113,7 @@ void reconnect_server_init(reconnect_server *server) {
 
 void reconnect_server_start(reconnect_server *server, int port) {
   struct sockaddr_in addr;
+  grpc_tcp_listener *listener;
   int port_added;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
@@ -121,8 +122,9 @@ void reconnect_server_start(reconnect_server *server, int port) {
   memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
 
   server->tcp_server = grpc_tcp_server_create();
-  port_added =
+  listener = 
       grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr));
+  port_added = grpc_tcp_listener_get_port(listener);
   GPR_ASSERT(port_added == port);
 
   grpc_tcp_server_start(&exec_ctx, server->tcp_server, server->pollsets, 1,
diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc
index 743ad065d13a797cce016e5202e8104150f2b4c5..418a54439a9585853b1036d66bc43d46c2839ffd 100644
--- a/test/cpp/client/credentials_test.cc
+++ b/test/cpp/client/credentials_test.cc
@@ -46,8 +46,8 @@ class CredentialsTest : public ::testing::Test {
 };
 
 TEST_F(CredentialsTest, InvalidGoogleRefreshToken) {
-  std::shared_ptr<Credentials> bad1 = GoogleRefreshTokenCredentials("");
-  EXPECT_EQ(static_cast<Credentials*>(nullptr), bad1.get());
+  std::shared_ptr<CallCredentials> bad1 = GoogleRefreshTokenCredentials("");
+  EXPECT_EQ(static_cast<CallCredentials*>(nullptr), bad1.get());
 }
 
 }  // namespace testing
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index cfb6c21edc9e6ea7098b29a93a63cf2b15650877..74290c36d234c03be1d28067d69524431a93aa81 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -199,7 +199,7 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<bool> {
 
   void ResetStub() {
     std::shared_ptr<Channel> channel =
-        CreateChannel(server_address_.str(), InsecureCredentials());
+        CreateChannel(server_address_.str(), InsecureChannelCredentials());
     stub_ = grpc::cpp::test::util::TestService::NewStub(channel);
   }
 
@@ -749,7 +749,7 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) {
 
 TEST_P(AsyncEnd2endTest, UnimplementedRpc) {
   std::shared_ptr<Channel> channel =
-      CreateChannel(server_address_.str(), InsecureCredentials());
+      CreateChannel(server_address_.str(), InsecureChannelCredentials());
   std::unique_ptr<grpc::cpp::test::util::UnimplementedService::Stub> stub;
   stub = grpc::cpp::test::util::UnimplementedService::NewStub(channel);
   EchoRequest send_request;
diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc
index 058e6961666ccf9fa3be29dbe80270c654879a1d..116785bbf2c7259e1a2cca39e089da6bdb7ee803 100644
--- a/test/cpp/end2end/client_crash_test.cc
+++ b/test/cpp/end2end/client_crash_test.cc
@@ -74,7 +74,7 @@ class CrashTest : public ::testing::Test {
     }));
     GPR_ASSERT(server_);
     return grpc::cpp::test::util::TestService::NewStub(
-        CreateChannel(addr, InsecureCredentials()));
+        CreateChannel(addr, InsecureChannelCredentials()));
   }
 
   void KillServer() { server_.reset(); }
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index c5c71850265cb38f8feb684912a9c86b527108d8..6da933302c0128728986c4889dd644b91e8eb9a9 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -146,13 +146,13 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor {
 
   TestAuthMetadataProcessor(bool is_blocking) : is_blocking_(is_blocking) {}
 
-  std::shared_ptr<Credentials> GetCompatibleClientCreds() {
+  std::shared_ptr<CallCredentials> GetCompatibleClientCreds() {
     return MetadataCredentialsFromPlugin(
         std::unique_ptr<MetadataCredentialsPlugin>(
             new TestMetadataCredentialsPlugin(kGoodGuy, is_blocking_, true)));
   }
 
-  std::shared_ptr<Credentials> GetIncompatibleClientCreds() {
+  std::shared_ptr<CallCredentials> GetIncompatibleClientCreds() {
     return MetadataCredentialsFromPlugin(
         std::unique_ptr<MetadataCredentialsPlugin>(
             new TestMetadataCredentialsPlugin("Mr Hyde", is_blocking_, true)));
@@ -407,7 +407,7 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> {
     }
     EXPECT_TRUE(is_server_started_);
     ChannelArguments args;
-    auto channel_creds = InsecureCredentials();
+    auto channel_creds = InsecureChannelCredentials();
     if (GetParam().use_tls) {
       SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
       args.SetSslTargetNameOverride("foo.test.google.fr");
@@ -429,7 +429,7 @@ class End2endTest : public ::testing::TestWithParam<TestScenario> {
       builder.RegisterService(proxy_service_.get());
       proxy_server_ = builder.BuildAndStart();
 
-      channel_ = CreateChannel(proxyaddr.str(), InsecureCredentials());
+      channel_ = CreateChannel(proxyaddr.str(), InsecureChannelCredentials());
     }
 
     stub_ = grpc::cpp::test::util::TestService::NewStub(channel_);
@@ -575,6 +575,18 @@ void CancelRpc(ClientContext* context, int delay_us, TestServiceImpl* service) {
   context->TryCancel();
 }
 
+TEST_P(End2endTest, CancelRpcBeforeStart) {
+  ResetStub();
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  request.set_message("hello");
+  context.TryCancel();
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_EQ("", response.message());
+  EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code());
+}
+
 // Client cancels request stream after sending two messages
 TEST_P(End2endTest, ClientCancelsRequestStream) {
   ResetStub();
@@ -751,7 +763,8 @@ TEST_P(End2endTest, ChannelStateTimeout) {
   std::ostringstream server_address;
   server_address << "127.0.0.1:" << port;
   // Channel to non-existing server
-  auto channel = CreateChannel(server_address.str(), InsecureCredentials());
+  auto channel =
+      CreateChannel(server_address.str(), InsecureChannelCredentials());
   // Start IDLE
   EXPECT_EQ(GRPC_CHANNEL_IDLE, channel->GetState(true));
 
@@ -971,33 +984,6 @@ TEST_P(SecureEnd2endTest, SimpleRpcWithHost) {
   EXPECT_TRUE(s.ok());
 }
 
-// rpc and stream should fail on bad credentials.
-TEST_P(SecureEnd2endTest, BadCredentials) {
-  std::shared_ptr<Credentials> bad_creds = GoogleRefreshTokenCredentials("");
-  EXPECT_EQ(static_cast<Credentials*>(nullptr), bad_creds.get());
-  std::shared_ptr<Channel> channel =
-      CreateChannel(server_address_.str(), bad_creds);
-  std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub(
-      grpc::cpp::test::util::TestService::NewStub(channel));
-  EchoRequest request;
-  EchoResponse response;
-  ClientContext context;
-  request.set_message("Hello");
-
-  Status s = stub->Echo(&context, request, &response);
-  EXPECT_EQ("", response.message());
-  EXPECT_FALSE(s.ok());
-  EXPECT_EQ(StatusCode::INVALID_ARGUMENT, s.error_code());
-  EXPECT_EQ("Invalid credentials.", s.error_message());
-
-  ClientContext context2;
-  auto stream = stub->BidiStream(&context2);
-  s = stream->Finish();
-  EXPECT_FALSE(s.ok());
-  EXPECT_EQ(StatusCode::INVALID_ARGUMENT, s.error_code());
-  EXPECT_EQ("Invalid credentials.", s.error_message());
-}
-
 bool MetadataContains(
     const std::multimap<grpc::string_ref, grpc::string_ref>& metadata,
     const grpc::string& key, const grpc::string& value) {
@@ -1055,7 +1041,7 @@ TEST_P(SecureEnd2endTest, SetPerCallCredentials) {
   EchoRequest request;
   EchoResponse response;
   ClientContext context;
-  std::shared_ptr<Credentials> creds =
+  std::shared_ptr<CallCredentials> creds =
       GoogleIAMCredentials("fake_token", "fake_selector");
   context.set_credentials(creds);
   request.set_message("Hello");
@@ -1072,30 +1058,15 @@ TEST_P(SecureEnd2endTest, SetPerCallCredentials) {
                                "fake_selector"));
 }
 
-TEST_P(SecureEnd2endTest, InsecurePerCallCredentials) {
-  ResetStub();
-  EchoRequest request;
-  EchoResponse response;
-  ClientContext context;
-  std::shared_ptr<Credentials> creds = InsecureCredentials();
-  context.set_credentials(creds);
-  request.set_message("Hello");
-  request.mutable_param()->set_echo_metadata(true);
-
-  Status s = stub_->Echo(&context, request, &response);
-  EXPECT_EQ(StatusCode::CANCELLED, s.error_code());
-  EXPECT_EQ("Failed to set credentials to rpc.", s.error_message());
-}
-
 TEST_P(SecureEnd2endTest, OverridePerCallCredentials) {
   ResetStub();
   EchoRequest request;
   EchoResponse response;
   ClientContext context;
-  std::shared_ptr<Credentials> creds1 =
+  std::shared_ptr<CallCredentials> creds1 =
       GoogleIAMCredentials("fake_token1", "fake_selector1");
   context.set_credentials(creds1);
-  std::shared_ptr<Credentials> creds2 =
+  std::shared_ptr<CallCredentials> creds2 =
       GoogleIAMCredentials("fake_token2", "fake_selector2");
   context.set_credentials(creds2);
   request.set_message("Hello");
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index 6a4691672871520e984f510b4832a2e61198cc1c..082119d6d52f0cae48c0b86b6a79825bd0e5c82b 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -120,7 +120,7 @@ class GenericEnd2endTest : public ::testing::Test {
 
   void ResetStub() {
     std::shared_ptr<Channel> channel =
-        CreateChannel(server_address_.str(), InsecureCredentials());
+        CreateChannel(server_address_.str(), InsecureChannelCredentials());
     generic_stub_.reset(new GenericStub(channel));
   }
 
diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc
index 80057d893e10071e9bccbeeaf722db1c2ea35daf..bd34cfba671972f87fd4da6b38715a74d8fffd5a 100644
--- a/test/cpp/end2end/mock_test.cc
+++ b/test/cpp/end2end/mock_test.cc
@@ -244,7 +244,7 @@ class MockTest : public ::testing::Test {
 
   void ResetStub() {
     std::shared_ptr<Channel> channel =
-        CreateChannel(server_address_.str(), InsecureCredentials());
+        CreateChannel(server_address_.str(), InsecureChannelCredentials());
     stub_ = grpc::cpp::test::util::TestService::NewStub(channel);
   }
 
diff --git a/test/cpp/end2end/server_crash_test_client.cc b/test/cpp/end2end/server_crash_test_client.cc
index 17869362c2e70d81bd7807b9ff0a72ef55e76301..2baefcbf42d06ce7bcc04edb767d3bf6427ea923 100644
--- a/test/cpp/end2end/server_crash_test_client.cc
+++ b/test/cpp/end2end/server_crash_test_client.cc
@@ -58,7 +58,7 @@ using namespace gflags;
 int main(int argc, char** argv) {
   ParseCommandLineFlags(&argc, &argv, true);
   auto stub = grpc::cpp::test::util::TestService::NewStub(
-      grpc::CreateChannel(FLAGS_address, grpc::InsecureCredentials()));
+      grpc::CreateChannel(FLAGS_address, grpc::InsecureChannelCredentials()));
 
   EchoRequest request;
   EchoResponse response;
diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc
index 0549bb8b5f7f7d46b06a61a20a575f301fba00fe..b1b18b2a7f4b30eb55d1dc274f10e7fc2f9ea3a0 100644
--- a/test/cpp/end2end/shutdown_test.cc
+++ b/test/cpp/end2end/shutdown_test.cc
@@ -93,7 +93,7 @@ class ShutdownTest : public ::testing::Test {
 
   void ResetStub() {
     string target = "dns:localhost:" + to_string(port_);
-    channel_ = CreateChannel(target, InsecureCredentials());
+    channel_ = CreateChannel(target, InsecureChannelCredentials());
     stub_ = grpc::cpp::test::util::TestService::NewStub(channel_);
   }
 
diff --git a/test/cpp/end2end/streaming_throughput_test.cc b/test/cpp/end2end/streaming_throughput_test.cc
index d4ab1486ccbbde7d6f266d4c8179b60ec2893339..b7e103a1ae0bf99a4095e48250867261e6ec0521 100644
--- a/test/cpp/end2end/streaming_throughput_test.cc
+++ b/test/cpp/end2end/streaming_throughput_test.cc
@@ -160,7 +160,7 @@ class End2endTest : public ::testing::Test {
 
   void ResetStub() {
     std::shared_ptr<Channel> channel =
-        CreateChannel(server_address_.str(), InsecureCredentials());
+        CreateChannel(server_address_.str(), InsecureChannelCredentials());
     stub_ = grpc::cpp::test::util::TestService::NewStub(channel);
   }
 
diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc
index 75a07d89c5d5c0cdedf5e1c57e5e2ca14f035fee..fb82b9613596e63543edc6373484360e2ab39567 100644
--- a/test/cpp/end2end/thread_stress_test.cc
+++ b/test/cpp/end2end/thread_stress_test.cc
@@ -190,7 +190,7 @@ class End2endTest : public ::testing::Test {
 
   void ResetStub() {
     std::shared_ptr<Channel> channel =
-        CreateChannel(server_address_.str(), InsecureCredentials());
+        CreateChannel(server_address_.str(), InsecureChannelCredentials());
     stub_ = grpc::cpp::test::util::TestService::NewStub(channel);
   }
 
diff --git a/test/cpp/end2end/zookeeper_test.cc b/test/cpp/end2end/zookeeper_test.cc
index d4c7f0489fd09a3cdd47818375185e412c5752fe..e88c0f9c68a870b9bebf015ad073c0f1fba2f2f1 100644
--- a/test/cpp/end2end/zookeeper_test.cc
+++ b/test/cpp/end2end/zookeeper_test.cc
@@ -157,7 +157,7 @@ class ZookeeperTest : public ::testing::Test {
 
   void ResetStub() {
     string target = "zookeeper://" + zookeeper_address_ + "/test";
-    channel_ = CreateChannel(target, InsecureCredentials());
+    channel_ = CreateChannel(target, InsecureChannelCredentials());
     stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_));
   }
 
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index 61b46d25aa041a08f32dd901ec8b82b1ee02f786..5caf0f2d1d0242bfaec238bce655292477bf4bdc 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -76,11 +76,11 @@ grpc::string GetServiceAccountJsonKey() {
 }
 
 grpc::string GetOauth2AccessToken() {
-  std::shared_ptr<Credentials> creds = GoogleComputeEngineCredentials();
-  SecureCredentials* secure_creds =
-      dynamic_cast<SecureCredentials*>(creds.get());
+  std::shared_ptr<CallCredentials> creds = GoogleComputeEngineCredentials();
+  SecureCallCredentials* secure_creds =
+      dynamic_cast<SecureCallCredentials*>(creds.get());
   GPR_ASSERT(secure_creds != nullptr);
-  grpc_credentials* c_creds = secure_creds->GetRawCreds();
+  grpc_call_credentials* c_creds = secure_creds->GetRawCreds();
   char* token = grpc_test_fetch_oauth2_token_with_credentials(c_creds);
   GPR_ASSERT(token != nullptr);
   gpr_log(GPR_INFO, "Get raw oauth2 access token: %s", token);
@@ -98,13 +98,13 @@ std::shared_ptr<Channel> CreateChannelForTestCase(
            FLAGS_server_port);
 
   if (test_case == "compute_engine_creds") {
-    std::shared_ptr<Credentials> creds;
+    std::shared_ptr<CallCredentials> creds;
     GPR_ASSERT(FLAGS_use_tls);
     creds = GoogleComputeEngineCredentials();
     return CreateTestChannel(host_port, FLAGS_server_host_override,
                              FLAGS_use_tls, !FLAGS_use_test_ca, creds);
   } else if (test_case == "jwt_token_creds") {
-    std::shared_ptr<Credentials> creds;
+    std::shared_ptr<CallCredentials> creds;
     GPR_ASSERT(FLAGS_use_tls);
     grpc::string json_key = GetServiceAccountJsonKey();
     std::chrono::seconds token_lifetime = std::chrono::hours(1);
@@ -114,7 +114,7 @@ std::shared_ptr<Channel> CreateChannelForTestCase(
                              FLAGS_use_tls, !FLAGS_use_test_ca, creds);
   } else if (test_case == "oauth2_auth_token") {
     grpc::string raw_token = GetOauth2AccessToken();
-    std::shared_ptr<Credentials> creds = AccessTokenCredentials(raw_token);
+    std::shared_ptr<CallCredentials> creds = AccessTokenCredentials(raw_token);
     return CreateTestChannel(host_port, FLAGS_server_host_override,
                              FLAGS_use_tls, !FLAGS_use_test_ca, creds);
   } else {
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index 46a5255e4c62d5f9c10f292060a9d73be7791340..6340007fa4bc5b6bca6136b2c58fd75aeb11b401 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -244,7 +244,7 @@ void InteropClient::DoPerRpcCreds(const grpc::string& json_key) {
 
   ClientContext context;
   std::chrono::seconds token_lifetime = std::chrono::hours(1);
-  std::shared_ptr<Credentials> creds =
+  std::shared_ptr<CallCredentials> creds =
       ServiceAccountJWTAccessCredentials(json_key, token_lifetime.count());
 
   context.set_credentials(creds);
diff --git a/test/cpp/interop/metrics_client.cc b/test/cpp/interop/metrics_client.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5d60a842038a65ca2ef72a8db7f93f3db156b2a2
--- /dev/null
+++ b/test/cpp/interop/metrics_client.cc
@@ -0,0 +1,102 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *is % allowed in string
+ */
+
+#include <memory>
+#include <string>
+
+#include <gflags/gflags.h>
+#include <grpc++/grpc++.h>
+
+#include "test/cpp/util/metrics_server.h"
+#include "test/cpp/util/test_config.h"
+#include "test/proto/metrics.grpc.pb.h"
+#include "test/proto/metrics.pb.h"
+
+DEFINE_string(metrics_server_address, "",
+              "The metrics server addresses in the fomrat <hostname>:<port>");
+
+using grpc::testing::EmptyMessage;
+using grpc::testing::GaugeResponse;
+using grpc::testing::MetricsService;
+using grpc::testing::MetricsServiceImpl;
+
+void PrintMetrics(grpc::string& server_address) {
+  gpr_log(GPR_INFO, "creating a channel to %s", server_address.c_str());
+  std::shared_ptr<grpc::Channel> channel(
+      grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials()));
+
+  std::unique_ptr<MetricsService::Stub> stub(MetricsService::NewStub(channel));
+
+  grpc::ClientContext context;
+  EmptyMessage message;
+
+  std::unique_ptr<grpc::ClientReader<GaugeResponse>> reader(
+      stub->GetAllGauges(&context, message));
+
+  GaugeResponse gauge_response;
+  long overall_qps = 0;
+  int idx = 0;
+  while (reader->Read(&gauge_response)) {
+    if (gauge_response.value_case() == GaugeResponse::kLongValue) {
+      gpr_log(GPR_INFO, "Gauge: %d (%s: %ld)", ++idx,
+              gauge_response.name().c_str(), gauge_response.long_value());
+      overall_qps += gauge_response.long_value();
+    } else {
+      gpr_log(GPR_INFO, "Gauge %s is not a long value", gauge_response.name().c_str());
+    }
+  }
+
+  gpr_log(GPR_INFO, "OVERALL: %ld", overall_qps);
+
+  const grpc::Status status = reader->Finish();
+  if (!status.ok()) {
+    gpr_log(GPR_ERROR, "Error in getting metrics from the client");
+  }
+}
+
+int main(int argc, char** argv) {
+  grpc::testing::InitTest(&argc, &argv, true);
+
+  // Make sure server_addresses flag is not empty
+  if (FLAGS_metrics_server_address.empty()) {
+    gpr_log(
+        GPR_ERROR,
+        "Cannot connect to the Metrics server. Please pass the address of the"
+        "metrics server to connect to via the 'metrics_server_address' flag");
+    return 1;
+  }
+
+  PrintMetrics(FLAGS_metrics_server_address);
+
+  return 0;
+}
diff --git a/test/cpp/interop/stress_interop_client.cc b/test/cpp/interop/stress_interop_client.cc
index f8c55cf795917023d42f01a2058b231a0374a503..5d2951e3ed531e4ec003074006f7bccca5df7e0c 100644
--- a/test/cpp/interop/stress_interop_client.cc
+++ b/test/cpp/interop/stress_interop_client.cc
@@ -40,6 +40,7 @@
 #include <grpc++/create_channel.h>
 
 #include "test/cpp/interop/interop_client.h"
+#include "test/cpp/util/metrics_server.h"
 
 namespace grpc {
 namespace testing {
@@ -81,21 +82,19 @@ TestCaseType WeightedRandomTestSelector::GetNextTest() const {
 
 StressTestInteropClient::StressTestInteropClient(
     int test_id, const grpc::string& server_address,
+    std::shared_ptr<Channel> channel,
     const WeightedRandomTestSelector& test_selector, long test_duration_secs,
-    long sleep_duration_ms)
+    long sleep_duration_ms, long metrics_collection_interval_secs)
     : test_id_(test_id),
       server_address_(server_address),
+      channel_(channel),
+      interop_client_(new InteropClient(channel, false)),
       test_selector_(test_selector),
       test_duration_secs_(test_duration_secs),
-      sleep_duration_ms_(sleep_duration_ms) {
-  // TODO(sreek): This will change once we add support for other tests
-  // that won't work with InsecureCredentials()
-  std::shared_ptr<Channel> channel(
-      CreateChannel(server_address, InsecureCredentials()));
-  interop_client_.reset(new InteropClient(channel, false));
-}
+      sleep_duration_ms_(sleep_duration_ms),
+      metrics_collection_interval_secs_(metrics_collection_interval_secs) {}
 
-void StressTestInteropClient::MainLoop() {
+void StressTestInteropClient::MainLoop(std::shared_ptr<Gauge> qps_gauge) {
   gpr_log(GPR_INFO, "Running test %d. ServerAddr: %s", test_id_,
           server_address_.c_str());
 
@@ -104,21 +103,38 @@ void StressTestInteropClient::MainLoop() {
                    gpr_time_from_seconds(test_duration_secs_, GPR_TIMESPAN));
 
   gpr_timespec current_time = gpr_now(GPR_CLOCK_REALTIME);
+  gpr_timespec next_stat_collection_time = current_time;
+  gpr_timespec collection_interval =
+      gpr_time_from_seconds(metrics_collection_interval_secs_, GPR_TIMESPAN);
+  long num_calls_per_interval = 0;
+
   while (test_duration_secs_ < 0 ||
-         gpr_time_cmp(current_time, test_end_time) < 0) {
+         gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), test_end_time) < 0) {
     // Select the test case to execute based on the weights and execute it
     TestCaseType test_case = test_selector_.GetNextTest();
     gpr_log(GPR_INFO, "%d - Executing the test case %d", test_id_, test_case);
     RunTest(test_case);
 
+    num_calls_per_interval++;
+
+    // See if its time to collect stats yet
+    current_time = gpr_now(GPR_CLOCK_REALTIME);
+    if (gpr_time_cmp(next_stat_collection_time, current_time) < 0) {
+      qps_gauge->Set(num_calls_per_interval /
+                     metrics_collection_interval_secs_);
+
+      num_calls_per_interval = 0;
+      next_stat_collection_time =
+          gpr_time_add(current_time, collection_interval);
+    }
+
     // Sleep between successive calls if needed
     if (sleep_duration_ms_ > 0) {
-      gpr_timespec sleep_time = gpr_time_add(
-          current_time, gpr_time_from_millis(sleep_duration_ms_, GPR_TIMESPAN));
+      gpr_timespec sleep_time =
+          gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                       gpr_time_from_millis(sleep_duration_ms_, GPR_TIMESPAN));
       gpr_sleep_until(sleep_time);
     }
-
-    current_time = gpr_now(GPR_CLOCK_REALTIME);
   }
 }
 
diff --git a/test/cpp/interop/stress_interop_client.h b/test/cpp/interop/stress_interop_client.h
index 36261e501ffb89df59dafb51050a9d15e4def34b..6fd303d6b791db003564638327d9cab9b828fc6f 100644
--- a/test/cpp/interop/stress_interop_client.h
+++ b/test/cpp/interop/stress_interop_client.h
@@ -41,6 +41,7 @@
 #include <grpc++/create_channel.h>
 
 #include "test/cpp/interop/interop_client.h"
+#include "test/cpp/util/metrics_server.h"
 
 namespace grpc {
 namespace testing {
@@ -84,20 +85,26 @@ class WeightedRandomTestSelector {
 class StressTestInteropClient {
  public:
   StressTestInteropClient(int test_id, const grpc::string& server_address,
+                          std::shared_ptr<Channel> channel,
                           const WeightedRandomTestSelector& test_selector,
-                          long test_duration_secs, long sleep_duration_ms);
+                          long test_duration_secs, long sleep_duration_ms,
+                          long metrics_collection_interval_secs);
 
-  void MainLoop();  // The main function. Use this as the thread entry point.
+  // The main function. Use this as the thread entry point.
+  // qps_gauge is the Gauge to record the requests per second metric
+  void MainLoop(std::shared_ptr<Gauge> qps_gauge);
 
  private:
   void RunTest(TestCaseType test_case);
 
   int test_id_;
-  std::unique_ptr<InteropClient> interop_client_;
   const grpc::string& server_address_;
+  std::shared_ptr<Channel> channel_;
+  std::unique_ptr<InteropClient> interop_client_;
   const WeightedRandomTestSelector& test_selector_;
   long test_duration_secs_;
   long sleep_duration_ms_;
+  long metrics_collection_interval_secs_;
 };
 
 }  // namespace testing
diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc
index 5d1419728e4ca7d46ddc809a7d828a12e1f2860d..7e926a1a56d0de120a5caeda039f41fc3e1bd846 100644
--- a/test/cpp/interop/stress_test.cc
+++ b/test/cpp/interop/stress_test.cc
@@ -41,10 +41,19 @@
 #include <grpc/support/time.h>
 #include <grpc++/create_channel.h>
 #include <grpc++/grpc++.h>
+#include <grpc++/impl/thd.h>
 
 #include "test/cpp/interop/interop_client.h"
 #include "test/cpp/interop/stress_interop_client.h"
+#include "test/cpp/util/metrics_server.h"
 #include "test/cpp/util/test_config.h"
+#include "test/proto/metrics.grpc.pb.h"
+#include "test/proto/metrics.pb.h"
+
+DEFINE_int32(metrics_port, 8081, "The metrics server port.");
+
+DEFINE_int32(metrics_collection_interval_secs, 5,
+             "How often (in seconds) should metrics be recorded.");
 
 DEFINE_int32(sleep_duration_ms, 0,
              "The duration (in millisec) between two"
@@ -61,6 +70,11 @@ DEFINE_string(server_addresses, "localhost:8080",
               " \"<name_1>:<port_1>,<name_2>:<port_1>...<name_N>:<port_N>\"\n"
               " Note: <name> can be servername or IP address.");
 
+DEFINE_int32(num_stubs_per_channel, 1,
+             "Number of stubs per each channels to server. This number also "
+             "indicates the max number of parallel RPC calls on each channel "
+             "at any given time.");
+
 // TODO(sreek): Add more test cases here in future
 DEFINE_string(test_cases, "",
               "List of test cases to call along with the"
@@ -78,16 +92,13 @@ DEFINE_string(test_cases, "",
               " 'large_unary', 10% of the time and 'empty_stream' the remaining"
               " 70% of the time");
 
-using std::make_pair;
-using std::pair;
-using std::thread;
-using std::vector;
-
 using grpc::testing::kTestCaseList;
+using grpc::testing::MetricsService;
+using grpc::testing::MetricsServiceImpl;
 using grpc::testing::StressTestInteropClient;
 using grpc::testing::TestCaseType;
-using grpc::testing::WeightedRandomTestSelector;
 using grpc::testing::UNKNOWN_TEST;
+using grpc::testing::WeightedRandomTestSelector;
 
 TestCaseType GetTestTypeFromName(const grpc::string& test_name) {
   TestCaseType test_case = UNKNOWN_TEST;
@@ -104,7 +115,7 @@ TestCaseType GetTestTypeFromName(const grpc::string& test_name) {
 
 // Converts a string of comma delimited tokens to a vector of tokens
 bool ParseCommaDelimitedString(const grpc::string& comma_delimited_str,
-                               vector<grpc::string>& tokens) {
+                               std::vector<grpc::string>& tokens) {
   size_t bpos = 0;
   size_t epos = grpc::string::npos;
 
@@ -122,10 +133,10 @@ bool ParseCommaDelimitedString(const grpc::string& comma_delimited_str,
 //   - Whether parsing was successful (return value)
 //   - Vector of (test_type_enum, weight) pairs returned via 'tests' parameter
 bool ParseTestCasesString(const grpc::string& test_cases,
-                          vector<pair<TestCaseType, int>>& tests) {
+                          std::vector<std::pair<TestCaseType, int>>& tests) {
   bool is_success = true;
 
-  vector<grpc::string> tokens;
+  std::vector<grpc::string> tokens;
   ParseCommaDelimitedString(test_cases, tokens);
 
   for (auto it = tokens.begin(); it != tokens.end(); it++) {
@@ -153,8 +164,8 @@ bool ParseTestCasesString(const grpc::string& test_cases,
 }
 
 // For debugging purposes
-void LogParameterInfo(const vector<grpc::string>& addresses,
-                      const vector<pair<TestCaseType, int>>& tests) {
+void LogParameterInfo(const std::vector<grpc::string>& addresses,
+                      const std::vector<std::pair<TestCaseType, int>>& tests) {
   gpr_log(GPR_INFO, "server_addresses: %s", FLAGS_server_addresses.c_str());
   gpr_log(GPR_INFO, "test_cases : %s", FLAGS_test_cases.c_str());
   gpr_log(GPR_INFO, "sleep_duration_ms: %d", FLAGS_sleep_duration_ms);
@@ -180,7 +191,7 @@ int main(int argc, char** argv) {
   srand(time(NULL));
 
   // Parse the server addresses
-  vector<grpc::string> server_addresses;
+  std::vector<grpc::string> server_addresses;
   ParseCommaDelimitedString(FLAGS_server_addresses, server_addresses);
 
   // Parse test cases and weights
@@ -189,7 +200,7 @@ int main(int argc, char** argv) {
     return 1;
   }
 
-  vector<pair<TestCaseType, int>> tests;
+  std::vector<std::pair<TestCaseType, int>> tests;
   if (!ParseTestCasesString(FLAGS_test_cases, tests)) {
     gpr_log(GPR_ERROR, "Error in parsing test cases string %s ",
             FLAGS_test_cases.c_str());
@@ -199,23 +210,48 @@ int main(int argc, char** argv) {
   LogParameterInfo(server_addresses, tests);
 
   WeightedRandomTestSelector test_selector(tests);
+  MetricsServiceImpl metrics_service;
 
   gpr_log(GPR_INFO, "Starting test(s)..");
 
-  vector<thread> test_threads;
+  std::vector<grpc::thread> test_threads;
+
   int thread_idx = 0;
   for (auto it = server_addresses.begin(); it != server_addresses.end(); it++) {
-    StressTestInteropClient* client = new StressTestInteropClient(
-        ++thread_idx, *it, test_selector, FLAGS_test_duration_secs,
-        FLAGS_sleep_duration_ms);
-
-    test_threads.emplace_back(
-        thread(&StressTestInteropClient::MainLoop, client));
+    // TODO(sreek): This will change once we add support for other tests
+    // that won't work with InsecureChannelCredentials()
+    std::shared_ptr<grpc::Channel> channel(
+        grpc::CreateChannel(*it, grpc::InsecureChannelCredentials()));
+
+    // Make multiple stubs (as defined by num_stubs_per_channel flag) to use the
+    // same channel. This is to test calling multiple RPC calls in parallel on
+    // each channel.
+    for (int i = 0; i < FLAGS_num_stubs_per_channel; i++) {
+      StressTestInteropClient* client = new StressTestInteropClient(
+          ++thread_idx, *it, channel, test_selector, FLAGS_test_duration_secs,
+          FLAGS_sleep_duration_ms, FLAGS_metrics_collection_interval_secs);
+
+      bool is_already_created;
+      grpc::string metricName =
+          "/stress_test/qps/thread/" + std::to_string(thread_idx);
+      test_threads.emplace_back(
+          grpc::thread(&StressTestInteropClient::MainLoop, client,
+                 metrics_service.CreateGauge(metricName, &is_already_created)));
+
+      // The Gauge should not have been already created
+      GPR_ASSERT(!is_already_created);
+    }
   }
 
+  // Start metrics server before waiting for the stress test threads
+  std::unique_ptr<grpc::Server> metrics_server =
+      metrics_service.StartServer(FLAGS_metrics_port);
+
+  // Wait for the stress test threads to complete
   for (auto it = test_threads.begin(); it != test_threads.end(); it++) {
     it->join();
   }
 
+  metrics_server->Wait();
   return 0;
 }
diff --git a/test/cpp/qps/async_streaming_ping_pong_test.cc b/test/cpp/qps/async_streaming_ping_pong_test.cc
index 9fef93a70fd8e136589d9f888c8fa7433de65c11..0acdf3affb396771d17d9abb2682db73d8ca57d5 100644
--- a/test/cpp/qps/async_streaming_ping_pong_test.cc
+++ b/test/cpp/qps/async_streaming_ping_pong_test.cc
@@ -58,6 +58,7 @@ static void RunAsyncStreamingPingPong() {
 
   ServerConfig server_config;
   server_config.set_server_type(ASYNC_SERVER);
+  server_config.set_host("localhost");
   server_config.set_async_server_threads(1);
 
   const auto result =
diff --git a/test/cpp/qps/async_unary_ping_pong_test.cc b/test/cpp/qps/async_unary_ping_pong_test.cc
index b4ab0e5d5958c5396a6cf56a67684f537b65eea8..d21e116171aadef8cc7cfea43ccebf24bfe05c96 100644
--- a/test/cpp/qps/async_unary_ping_pong_test.cc
+++ b/test/cpp/qps/async_unary_ping_pong_test.cc
@@ -58,6 +58,7 @@ static void RunAsyncUnaryPingPong() {
 
   ServerConfig server_config;
   server_config.set_server_type(ASYNC_SERVER);
+  server_config.set_host("localhost");
   server_config.set_async_server_threads(1);
 
   const auto result =
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index f4400692feae915b58b09f1223614e0d6799582d..b24a90adacdba6b93c9d68c8703d71e8a0bafe44 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -181,29 +181,29 @@ class Client {
 
     std::unique_ptr<RandomDist> random_dist;
     switch (load.load_case()) {
-    case LoadParams::kClosedLoop:
-      // Closed-loop doesn't use random dist at all
-      break;
-    case LoadParams::kPoisson:
-      random_dist.reset(
-          new ExpDist(load.poisson().offered_load() / num_threads));
-      break;
-    case LoadParams::kUniform:
-      random_dist.reset(
-          new UniformDist(load.uniform().interarrival_lo() * num_threads,
-                          load.uniform().interarrival_hi() * num_threads));
-      break;
-    case LoadParams::kDeterm:
-      random_dist.reset(
-          new DetDist(num_threads / load.determ().offered_load()));
-      break;
-    case LoadParams::kPareto:
-      random_dist.reset(
-          new ParetoDist(load.pareto().interarrival_base() * num_threads,
-                         load.pareto().alpha()));
-      break;
-    default:
-      GPR_ASSERT(false);
+      case LoadParams::kClosedLoop:
+        // Closed-loop doesn't use random dist at all
+        break;
+      case LoadParams::kPoisson:
+        random_dist.reset(
+            new ExpDist(load.poisson().offered_load() / num_threads));
+        break;
+      case LoadParams::kUniform:
+        random_dist.reset(
+            new UniformDist(load.uniform().interarrival_lo() * num_threads,
+                            load.uniform().interarrival_hi() * num_threads));
+        break;
+      case LoadParams::kDeterm:
+        random_dist.reset(
+            new DetDist(num_threads / load.determ().offered_load()));
+        break;
+      case LoadParams::kPareto:
+        random_dist.reset(
+            new ParetoDist(load.pareto().interarrival_base() * num_threads,
+                           load.pareto().alpha()));
+        break;
+      default:
+        GPR_ASSERT(false);
     }
 
     // Set closed_loop_ based on whether or not random_dist is set
diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc
index 2c6247deea16e28b6e88d49b05eef929ea4b1926..20dc65046be214b25af39bcc92398d9e81db4d97 100644
--- a/test/cpp/qps/driver.cc
+++ b/test/cpp/qps/driver.cc
@@ -110,7 +110,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
   list<ClientContext> contexts;
 
   // To be added to the result, containing the final configuration used for
-  // client and config (incluiding host, etc.)
+  // client and config (including host, etc.)
   ClientConfig result_client_config;
   ServerConfig result_server_config;
 
@@ -162,7 +162,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
   auto* servers = new ServerData[num_servers];
   for (size_t i = 0; i < num_servers; i++) {
     servers[i].stub = WorkerService::NewStub(
-        CreateChannel(workers[i], InsecureCredentials()));
+        CreateChannel(workers[i], InsecureChannelCredentials()));
     ServerArgs args;
     result_server_config = server_config;
     *args.mutable_setup() = server_config;
@@ -189,7 +189,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
   auto* clients = new ClientData[num_clients];
   for (size_t i = 0; i < num_clients; i++) {
     clients[i].stub = WorkerService::NewStub(
-        CreateChannel(workers[i + num_servers], InsecureCredentials()));
+        CreateChannel(workers[i + num_servers], InsecureChannelCredentials()));
     ClientArgs args;
     result_client_config = client_config;
     *args.mutable_setup() = client_config;
diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h
index 35527d2a2cb2a1b08400d8190c98fbc6dcf2a83d..b45c769a779309289204a9b766883ff11473ccde 100644
--- a/test/cpp/qps/histogram.h
+++ b/test/cpp/qps/histogram.h
@@ -42,7 +42,9 @@ namespace testing {
 
 class Histogram {
  public:
-  Histogram() : impl_(gpr_histogram_create(0.01, 60e9)) {}
+  // TODO: look into making histogram params not hardcoded for C++
+  Histogram() : impl_(gpr_histogram_create(default_resolution(),
+                                           default_max_possible())) {}
   ~Histogram() {
     if (impl_) gpr_histogram_destroy(impl_);
   }
@@ -73,6 +75,9 @@ class Histogram {
                                  p.sum_of_squares(), p.count());
   }
 
+  static double default_resolution() { return 0.01; }
+  static double default_max_possible() { return 60e9; }
+
  private:
   Histogram(const Histogram&);
   Histogram& operator=(const Histogram&);
diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc
index 4c93a042cf5b1ff0e2b609f2d6f6cf359fe1ab9b..0479e1aff4bcc758d7d3df3b431d94e06e3cf89a 100644
--- a/test/cpp/qps/qps_driver.cc
+++ b/test/cpp/qps/qps_driver.cc
@@ -137,8 +137,14 @@ static void QpsDriver() {
     // No further load parameters to set up for closed loop
   }
 
+  client_config.mutable_histogram_params()->
+      set_resolution(Histogram::default_resolution());
+  client_config.mutable_histogram_params()->
+      set_max_possible(Histogram::default_max_possible());
+
   ServerConfig server_config;
   server_config.set_server_type(server_type);
+  server_config.set_host("localhost");
   server_config.set_async_server_threads(FLAGS_async_server_threads);
 
   if (FLAGS_secure_test) {
diff --git a/test/cpp/qps/qps_openloop_test.cc b/test/cpp/qps/qps_openloop_test.cc
index dc88c893bb9f1f5d2cb9ef5d43d9f81956d93afb..51df79ef2f3f3eb6b3ac753be2e1a79fa89312f9 100644
--- a/test/cpp/qps/qps_openloop_test.cc
+++ b/test/cpp/qps/qps_openloop_test.cc
@@ -59,6 +59,7 @@ static void RunQPS() {
 
   ServerConfig server_config;
   server_config.set_server_type(ASYNC_SERVER);
+  server_config.set_host("localhost");
   server_config.set_async_server_threads(4);
 
   const auto result =
diff --git a/test/cpp/qps/qps_test.cc b/test/cpp/qps/qps_test.cc
index 89b35cfb0523c3dcd729d8ef9546897520830be5..1f87d18137417f0f7df7fc0663e69351951a46c3 100644
--- a/test/cpp/qps/qps_test.cc
+++ b/test/cpp/qps/qps_test.cc
@@ -58,6 +58,7 @@ static void RunQPS() {
 
   ServerConfig server_config;
   server_config.set_server_type(ASYNC_SERVER);
+  server_config.set_host("localhost");
   server_config.set_async_server_threads(8);
 
   const auto result =
diff --git a/test/cpp/qps/qps_test_with_poll.cc b/test/cpp/qps/qps_test_with_poll.cc
index 97da4096ed3253145eafc47f75d8c87baee0e2b0..dc800092db9775c593d41d756e3a1a4198ea0730 100644
--- a/test/cpp/qps/qps_test_with_poll.cc
+++ b/test/cpp/qps/qps_test_with_poll.cc
@@ -62,6 +62,7 @@ static void RunQPS() {
 
   ServerConfig server_config;
   server_config.set_server_type(ASYNC_SERVER);
+  server_config.set_host("localhost");
   server_config.set_async_server_threads(4);
 
   const auto result =
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index 78779231d38af3fbcfb90cc2b25a35f1fbbed104..5caf3fe69a290c654b92d1c348c5ca5737aaf3b2 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -115,8 +115,8 @@ class PerfDbReporter : public Reporter {
         test_name_(test_name),
         sys_info_(sys_info),
         tag_(tag) {
-    perf_db_client_.init(
-        grpc::CreateChannel(server_address, grpc::InsecureCredentials()));
+    perf_db_client_.init(grpc::CreateChannel(
+        server_address, grpc::InsecureChannelCredentials()));
   }
   ~PerfDbReporter() GRPC_OVERRIDE { SendData(); };
 
diff --git a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
index df06f7e471f27249bd011d78f737827850905c20..ce9f02cceb2a1a74ca7ef790a5b056b6cf40d4a7 100644
--- a/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
+++ b/test/cpp/qps/secure_sync_unary_ping_pong_test.cc
@@ -57,6 +57,7 @@ static void RunSynchronousUnaryPingPong() {
 
   ServerConfig server_config;
   server_config.set_server_type(SYNC_SERVER);
+  server_config.set_host("localhost");
 
   // Set up security params
   SecurityParams security;
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 2d922fa6150dac51779099af60758bf559b932d9..c151918ce4c967e75bc8a2b6828c9fbea2aedcfb 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -60,7 +60,7 @@ class AsyncQpsServerTest : public Server {
   explicit AsyncQpsServerTest(const ServerConfig &config) : Server(config) {
     char *server_address = NULL;
 
-    gpr_join_host_port(&server_address, "::", port());
+    gpr_join_host_port(&server_address, config.host().c_str(), port());
 
     ServerBuilder builder;
     builder.AddListeningPort(server_address,
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index a09b174b7e0448c680c392a55a1d8c040029b6a6..3a15bec888d3bdd1e5d0fe42cdc6698d954d9e23 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -89,7 +89,7 @@ class SynchronousServer GRPC_FINAL : public grpc::testing::Server {
 
     char* server_address = NULL;
 
-    gpr_join_host_port(&server_address, "::", port());
+    gpr_join_host_port(&server_address, config.host().c_str(), port());
     builder.AddListeningPort(server_address,
                              Server::CreateServerCredentials(config));
     gpr_free(server_address);
diff --git a/test/cpp/qps/sync_streaming_ping_pong_test.cc b/test/cpp/qps/sync_streaming_ping_pong_test.cc
index 186afc03f7cece0ea8af3513ab63abc5a8b08ee2..dd8c682815c37020de7ef467442a47cafeccce7f 100644
--- a/test/cpp/qps/sync_streaming_ping_pong_test.cc
+++ b/test/cpp/qps/sync_streaming_ping_pong_test.cc
@@ -57,6 +57,7 @@ static void RunSynchronousStreamingPingPong() {
 
   ServerConfig server_config;
   server_config.set_server_type(SYNC_SERVER);
+  server_config.set_host("localhost");
 
   const auto result =
       RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
diff --git a/test/cpp/qps/sync_unary_ping_pong_test.cc b/test/cpp/qps/sync_unary_ping_pong_test.cc
index 25851833a6d6f316bc240e7c598be9fca627b9a1..2edb33ef0146952ba740d3c3d7f331cabf8037c4 100644
--- a/test/cpp/qps/sync_unary_ping_pong_test.cc
+++ b/test/cpp/qps/sync_unary_ping_pong_test.cc
@@ -57,6 +57,7 @@ static void RunSynchronousUnaryPingPong() {
 
   ServerConfig server_config;
   server_config.set_server_type(SYNC_SERVER);
+  server_config.set_host("localhost");
 
   const auto result =
       RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc
index 9c8d59987e03557e7b86071c48e6b57711ddbd4b..32cd8e41030095f2df25342cdb4edb6265cbd6ea 100644
--- a/test/cpp/util/cli_call_test.cc
+++ b/test/cpp/util/cli_call_test.cc
@@ -89,7 +89,8 @@ class CliCallTest : public ::testing::Test {
   void TearDown() GRPC_OVERRIDE { server_->Shutdown(); }
 
   void ResetStub() {
-    channel_ = CreateChannel(server_address_.str(), InsecureCredentials());
+    channel_ =
+        CreateChannel(server_address_.str(), InsecureChannelCredentials());
     stub_ = grpc::cpp::test::util::TestService::NewStub(channel_);
   }
 
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index f0d5bfc7ebc1ba0cf28849a8174731771acacaa8..0cd9f9e76738c459ecf26434a502a754bad812a6 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -58,13 +58,14 @@ namespace grpc {
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
     bool enable_ssl, bool use_prod_roots,
-    const std::shared_ptr<Credentials>& creds) {
+    const std::shared_ptr<CallCredentials>& creds) {
   ChannelArguments channel_args;
   if (enable_ssl) {
     const char* roots_certs = use_prod_roots ? "" : test_root_cert;
     SslCredentialsOptions ssl_opts = {roots_certs, "", ""};
 
-    std::shared_ptr<Credentials> channel_creds = SslCredentials(ssl_opts);
+    std::shared_ptr<ChannelCredentials> channel_creds =
+        SslCredentials(ssl_opts);
 
     if (!server.empty() && !override_hostname.empty()) {
       channel_args.SetSslTargetNameOverride(override_hostname);
@@ -72,11 +73,11 @@ std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& connect_to =
         server.empty() ? override_hostname : server;
     if (creds.get()) {
-      channel_creds = CompositeCredentials(creds, channel_creds);
+      channel_creds = CompositeChannelCredentials(channel_creds, creds);
     }
     return CreateCustomChannel(connect_to, channel_creds, channel_args);
   } else {
-    return CreateChannel(server, InsecureCredentials());
+    return CreateChannel(server, InsecureChannelCredentials());
   }
 }
 
@@ -84,7 +85,7 @@ std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
     bool enable_ssl, bool use_prod_roots) {
   return CreateTestChannel(server, override_hostname, enable_ssl,
-                           use_prod_roots, std::shared_ptr<Credentials>());
+                           use_prod_roots, std::shared_ptr<CallCredentials>());
 }
 
 // Shortcut for end2end and interop tests.
diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h
index a4750689a0c826fc8cfc46765eec6e2b02c2fbf9..b50d653de3b9d2744949709acd7eaf5c3f5e5492 100644
--- a/test/cpp/util/create_test_channel.h
+++ b/test/cpp/util/create_test_channel.h
@@ -51,7 +51,7 @@ std::shared_ptr<Channel> CreateTestChannel(
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
     bool enable_ssl, bool use_prod_roots,
-    const std::shared_ptr<Credentials>& creds);
+    const std::shared_ptr<CallCredentials>& creds);
 
 }  // namespace grpc
 
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index 334b6efb6a54ef0745d7c866d18903f1723b935a..3f40b242fc00fd7abbd2a0dae6be7544f95f068f 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -148,9 +148,9 @@ int main(int argc, char** argv) {
   std::stringstream input_stream;
   input_stream << input_file.rdbuf();
 
-  std::shared_ptr<grpc::Credentials> creds;
+  std::shared_ptr<grpc::ChannelCredentials> creds;
   if (!FLAGS_enable_ssl) {
-    creds = grpc::InsecureCredentials();
+    creds = grpc::InsecureChannelCredentials();
   } else {
     if (FLAGS_use_auth) {
       creds = grpc::GoogleDefaultCredentials();
diff --git a/test/cpp/util/metrics_server.cc b/test/cpp/util/metrics_server.cc
new file mode 100644
index 0000000000000000000000000000000000000000..426295f9b441e1952cc2b6da920a55dd39515baa
--- /dev/null
+++ b/test/cpp/util/metrics_server.cc
@@ -0,0 +1,119 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *is % allowed in string
+ */
+
+#include "test/cpp/util/metrics_server.h"
+
+#include <grpc++/server_builder.h>
+
+#include "test/proto/metrics.grpc.pb.h"
+#include "test/proto/metrics.pb.h"
+
+namespace grpc {
+namespace testing {
+
+Gauge::Gauge(long initial_val) : val_(initial_val) {}
+
+void Gauge::Set(long new_val) {
+  std::lock_guard<std::mutex> lock(val_mu_);
+  val_ = new_val;
+}
+
+long Gauge::Get() {
+  std::lock_guard<std::mutex> lock(val_mu_);
+  return val_;
+}
+
+grpc::Status MetricsServiceImpl::GetAllGauges(
+    ServerContext* context, const EmptyMessage* request,
+    ServerWriter<GaugeResponse>* writer) {
+  gpr_log(GPR_INFO, "GetAllGauges called");
+
+  std::lock_guard<std::mutex> lock(mu_);
+  for (auto it = gauges_.begin(); it != gauges_.end(); it++) {
+    GaugeResponse resp;
+    resp.set_name(it->first);                // Gauge name
+    resp.set_long_value(it->second->Get());  // Gauge value
+    writer->Write(resp);
+  }
+
+  return Status::OK;
+}
+
+grpc::Status MetricsServiceImpl::GetGauge(ServerContext* context,
+                                          const GaugeRequest* request,
+                                          GaugeResponse* response) {
+  std::lock_guard<std::mutex> lock(mu_);
+
+  const auto it = gauges_.find(request->name());
+  if (it != gauges_.end()) {
+    response->set_name(it->first);
+    response->set_long_value(it->second->Get());
+  }
+
+  return Status::OK;
+}
+
+std::shared_ptr<Gauge> MetricsServiceImpl::CreateGauge(const grpc::string& name,
+                                                       bool* already_present) {
+  std::lock_guard<std::mutex> lock(mu_);
+
+  std::shared_ptr<Gauge> gauge(new Gauge(0));
+  const auto p = gauges_.emplace(name, gauge);
+
+  // p.first is an iterator pointing to <name, shared_ptr<Gauge>> pair. p.second
+  // is a boolean which is set to 'true' if the Gauge is inserted in the guages_
+  // map and 'false' if it is already present in the map
+  *already_present = !p.second;
+  return p.first->second;
+}
+
+// Starts the metrics server and returns the grpc::Server instance. Call Wait()
+// on the returned server instance.
+std::unique_ptr<grpc::Server> MetricsServiceImpl::StartServer(int port) {
+  gpr_log(GPR_INFO, "Building metrics server..");
+
+  const grpc::string address = "0.0.0.0:" + std::to_string(port);
+
+  ServerBuilder builder;
+  builder.AddListeningPort(address, grpc::InsecureServerCredentials());
+  builder.RegisterService(this);
+
+  std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
+  gpr_log(GPR_INFO, "Metrics server %s started. Ready to receive requests..",
+          address.c_str());
+
+  return server;
+}
+
+}  // namespace testing
+}  // namespace grpc
diff --git a/test/cpp/util/metrics_server.h b/test/cpp/util/metrics_server.h
new file mode 100644
index 0000000000000000000000000000000000000000..edde37dc4c0365fce38152480dbbaa7660c35fb7
--- /dev/null
+++ b/test/cpp/util/metrics_server.h
@@ -0,0 +1,100 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *is % allowed in string
+ */
+#ifndef GRPC_TEST_CPP_METRICS_SERVER_H
+#define GRPC_TEST_CPP_METRICS_SERVER_H
+
+#include <map>
+#include <mutex>
+
+#include "test/proto/metrics.grpc.pb.h"
+#include "test/proto/metrics.pb.h"
+
+/*
+ * This implements a Metrics server defined in test/proto/metrics.proto. Any
+ * test service can use this to export Metrics (TODO (sreek): Only Gauges for
+ * now).
+ *
+ * Example:
+ *    MetricsServiceImpl metricsImpl;
+ *    ..
+ *    // Create Gauge(s). Note: Gauges can be created even after calling
+ *    // 'StartServer'.
+ *    Gauge gauge1 = metricsImpl.CreateGauge("foo",is_present);
+ *    // gauge1 can now be used anywhere in the program to set values.
+ *    ...
+ *    // Create the metrics server
+ *    std::unique_ptr<grpc::Server> server = metricsImpl.StartServer(port);
+ *    server->Wait(); // Note: This is blocking.
+ */
+namespace grpc {
+namespace testing {
+
+// TODO(sreek): Add support for other types of Gauges like Double, String in
+// future
+class Gauge {
+ public:
+  Gauge(long initial_val);
+  void Set(long new_val);
+  long Get();
+
+ private:
+  long val_;
+  std::mutex val_mu_;
+};
+
+class MetricsServiceImpl GRPC_FINAL : public MetricsService::Service {
+ public:
+  grpc::Status GetAllGauges(ServerContext* context, const EmptyMessage* request,
+                            ServerWriter<GaugeResponse>* writer) GRPC_OVERRIDE;
+
+  grpc::Status GetGauge(ServerContext* context, const GaugeRequest* request,
+                        GaugeResponse* response) GRPC_OVERRIDE;
+
+  // Create a Gauge with name 'name'. is_present is set to true if the Gauge
+  // is already present in the map.
+  // NOTE: CreateGauge can be called anytime (i.e before or after calling
+  // StartServer).
+  std::shared_ptr<Gauge> CreateGauge(const grpc::string& name,
+                                     bool* already_present);
+
+  std::unique_ptr<grpc::Server> StartServer(int port);
+
+ private:
+  std::map<string, std::shared_ptr<Gauge>> gauges_;
+  std::mutex mu_;
+};
+
+}  // namespace testing
+}  // namespace grpc
+
+#endif  // GRPC_TEST_CPP_METRICS_SERVER_H
diff --git a/test/proto/benchmarks/control.proto b/test/proto/benchmarks/control.proto
index 966ab78baae32d57130883d39e42ccebca4b6a09..42a5dd0a8594fe43480405af5945d60f61dd5e04 100644
--- a/test/proto/benchmarks/control.proto
+++ b/test/proto/benchmarks/control.proto
@@ -49,7 +49,10 @@ enum RpcType {
   STREAMING = 1;
 }
 
+// Parameters of poisson process distribution, which is a good representation
+// of activity coming in from independent identical stationary sources.
 message PoissonParams {
+  // The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
   double offered_load = 1;
 }
 
@@ -67,6 +70,8 @@ message ParetoParams {
   double alpha = 2;
 }
 
+// Once an RPC finishes, immediately start a new one.
+// No configuration parameters needed.
 message ClosedLoopParams {
 }
 
@@ -87,16 +92,23 @@ message SecurityParams {
 }
 
 message ClientConfig {
+  // List of targets to connect to. At least one target needs to be specified.
   repeated string server_targets = 1;
   ClientType client_type = 2;
   SecurityParams security_params = 3;
+  // How many concurrent RPCs to start for each channel.
+  // For synchronous client, use a separate thread for each outstanding RPC.
   int32 outstanding_rpcs_per_channel = 4;
+  // Number of independent client channels to create.
+  // i-th channel will connect to server_target[i % server_targets.size()]
   int32 client_channels = 5;
-  // only for async client:
+  // Only for async client. Number of threads to use to start/manage RPCs.
   int32 async_client_threads = 7;
   RpcType rpc_type = 8;
+  // The requested load for the entire client (aggregated over all the threads).
   LoadParams load_params = 10;
   PayloadConfig payload_config = 11;
+  HistogramParams histogram_params = 12;
 }
 
 message ClientStatus {
@@ -105,6 +117,7 @@ message ClientStatus {
 
 // Request current stats
 message Mark {
+  // if true, the stats will be reset after taking their snapshot.
   bool reset = 1;
 }
 
@@ -118,10 +131,13 @@ message ClientArgs {
 message ServerConfig {
   ServerType server_type = 1;
   SecurityParams security_params = 2;
+  // Host on which to listen.
+  string host = 3;
+  // Port on which to listen. Zero means pick unused port.
   int32 port = 4;
-  // only for async server
+  // Only for async server. Number of threads used to serve the requests.
   int32 async_server_threads = 7;
-  // restrict core usage
+  // restrict core usage, currently unused
   int32 core_limit = 8;
   PayloadConfig payload_config = 9;
 }
@@ -135,6 +151,8 @@ message ServerArgs {
 
 message ServerStatus {
   ServerStats stats = 1;
+  // the port bound by the server
   int32 port = 2;
+  // Number of cores on the server. See gpr_cpu_num_cores.
   int32 cores = 3;
 }
diff --git a/test/proto/benchmarks/services.proto b/test/proto/benchmarks/services.proto
index 4c2cbabdf8710a34abe94c3658c19a15b3c8b8c3..ff295ed97024047088e680e90d08deeeeb656db1 100644
--- a/test/proto/benchmarks/services.proto
+++ b/test/proto/benchmarks/services.proto
@@ -47,9 +47,19 @@ service BenchmarkService {
 }
 
 service WorkerService {
-  // Start server with specified workload
+  // Start server with specified workload.
+  // First request sent specifies the ServerConfig followed by ServerStatus
+  // response. After that, a "Mark" can be sent anytime to request the latest
+  // stats. Closing the stream will initiate shutdown of the test server
+  // and once the shutdown has finished, the OK status is sent to terminate
+  // this RPC.
   rpc RunServer(stream ServerArgs) returns (stream ServerStatus);
 
-  // Start client with specified workload
+  // Start client with specified workload.
+  // First request sent specifies the ClientConfig followed by ClientStatus
+  // response. After that, a "Mark" can be sent anytime to request the latest
+  // stats. Closing the stream will initiate shutdown of the test client
+  // and once the shutdown has finished, the OK status is sent to terminate
+  // this RPC.
   rpc RunClient(stream ClientArgs) returns (stream ClientStatus);
 }
diff --git a/test/proto/benchmarks/stats.proto b/test/proto/benchmarks/stats.proto
index d52144f321497ab462b088ec54b87e68637f1d4d..6b045b31198ff7f4ba12ef0a81c0761d5d70b9f0 100644
--- a/test/proto/benchmarks/stats.proto
+++ b/test/proto/benchmarks/stats.proto
@@ -32,16 +32,24 @@ syntax = "proto3";
 package grpc.testing;
 
 message ServerStats {
-  // wall clock time
+  // wall clock time change in seconds since last reset
   double time_elapsed = 1;
 
-  // user time used by the server process and threads
+  // change in user time (in seconds) used by the server since last reset
   double time_user = 2;
 
-  // server time used by the server process and all threads
+  // change in server time (in seconds) used by the server process and all
+  // threads since last reset
   double time_system = 3;
 }
 
+// Histogram params based on grpc/support/histogram.c
+message HistogramParams {
+  double resolution = 1;  // first bucket is [0, 1 + resolution)
+  double max_possible = 2;  // use enough buckets to allow this value
+}
+
+// Histogram data based on grpc/support/histogram.c
 message HistogramData {
   repeated uint32 bucket = 1;
   double min_seen = 2;
@@ -52,7 +60,10 @@ message HistogramData {
 }
 
 message ClientStats {
+  // Latency histogram. Data points are in nanoseconds.
   HistogramData latencies = 1;
+
+  // See ServerStats for details.
   double time_elapsed = 2;
   double time_user = 3;
   double time_system = 4;
diff --git a/test/proto/metrics.proto b/test/proto/metrics.proto
new file mode 100644
index 0000000000000000000000000000000000000000..14740eb65d457fcf46a4b488399e955dde1b62a3
--- /dev/null
+++ b/test/proto/metrics.proto
@@ -0,0 +1,55 @@
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+syntax = "proto3";
+
+package grpc.testing;
+
+message GaugeResponse {
+  string name = 1;
+  oneof value {
+    int64 long_value = 2;
+    double double_vale = 3;
+    string string_value = 4;
+  }
+}
+
+message GaugeRequest {
+  string name = 1;
+}
+
+message EmptyMessage {}
+
+service MetricsService {
+  rpc GetAllGauges(EmptyMessage) returns (stream GaugeResponse);
+  rpc GetGauge(GaugeRequest) returns (GaugeResponse);
+}
diff --git a/tools/buildgen/plugins/transitive_dependencies.py b/tools/buildgen/plugins/transitive_dependencies.py
new file mode 100644
index 0000000000000000000000000000000000000000..c2d3da3a3b264dd95256fb7c24e2a9a554651d06
--- /dev/null
+++ b/tools/buildgen/plugins/transitive_dependencies.py
@@ -0,0 +1,63 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Buildgen transitive dependencies
+
+This takes the list of libs, node_modules, and targets from our
+yaml dictionary, and adds to each the transitive closure
+of the list of dependencies.
+
+"""
+
+def get_lib(libs, name):
+  return next(lib for lib in libs if lib['name']==name)
+
+def transitive_deps(lib, libs):
+  if 'deps' in lib:
+    # Recursively call transitive_deps on each dependency, and take the union
+    return set.union(set(lib['deps']),
+                     *[set(transitive_deps(get_lib(libs, dep), libs))
+                       for dep in lib['deps']])
+  else:
+    return set()
+
+def mako_plugin(dictionary):
+  """The exported plugin code for transitive_dependencies.
+
+  Each item in libs, node_modules, and targets can have a deps list.
+  We add a transitive_deps property to each with the transitive closure
+  of those dependency lists.
+  """
+  libs = dictionary.get('libs')
+  node_modules = dictionary.get('node_modules')
+  targets = dictionary.get('targets')
+
+  for target_list in (libs, node_modules, targets):
+    for target in target_list:
+      target['transitive_deps'] = transitive_deps(target, libs)
diff --git a/tools/codegen/core/gen_chttp2_stream_lists.py b/tools/codegen/core/gen_chttp2_stream_lists.py
deleted file mode 100644
index b28b04f643122b019e912540f228c8ed20be9eeb..0000000000000000000000000000000000000000
--- a/tools/codegen/core/gen_chttp2_stream_lists.py
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index 5d592c8e0aefdc4957deb9d59217bf34849630c2..f07718515a64010c25eeb267208850fc754ef14e 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC C++"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 0.11.0.0
+PROJECT_NUMBER         = 0.12.0.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index bbd1706fb059f6a03e6e6fdd1b5fc64a26a5433c..11aaa379cec55c10d2c2af3b3bae9cba6e681b24 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC C++"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 0.11.0.0
+PROJECT_NUMBER         = 0.12.0.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core
index beb0128e41a2a847b5c75fb7e121fde23a00de71..e411abf300547e3144ea31bde8c556ad6f37b78b 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC Core"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 0.11.0.0
+PROJECT_NUMBER         = 0.12.0.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 4ce48b4790d4229f2b5feabe39139fd478be07ac..f0ec37b089c48609f113c97a6b847e2e363f7002 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -40,7 +40,7 @@ PROJECT_NAME           = "GRPC Core"
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 0.11.0.0
+PROJECT_NUMBER         = 0.12.0.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
diff --git a/tools/gke/kubernetes_api.py b/tools/gke/kubernetes_api.py
new file mode 100755
index 0000000000000000000000000000000000000000..7dd30153650383a5669e07cb82283f226b7ec968
--- /dev/null
+++ b/tools/gke/kubernetes_api.py
@@ -0,0 +1,216 @@
+#!/usr/bin/env python2.7
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import requests
+import json
+
+_REQUEST_TIMEOUT_SECS = 10
+
+def _make_pod_config(pod_name, image_name, container_port_list, cmd_list,
+                    arg_list):
+  """Creates a string containing the Pod defintion as required by the Kubernetes API"""
+  body = {
+      'kind': 'Pod',
+      'apiVersion': 'v1',
+      'metadata': {
+          'name': pod_name,
+          'labels': {'name': pod_name}
+      },
+      'spec': {
+          'containers': [
+              {
+                  'name': pod_name,
+                  'image': image_name,
+                  'ports': []
+              }
+          ]
+      }
+  }
+  # Populate the 'ports' list
+  for port in container_port_list:
+    port_entry = {'containerPort': port, 'protocol': 'TCP'}
+    body['spec']['containers'][0]['ports'].append(port_entry)
+
+  # Add the 'Command' and 'Args' attributes if they are passed.
+  # Note:
+  #  - 'Command' overrides the ENTRYPOINT in the Docker Image
+  #  - 'Args' override the COMMAND in Docker image (yes, it is confusing!)
+  if len(cmd_list) > 0:
+    body['spec']['containers'][0]['command'] = cmd_list
+  if len(arg_list) > 0:
+    body['spec']['containers'][0]['args'] = arg_list
+  return json.dumps(body)
+
+
+def _make_service_config(service_name, pod_name, service_port_list,
+                        container_port_list, is_headless):
+  """Creates a string containing the Service definition as required by the Kubernetes API.
+
+  NOTE:
+  This creates either a Headless Service or 'LoadBalancer' service depending on
+  the is_headless parameter. For Headless services, there is no 'type' attribute
+  and the 'clusterIP' attribute is set to 'None'. Also, if the service is
+  Headless, Kubernetes creates DNS entries for Pods - i.e creates DNS A-records
+  mapping the service's name to the Pods' IPs
+  """
+  if len(container_port_list) != len(service_port_list):
+    print(
+        'ERROR: container_port_list and service_port_list must be of same size')
+    return ''
+  body = {
+      'kind': 'Service',
+      'apiVersion': 'v1',
+      'metadata': {
+          'name': service_name,
+          'labels': {
+              'name': service_name
+          }
+      },
+      'spec': {
+          'ports': [],
+          'selector': {
+              'name': pod_name
+          }
+      }
+  }
+  # Populate the 'ports' list in the 'spec' section. This maps service ports
+  # (port numbers that are exposed by Kubernetes) to container ports (i.e port
+  # numbers that are exposed by your Docker image)
+  for idx in range(len(container_port_list)):
+    port_entry = {
+        'port': service_port_list[idx],
+        'targetPort': container_port_list[idx],
+        'protocol': 'TCP'
+    }
+    body['spec']['ports'].append(port_entry)
+
+  # Make this either a LoadBalancer service or a headless service depending on
+  # the is_headless parameter
+  if is_headless:
+    body['spec']['clusterIP'] = 'None'
+  else:
+    body['spec']['type'] = 'LoadBalancer'
+  return json.dumps(body)
+
+
+def _print_connection_error(msg):
+  print('ERROR: Connection failed. Did you remember to run Kubenetes proxy on '
+        'localhost (i.e kubectl proxy --port=<proxy_port>) ?. Error: %s' % msg)
+
+def _do_post(post_url, api_name, request_body):
+  """Helper to do HTTP POST.
+
+  Note:
+  1) On success, Kubernetes returns a success code of 201(CREATED) not 200(OK)
+  2) A response code of 509(CONFLICT) is interpreted as a success code (since
+  the error is most likely due to the resource already existing). This makes
+  _do_post() idempotent which is semantically desirable.
+  """
+  is_success = True
+  try:
+    r = requests.post(post_url, data=request_body, timeout=_REQUEST_TIMEOUT_SECS)
+    if r.status_code == requests.codes.conflict:
+      print('WARN: Looks like the resource already exists. Api: %s, url: %s' %
+            (api_name, post_url))
+    elif r.status_code != requests.codes.created:
+      print('ERROR: %s API returned error. HTTP response: (%d) %s' %
+            (api_name, r.status_code, r.text))
+      is_success = False
+  except(requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
+    is_success = False
+    _print_connection_error(str(e))
+  return is_success
+
+
+def _do_delete(del_url, api_name):
+  """Helper to do HTTP DELETE.
+
+  Note: A response code of 404(NOT_FOUND) is treated as success to keep
+  _do_delete() idempotent.
+  """
+  is_success = True
+  try:
+    r = requests.delete(del_url, timeout=_REQUEST_TIMEOUT_SECS)
+    if r.status_code == requests.codes.not_found:
+      print('WARN: The resource does not exist. Api: %s, url: %s' %
+            (api_name, del_url))
+    elif r.status_code != requests.codes.ok:
+      print('ERROR: %s API returned error. HTTP response: %s' %
+            (api_name, r.text))
+      is_success = False
+  except(requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
+    is_success = False
+    _print_connection_error(str(e))
+  return is_success
+
+
+def create_service(kube_host, kube_port, namespace, service_name, pod_name,
+                   service_port_list, container_port_list, is_headless):
+  """Creates either a Headless Service or a LoadBalancer Service depending
+  on the is_headless parameter.
+  """
+  post_url = 'http://%s:%d/api/v1/namespaces/%s/services' % (
+      kube_host, kube_port, namespace)
+  request_body = _make_service_config(service_name, pod_name, service_port_list,
+                                     container_port_list, is_headless)
+  return _do_post(post_url, 'Create Service', request_body)
+
+
+def create_pod(kube_host, kube_port, namespace, pod_name, image_name,
+               container_port_list, cmd_list, arg_list):
+  """Creates a Kubernetes Pod.
+
+  Note that it is generally NOT considered a good practice to directly create
+  Pods. Typically, the recommendation is to create 'Controllers' to create and
+  manage Pods' lifecycle. Currently Kubernetes only supports 'Replication
+  Controller' which creates a configurable number of 'identical Replicas' of
+  Pods and automatically restarts any Pods in case of failures (for eg: Machine
+  failures in Kubernetes). This makes it less flexible for our test use cases
+  where we might want slightly different set of args to each Pod. Hence we
+  directly create Pods and not care much about Kubernetes failures since those
+  are very rare.
+  """
+  post_url = 'http://%s:%d/api/v1/namespaces/%s/pods' % (kube_host, kube_port,
+                                                         namespace)
+  request_body = _make_pod_config(pod_name, image_name, container_port_list,
+                                 cmd_list, arg_list)
+  return _do_post(post_url, 'Create Pod', request_body)
+
+
+def delete_service(kube_host, kube_port, namespace, service_name):
+  del_url = 'http://%s:%d/api/v1/namespaces/%s/services/%s' % (
+      kube_host, kube_port, namespace, service_name)
+  return _do_delete(del_url, 'Delete Service')
+
+
+def delete_pod(kube_host, kube_port, namespace, pod_name):
+  del_url = 'http://%s:%d/api/v1/namespaces/%s/pods/%s' % (kube_host, kube_port,
+                                                           namespace, pod_name)
+  return _do_delete(del_url, 'Delete Pod')
diff --git a/tools/http2_interop/goaway.go b/tools/http2_interop/goaway.go
new file mode 100644
index 0000000000000000000000000000000000000000..289442d615bb3189816b377ef6b49bd92ed0ca18
--- /dev/null
+++ b/tools/http2_interop/goaway.go
@@ -0,0 +1,72 @@
+package http2interop
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+)
+
+type GoAwayFrame struct {
+	Header FrameHeader
+	Reserved
+	StreamID
+	// TODO(carl-mastrangelo): make an enum out of this.
+	Code uint32
+	Data []byte
+}
+
+func (f *GoAwayFrame) GetHeader() *FrameHeader {
+	return &f.Header
+}
+
+func (f *GoAwayFrame) ParsePayload(r io.Reader) error {
+	raw := make([]byte, f.Header.Length)
+	if _, err := io.ReadFull(r, raw); err != nil {
+		return err
+	}
+	return f.UnmarshalPayload(raw)
+}
+
+func (f *GoAwayFrame) UnmarshalPayload(raw []byte) error {
+	if f.Header.Length != len(raw) {
+		return fmt.Errorf("Invalid Payload length %d != %d", f.Header.Length, len(raw))
+	}
+	if f.Header.Length < 8 {
+		return fmt.Errorf("Invalid Payload length %d", f.Header.Length)
+	}
+	*f = GoAwayFrame{
+		Reserved: Reserved(raw[0]>>7 == 1),
+		StreamID: StreamID(binary.BigEndian.Uint32(raw[0:4]) & 0x7fffffff),
+		Code:     binary.BigEndian.Uint32(raw[4:8]),
+		Data:     []byte(string(raw[8:])),
+	}
+
+	return nil
+}
+
+func (f *GoAwayFrame) MarshalPayload() ([]byte, error) {
+	raw := make([]byte, 8, 8+len(f.Data))
+	binary.BigEndian.PutUint32(raw[:4], uint32(f.StreamID))
+	binary.BigEndian.PutUint32(raw[4:8], f.Code)
+	raw = append(raw, f.Data...)
+
+	return raw, nil
+}
+
+func (f *GoAwayFrame) MarshalBinary() ([]byte, error) {
+	payload, err := f.MarshalPayload()
+	if err != nil {
+		return nil, err
+	}
+
+	f.Header.Length = len(payload)
+	f.Header.Type = GoAwayFrameType
+	header, err := f.Header.MarshalBinary()
+	if err != nil {
+		return nil, err
+	}
+
+	header = append(header, payload...)
+
+	return header, nil
+}
diff --git a/tools/http2_interop/http2_interop.test b/tools/http2_interop/http2_interop.test
deleted file mode 100755
index 0700763dc3386b03bbbf19ef4c241702ccf187ad..0000000000000000000000000000000000000000
Binary files a/tools/http2_interop/http2_interop.test and /dev/null differ
diff --git a/tools/http2_interop/http2interop.go b/tools/http2_interop/http2interop.go
index 8585a044e538d6471b615ba40b3490f85ddba35c..bef8b0b656eaf75990d3521e87e9b4f5bd94b8e7 100644
--- a/tools/http2_interop/http2interop.go
+++ b/tools/http2_interop/http2interop.go
@@ -252,6 +252,58 @@ func testTLSApplicationProtocol(ctx *HTTP2InteropCtx) error {
 	return nil
 }
 
+func testTLSBadCipherSuites(ctx *HTTP2InteropCtx) error {
+	config := buildTlsConfig(ctx)
+	// These are the suites that Go supports, but are forbidden by http2.
+	config.CipherSuites = []uint16{
+		tls.TLS_RSA_WITH_RC4_128_SHA,
+		tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+		tls.TLS_RSA_WITH_AES_128_CBC_SHA,
+		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+		tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+		tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+		tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+		tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+	}
+	conn, err := connectWithTls(ctx, config)
+	if err != nil {
+		return err
+	}
+	defer conn.Close()
+	conn.SetDeadline(time.Now().Add(defaultTimeout))
+
+	if err := http2Connect(conn, nil); err != nil {
+		return err
+	}
+
+	for {
+		f, err := parseFrame(conn)
+		if err != nil {
+			return err
+		}
+		if gf, ok := f.(*GoAwayFrame); ok {
+			return fmt.Errorf("Got goaway frame %d", gf.Code)
+		}
+	}
+	return nil
+}
+
+func http2Connect(c net.Conn, sf *SettingsFrame) error {
+	if _, err := c.Write([]byte(Preface)); err != nil {
+		return err
+	}
+	if sf == nil {
+		sf = &SettingsFrame{}
+	}
+	if err := streamFrame(c, sf); err != nil {
+		return err
+	}
+	return nil
+}
+
 func connect(ctx *HTTP2InteropCtx) (net.Conn, error) {
 	var conn net.Conn
 	var err error
diff --git a/tools/http2_interop/http2interop_test.go b/tools/http2_interop/http2interop_test.go
index dc2960048f13e58e3d2a5d79a88d39b2c3834cc1..e3d366f2f2752d8b7248990bfd432c914d958ed2 100644
--- a/tools/http2_interop/http2interop_test.go
+++ b/tools/http2_interop/http2interop_test.go
@@ -3,13 +3,13 @@ package http2interop
 import (
 	"crypto/tls"
 	"crypto/x509"
-	"strings"
 	"flag"
 	"fmt"
 	"io"
 	"io/ioutil"
 	"os"
 	"strconv"
+	"strings"
 	"testing"
 )
 
@@ -17,8 +17,7 @@ var (
 	serverHost = flag.String("server_host", "", "The host to test")
 	serverPort = flag.Int("server_port", 443, "The port to test")
 	useTls     = flag.Bool("use_tls", true, "Should TLS tests be run")
-	// TODO: implement
-	testCase              = flag.String("test_case", "", "What test cases to run")
+	testCase   = flag.String("test_case", "", "What test cases to run (tls, framing)")
 
 	// The rest of these are unused, but present to fulfill the client interface
 	serverHostOverride    = flag.String("server_host_override", "", "Unused")
@@ -70,6 +69,9 @@ func (ctx *HTTP2InteropCtx) Close() error {
 }
 
 func TestShortPreface(t *testing.T) {
+	if *testCase != "framing" {
+		t.SkipNow()
+	}
 	ctx := InteropCtx(t)
 	for i := 0; i < len(Preface)-1; i++ {
 		if err := testShortPreface(ctx, Preface[:i]+"X"); err != io.EOF {
@@ -79,6 +81,9 @@ func TestShortPreface(t *testing.T) {
 }
 
 func TestUnknownFrameType(t *testing.T) {
+	if *testCase != "framing" {
+		t.SkipNow()
+	}
 	ctx := InteropCtx(t)
 	if err := testUnknownFrameType(ctx); err != nil {
 		t.Fatal(err)
@@ -86,33 +91,53 @@ func TestUnknownFrameType(t *testing.T) {
 }
 
 func TestTLSApplicationProtocol(t *testing.T) {
+	if *testCase != "tls" {
+		t.SkipNow()
+	}
 	ctx := InteropCtx(t)
-	err := testTLSApplicationProtocol(ctx); 
+	err := testTLSApplicationProtocol(ctx)
 	matchError(t, err, "EOF")
 }
 
 func TestTLSMaxVersion(t *testing.T) {
+	if *testCase != "tls" {
+		t.SkipNow()
+	}
 	ctx := InteropCtx(t)
-	err := testTLSMaxVersion(ctx, tls.VersionTLS11);
+	err := testTLSMaxVersion(ctx, tls.VersionTLS11)
+	// TODO(carl-mastrangelo): maybe this should be some other error.  If the server picks
+	// the wrong protocol version, thats bad too.
 	matchError(t, err, "EOF", "server selected unsupported protocol")
 }
 
+func TestTLSBadCipherSuites(t *testing.T) {
+	if *testCase != "tls" {
+		t.SkipNow()
+	}
+	ctx := InteropCtx(t)
+	err := testTLSBadCipherSuites(ctx)
+	matchError(t, err, "EOF", "Got goaway frame")
+}
+
 func TestClientPrefaceWithStreamId(t *testing.T) {
+	if *testCase != "framing" {
+		t.SkipNow()
+	}
 	ctx := InteropCtx(t)
 	err := testClientPrefaceWithStreamId(ctx)
 	matchError(t, err, "EOF")
 }
 
-func matchError(t *testing.T, err error, matches  ... string) {
-  if err == nil {
-    t.Fatal("Expected an error")
-  }
-  for _, s := range matches {
-    if strings.Contains(err.Error(), s) {
-      return
-    }
-  }
-  t.Fatalf("Error %v not in %+v", err, matches)
+func matchError(t *testing.T, err error, matches ...string) {
+	if err == nil {
+		t.Fatal("Expected an error")
+	}
+	for _, s := range matches {
+		if strings.Contains(err.Error(), s) {
+			return
+		}
+	}
+	t.Fatalf("Error %v not in %+v", err, matches)
 }
 
 func TestMain(m *testing.M) {
diff --git a/tools/jenkins/run_interop.sh b/tools/jenkins/run_interop.sh
index 5dd477ed77ac2ee927fff38eaaeefc3f8bb7e869..a424aea7fc47641fefd5a39c96d987ea6e569a0a 100755
--- a/tools/jenkins/run_interop.sh
+++ b/tools/jenkins/run_interop.sh
@@ -34,4 +34,4 @@ set -ex
 # Enter the gRPC repo root
 cd $(dirname $0)/../..
 
-tools/run_tests/run_interop_tests.py -l all -s all --cloud_to_prod --cloud_to_prod_auth --use_docker -t -j 12 $@ || true
+tools/run_tests/run_interop_tests.py -l all -s all --cloud_to_prod --cloud_to_prod_auth --use_docker --http2_interop -t -j 12 $@ || true
diff --git a/tools/run_tests/dockerjob.py b/tools/run_tests/dockerjob.py
index 7d64222ba0b53931f57adf0869bc80ee6dd98000..326c4faed95629dbc7236eeec4562e0674e769d9 100755
--- a/tools/run_tests/dockerjob.py
+++ b/tools/run_tests/dockerjob.py
@@ -47,6 +47,7 @@ def random_name(base_name):
 def docker_kill(cid):
   """Kills a docker container. Returns True if successful."""
   return subprocess.call(['docker','kill', str(cid)],
+                         stdin=subprocess.PIPE,
                          stdout=_DEVNULL,
                          stderr=subprocess.STDOUT) == 0
 
@@ -78,6 +79,7 @@ def finish_jobs(jobs):
 def image_exists(image):
   """Returns True if given docker image exists."""
   return subprocess.call(['docker','inspect', image],
+                         stdin=subprocess.PIPE,
                          stdout=_DEVNULL,
                          stderr=subprocess.STDOUT) == 0
 
@@ -88,6 +90,7 @@ def remove_image(image, skip_nonexistent=False, max_retries=10):
     return True
   for attempt in range(0, max_retries):
     if subprocess.call(['docker','rmi', '-f', image],
+                       stdin=subprocess.PIPE,
                        stdout=_DEVNULL,
                        stderr=subprocess.STDOUT) == 0:
       return True
diff --git a/tools/run_tests/port_server.py b/tools/run_tests/port_server.py
index 3b85486ebfe599732f38f1db2756db9b03edc2e4..14e82b601eadbef7062397a2c33c791bff43318c 100755
--- a/tools/run_tests/port_server.py
+++ b/tools/run_tests/port_server.py
@@ -42,7 +42,7 @@ import time
 # increment this number whenever making a change to ensure that
 # the changes are picked up by running CI servers
 # note that all changes must be backwards compatible
-_MY_VERSION = 5
+_MY_VERSION = 7
 
 
 if len(sys.argv) == 2 and sys.argv[1] == 'dump_version':
diff --git a/tools/run_tests/report_utils.py b/tools/run_tests/report_utils.py
index bb9eca42548aee3e877f6e535ff90fec1843fe57..adeb707a0734823c3d2e249418b1775a1993ea86 100644
--- a/tools/run_tests/report_utils.py
+++ b/tools/run_tests/report_utils.py
@@ -29,6 +29,11 @@
 
 """Generate XML and HTML test reports."""
 
+try:
+  from mako.runtime import Context
+  from mako.template import Template
+except (ImportError):
+  pass  # Mako not installed but it is ok. 
 import os
 import string
 import xml.etree.cElementTree as ET
@@ -49,7 +54,7 @@ def _filter_msg(msg, output_format):
     return msg
 
 
-def render_xml_report(resultset, xml_report):
+def render_junit_xml_report(resultset, xml_report):
   """Generate JUnit-like XML report."""
   root = ET.Element('testsuites')
   testsuite = ET.SubElement(root, 'testsuite', id='1', package='grpc', 
@@ -69,147 +74,36 @@ def render_xml_report(resultset, xml_report):
   tree.write(xml_report, encoding='UTF-8')
 
 
-# TODO(adelez): Use mako template.
-def fill_one_test_result(shortname, resultset, html_str):
-  if shortname in resultset:
-    # Because interop tests does not have runs_per_test flag, each test is run
-    # once. So there should only be one element for each result.
-    result = resultset[shortname][0] 
-    if result.state == 'PASSED':
-      html_str = '%s<td bgcolor=\"green\">PASS</td>\n' % html_str
-    else:
-      tooltip = ''
-      if result.returncode > 0 or result.message:
-        if result.returncode > 0:
-          tooltip = 'returncode: %d ' % result.returncode
-        if result.message:
-          escaped_msg = _filter_msg(result.message, 'HTML')
-          tooltip = '%smessage: %s' % (tooltip, escaped_msg)       
-      if result.state == 'FAILED':
-        html_str = '%s<td bgcolor=\"red\">' % html_str
-        if tooltip:  
-          html_str = ('%s<a href=\"#\" data-toggle=\"tooltip\" '
-                      'data-placement=\"auto\" title=\"%s\">FAIL</a></td>\n' % 
-                      (html_str, tooltip))
-        else:
-          html_str = '%sFAIL</td>\n' % html_str
-      elif result.state == 'TIMEOUT':
-        html_str = '%s<td bgcolor=\"yellow\">' % html_str
-        if tooltip:
-          html_str = ('%s<a href=\"#\" data-toggle=\"tooltip\" '
-                      'data-placement=\"auto\" title=\"%s\">TIMEOUT</a></td>\n' 
-                      % (html_str, tooltip))
-        else:
-          html_str = '%sTIMEOUT</td>\n' % html_str
-  else:
-    html_str = '%s<td bgcolor=\"magenta\">Not implemented</td>\n' % html_str
-  
-  return html_str
-
+def render_interop_html_report(
+  client_langs, server_langs, test_cases, auth_test_cases, http2_cases, 
+  resultset, num_failures, cloud_to_prod, http2_interop):
+  """Generate HTML report for interop tests."""
+  html_report_dir = 'reports'
+  template_file = os.path.join(html_report_dir, 'interop_html_report.template')
+  try:
+    mytemplate = Template(filename=template_file, format_exceptions=True)
+  except NameError:
+    print 'Mako template is not installed. Skipping HTML report generation.'
+    return
+  except IOError as e:
+    print 'Failed to find the template %s: %s' % (template_file, e)
+    return
 
-def render_html_report(client_langs, server_langs, test_cases, auth_test_cases,
-                       http2_cases, resultset, num_failures, cloud_to_prod, 
-                       http2_interop):
-  """Generate html report."""
   sorted_test_cases = sorted(test_cases)
   sorted_auth_test_cases = sorted(auth_test_cases)
   sorted_http2_cases = sorted(http2_cases)
   sorted_client_langs = sorted(client_langs)
   sorted_server_langs = sorted(server_langs)
-  html_str = ('<!DOCTYPE html>\n'
-              '<html lang=\"en\">\n'
-              '<head><title>Interop Test Result</title></head>\n'
-              '<body>\n')
-  if num_failures > 1:
-    html_str = (
-        '%s<p><h2><font color=\"red\">%d tests failed!</font></h2></p>\n' % 
-        (html_str, num_failures))
-  elif num_failures:
-    html_str = (
-        '%s<p><h2><font color=\"red\">%d test failed!</font></h2></p>\n' % 
-        (html_str, num_failures))
-  else:
-    html_str = (
-        '%s<p><h2><font color=\"green\">All tests passed!</font></h2></p>\n' % 
-        html_str)
-  if cloud_to_prod:
-    # Each column header is the client language.
-    html_str = ('%s<h2>Cloud to Prod</h2>\n' 
-                '<table style=\"width:100%%\" border=\"1\">\n'
-                '<tr bgcolor=\"#00BFFF\">\n'
-                '<th>Client languages &#9658;</th>\n') % html_str
-    for client_lang in sorted_client_langs:
-      html_str = '%s<th>%s\n' % (html_str, client_lang)
-    html_str = '%s</tr>\n' % html_str
-    for test_case in sorted_test_cases + sorted_auth_test_cases:
-      html_str = '%s<tr><td><b>%s</b></td>\n' % (html_str, test_case)
-      for client_lang in sorted_client_langs:
-        if not test_case in sorted_auth_test_cases:
-          shortname = 'cloud_to_prod:%s:%s' % (client_lang, test_case)
-        else:
-          shortname = 'cloud_to_prod_auth:%s:%s' % (client_lang, test_case)
-        html_str = fill_one_test_result(shortname, resultset, html_str)
-      html_str = '%s</tr>\n' % html_str 
-    html_str = '%s</table>\n' % html_str
-  if http2_interop:
-    # Each column header is the server language.
-    html_str = ('%s<h2>HTTP/2 Interop</h2>\n' 
-                '<table style=\"width:100%%\" border=\"1\">\n'
-                '<tr bgcolor=\"#00BFFF\">\n'
-                '<th>Servers &#9658;<br/>'
-                'Test Cases &#9660;</th>\n') % html_str
-    for server_lang in sorted_server_langs:
-      html_str = '%s<th>%s\n' % (html_str, server_lang)
-    if cloud_to_prod:
-      html_str = '%s<th>%s\n' % (html_str, "prod")
-    html_str = '%s</tr>\n' % html_str
-    for test_case in sorted_http2_cases:
-      html_str = '%s<tr><td><b>%s</b></td>\n' % (html_str, test_case)
-      # Fill up the cells with test result.
-      for server_lang in sorted_server_langs:
-        shortname = 'cloud_to_cloud:%s:%s_server:%s' % (
-            "http2", server_lang, test_case)
-        html_str = fill_one_test_result(shortname, resultset, html_str)
-      if cloud_to_prod:
-        shortname = 'cloud_to_prod:%s:%s' % ("http2", test_case)
-        html_str = fill_one_test_result(shortname, resultset, html_str)
-      html_str = '%s</tr>\n' % html_str
-    html_str = '%s</table>\n' % html_str
-  if server_langs:
-    for test_case in sorted_test_cases:
-      # Each column header is the client language.
-      html_str = ('%s<h2>%s</h2>\n' 
-                  '<table style=\"width:100%%\" border=\"1\">\n'
-                  '<tr bgcolor=\"#00BFFF\">\n'
-                  '<th>Client languages &#9658;<br/>'
-                  'Server languages &#9660;</th>\n') % (html_str, test_case)
-      for client_lang in sorted_client_langs:
-        html_str = '%s<th>%s\n' % (html_str, client_lang)
-      html_str = '%s</tr>\n' % html_str
-      # Each row head is the server language.
-      for server_lang in sorted_server_langs:
-        html_str = '%s<tr><td><b>%s</b></td>\n' % (html_str, server_lang)
-        # Fill up the cells with test result.
-        for client_lang in sorted_client_langs:
-          shortname = 'cloud_to_cloud:%s:%s_server:%s' % (
-              client_lang, server_lang, test_case)
-          html_str = fill_one_test_result(shortname, resultset, html_str)
-        html_str = '%s</tr>\n' % html_str
-      html_str = '%s</table>\n' % html_str
 
-  html_str = ('%s\n'
-              '<script>\n'
-              '$(document).ready(function(){'
-              '$(\'[data-toggle=\"tooltip\"]\').tooltip();\n'   
-              '});\n'
-              '</script>\n'
-              '</body>\n'
-              '</html>') % html_str  
-  
-  # Write to reports/index.html as set up in Jenkins plugin.
-  html_report_dir = 'reports'
-  if not os.path.exists(html_report_dir):
-    os.mkdir(html_report_dir)
+  args = {'client_langs': sorted_client_langs, 
+          'server_langs': sorted_server_langs,
+          'test_cases': sorted_test_cases,
+          'auth_test_cases': sorted_auth_test_cases,
+          'http2_cases': sorted_http2_cases,
+          'resultset': resultset,
+          'num_failures': num_failures,
+          'cloud_to_prod': cloud_to_prod,
+          'http2_interop': http2_interop}
   html_file_path = os.path.join(html_report_dir, 'index.html')
-  with open(html_file_path, 'w') as f:
-    f.write(html_str)
+  with open(html_file_path, 'w') as output_file:
+    mytemplate.render_context(Context(output_file, **args))
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 1686942b0ae9eb2ce467922fa75c7027ed60ed14..5435a1d02fcb7d0c189f9748e68a927b1605f11c 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -37,7 +37,6 @@ import jobset
 import multiprocessing
 import os
 import report_utils
-import subprocess
 import sys
 import tempfile
 import time
@@ -170,7 +169,7 @@ class Http2Client:
     self.safename = str(self)
 
   def client_args(self):
-    return ['tools/http2_interop/http2_interop.test']
+    return ['tools/http2_interop/http2_interop.test', '-test.v']
 
   def cloud_to_prod_env(self):
     return {}
@@ -306,7 +305,7 @@ _TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong',
 _AUTH_TEST_CASES = ['compute_engine_creds', 'jwt_token_creds',
                     'oauth2_auth_token', 'per_rpc_creds']
 
-_HTTP2_TEST_CASES = ["tls"]
+_HTTP2_TEST_CASES = ["tls", "framing"]
 
 def docker_run_cmdline(cmdline, image, docker_args=[], cwd=None, environ=None):
   """Wraps given cmdline array to create 'docker run' cmdline from it."""
@@ -624,7 +623,9 @@ try:
                                            docker_image=docker_images.get(str(language)))
           jobs.append(test_job)
           
-    if args.http2_interop:
+    # TODO(carl-mastrangelo): Currently prod TLS terminators aren't spec compliant. Reenable
+    # this once a better solution is in place.
+    if args.http2_interop and False:
       for test_case in _HTTP2_TEST_CASES:
         test_job = cloud_to_prod_jobspec(http2Interop, test_case,
                                          docker_image=docker_images.get(str(http2Interop)))
@@ -660,6 +661,9 @@ try:
           
     if args.http2_interop:
       for test_case in _HTTP2_TEST_CASES:
+        if server_name == "go":
+          # TODO(carl-mastrangelo): Reenable after https://github.com/grpc/grpc-go/issues/434
+          continue 
         test_job = cloud_to_cloud_jobspec(http2Interop,
                                           test_case,
                                           server_name,
@@ -681,9 +685,9 @@ try:
   else:
     jobset.message('SUCCESS', 'All tests passed', do_newline=True)
 
-  report_utils.render_xml_report(resultset, 'report.xml')
+  report_utils.render_junit_xml_report(resultset, 'report.xml')
   
-  report_utils.render_html_report(
+  report_utils.render_interop_html_report(
       set([str(l) for l in languages]), servers, _TEST_CASES, _AUTH_TEST_CASES, 
       _HTTP2_TEST_CASES, resultset, num_failures,
       args.cloud_to_prod_auth or args.cloud_to_prod, args.http2_interop)
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 85c73d6fbd20eb9dca23061d3227e8d2c3c5523c..2d12adebbb60903f4a991763705d35daa0b2ebf1 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -485,10 +485,10 @@ _CONFIGS = {
     'msan': SimpleConfig('msan', timeout_multiplier=1.5),
     'ubsan': SimpleConfig('ubsan'),
     'asan': SimpleConfig('asan', timeout_multiplier=1.5, environ={
-        'ASAN_OPTIONS': 'detect_leaks=1:color=always:suppressions=tools/tsan_suppressions.txt',
+        'ASAN_OPTIONS': 'detect_leaks=1:color=always',
         'LSAN_OPTIONS': 'report_objects=1'}),
     'asan-noleaks': SimpleConfig('asan', environ={
-        'ASAN_OPTIONS': 'detect_leaks=0:color=always:suppressions=tools/tsan_suppressions.txt'}),
+        'ASAN_OPTIONS': 'detect_leaks=0:color=always'}),
     'gcov': SimpleConfig('gcov'),
     'memcheck': ValgrindConfig('valgrind', 'memcheck', ['--leak-check=full']),
     'helgrind': ValgrindConfig('dbg', 'helgrind')
@@ -624,10 +624,15 @@ build_configs = set(cfg.build_config for cfg in run_configs)
 if args.travis:
   _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
 
-languages = set(_LANGUAGES[l]
-                for l in itertools.chain.from_iterable(
-                      _LANGUAGES.iterkeys() if x == 'all' else [x]
-                      for x in args.language))
+if 'all' in args.language:
+  lang_list = _LANGUAGES.keys()  
+else:
+  lang_list = args.language
+# We don't support code coverage on ObjC
+if 'gcov' in args.config and 'objc' in lang_list:
+  lang_list.remove('objc')
+
+languages = set(_LANGUAGES[l] for l in lang_list)
 
 if len(build_configs) > 1:
   for language in languages:
@@ -749,7 +754,8 @@ def _start_port_server(port_server_port):
     running = False
   if running:
     current_version = int(subprocess.check_output(
-        [sys.executable, 'tools/run_tests/port_server.py', 'dump_version']))
+        [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
+         'dump_version']))
     print 'my port server is version %d' % current_version
     running = (version >= current_version)
     if not running:
@@ -760,13 +766,18 @@ def _start_port_server(port_server_port):
     fd, logfile = tempfile.mkstemp()
     os.close(fd)
     print 'starting port_server, with log file %s' % logfile
-    args = [sys.executable, 'tools/run_tests/port_server.py', '-p', '%d' % port_server_port, '-l', logfile]
+    args = [sys.executable, os.path.abspath('tools/run_tests/port_server.py'),
+            '-p', '%d' % port_server_port, '-l', logfile]
     env = dict(os.environ)
     env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
     if platform.system() == 'Windows':
+      # Working directory of port server needs to be outside of Jenkins
+      # workspace to prevent file lock issues.
+      tempdir = tempfile.mkdtemp()
       port_server = subprocess.Popen(
           args,
           env=env,
+          cwd=tempdir,
           creationflags = 0x00000008, # detached process
           close_fds=True)
     else:
@@ -834,6 +845,7 @@ def _calculate_num_runs_failures(list_of_results):
       num_failures += jobresult.num_failures
   return num_runs, num_failures
 
+
 def _build_and_run(
     check_cancelled, newline_on_success, cache, xml_report=None):
   """Do one pass of building & running tests."""
@@ -896,7 +908,7 @@ def _build_and_run(
     for antagonist in antagonists:
       antagonist.kill()
     if xml_report and resultset:
-      report_utils.render_xml_report(resultset, xml_report)
+      report_utils.render_junit_xml_report(resultset, xml_report)
 
   number_failures, _ = jobset.run(
       post_tests_steps, maxjobs=1, stop_on_failure=True,
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index d3493bbe2c43d4f6e88c53b23667c394211a78e5..577cf4a19f0b35793cf357057f45747bdefaf2f8 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -1398,6 +1398,25 @@
       "test/cpp/interop/interop_test.cc"
     ]
   }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_config"
+    ], 
+    "headers": [
+      "test/cpp/util/metrics_server.h", 
+      "test/proto/metrics.grpc.pb.h", 
+      "test/proto/metrics.pb.h"
+    ], 
+    "language": "c++", 
+    "name": "metrics_client", 
+    "src": [
+      "test/cpp/interop/metrics_client.cc", 
+      "test/cpp/util/metrics_server.h"
+    ]
+  }, 
   {
     "deps": [
       "gpr", 
@@ -1683,10 +1702,13 @@
       "test/cpp/interop/client_helper.h", 
       "test/cpp/interop/interop_client.h", 
       "test/cpp/interop/stress_interop_client.h", 
+      "test/cpp/util/metrics_server.h", 
       "test/proto/empty.grpc.pb.h", 
       "test/proto/empty.pb.h", 
       "test/proto/messages.grpc.pb.h", 
       "test/proto/messages.pb.h", 
+      "test/proto/metrics.grpc.pb.h", 
+      "test/proto/metrics.pb.h", 
       "test/proto/test.grpc.pb.h", 
       "test/proto/test.pb.h"
     ], 
@@ -1698,7 +1720,9 @@
       "test/cpp/interop/interop_client.h", 
       "test/cpp/interop/stress_interop_client.cc", 
       "test/cpp/interop/stress_interop_client.h", 
-      "test/cpp/interop/stress_test.cc"
+      "test/cpp/interop/stress_test.cc", 
+      "test/cpp/util/metrics_server.cc", 
+      "test/cpp/util/metrics_server.h"
     ]
   }, 
   {
@@ -2023,6 +2047,21 @@
     "name": "h2_compress_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_compress", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_compress_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -2548,6 +2587,21 @@
     "name": "h2_fakesec_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_fakesec", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_fakesec_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -3073,6 +3127,21 @@
     "name": "h2_full_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_full", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_full_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -3598,6 +3667,21 @@
     "name": "h2_full+poll_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_full+poll", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_full+poll_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -4123,6 +4207,21 @@
     "name": "h2_oauth2_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_oauth2", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_oauth2_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -5068,6 +5167,21 @@
     "name": "h2_sockpair_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_sockpair", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_sockpair_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -5998,6 +6112,21 @@
     "name": "h2_sockpair_1byte_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_sockpair_1byte", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -6508,6 +6637,21 @@
     "name": "h2_ssl_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_ssl", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_ssl_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -7033,6 +7177,21 @@
     "name": "h2_ssl+poll_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_ssl+poll", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_ssl+poll_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -8023,6 +8182,21 @@
     "name": "h2_uchannel_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_uchannel", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_uchannel_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -8533,6 +8707,21 @@
     "name": "h2_uds_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_uds", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_uds_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -9043,6 +9232,21 @@
     "name": "h2_uds+poll_high_initial_seqno_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_certs", 
+      "end2end_fixture_h2_uds+poll", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_uds+poll_hpack_size_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_certs", 
@@ -9537,6 +9741,20 @@
     "name": "h2_compress_high_initial_seqno_nosec_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_fixture_h2_compress", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_compress_hpack_size_nosec_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_fixture_h2_compress", 
@@ -10013,6 +10231,20 @@
     "name": "h2_full_high_initial_seqno_nosec_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_fixture_h2_full", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_full_hpack_size_nosec_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_fixture_h2_full", 
@@ -10489,6 +10721,20 @@
     "name": "h2_full+poll_high_initial_seqno_nosec_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_fixture_h2_full+poll", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_full+poll_hpack_size_nosec_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_fixture_h2_full+poll", 
@@ -11343,6 +11589,20 @@
     "name": "h2_sockpair_high_initial_seqno_nosec_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_fixture_h2_sockpair", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_sockpair_hpack_size_nosec_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_fixture_h2_sockpair", 
@@ -12183,6 +12443,20 @@
     "name": "h2_sockpair_1byte_high_initial_seqno_nosec_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_fixture_h2_sockpair_1byte", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_hpack_size_nosec_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_fixture_h2_sockpair_1byte", 
@@ -12645,6 +12919,20 @@
     "name": "h2_uchannel_high_initial_seqno_nosec_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_fixture_h2_uchannel", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_uchannel_hpack_size_nosec_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_fixture_h2_uchannel", 
@@ -13107,6 +13395,20 @@
     "name": "h2_uds_high_initial_seqno_nosec_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_fixture_h2_uds", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_uds_hpack_size_nosec_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_fixture_h2_uds", 
@@ -13569,6 +13871,20 @@
     "name": "h2_uds+poll_high_initial_seqno_nosec_test", 
     "src": []
   }, 
+  {
+    "deps": [
+      "end2end_fixture_h2_uds+poll", 
+      "end2end_test_hpack_size", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "h2_uds+poll_hpack_size_nosec_test", 
+    "src": []
+  }, 
   {
     "deps": [
       "end2end_fixture_h2_uds+poll", 
@@ -16021,6 +16337,25 @@
       "test/core/end2end/tests/high_initial_seqno.c"
     ]
   }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [
+      "test/core/end2end/end2end_tests.h", 
+      "test/core/end2end/tests/cancel_test_helpers.h"
+    ], 
+    "language": "c", 
+    "name": "end2end_test_hpack_size", 
+    "src": [
+      "test/core/end2end/end2end_tests.h", 
+      "test/core/end2end/tests/cancel_test_helpers.h", 
+      "test/core/end2end/tests/hpack_size.c"
+    ]
+  }, 
   {
     "deps": [
       "gpr", 
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index 00ef157e98e124583a3c286964f38e24b72889c3..029fc5ec7198fea783d5db741978433df8150b60 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -1955,6 +1955,24 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -2568,6 +2586,23 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fakesec_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -3180,6 +3215,24 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -3708,6 +3761,18 @@
       "linux"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+poll_hpack_size_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux"
@@ -4213,6 +4278,23 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -5284,6 +5366,23 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -6369,6 +6468,23 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -6964,6 +7080,24 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -7492,6 +7626,18 @@
       "linux"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl+poll_hpack_size_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux"
@@ -8541,6 +8687,24 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uchannel_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -9121,6 +9285,22 @@
       "posix"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_hpack_size_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -9601,6 +9781,18 @@
       "linux"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds+poll_hpack_size_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux"
@@ -10105,6 +10297,24 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_hpack_size_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -10717,6 +10927,24 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_hpack_size_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -11233,6 +11461,18 @@
       "linux"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+poll_hpack_size_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux"
@@ -12180,6 +12420,23 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_hpack_size_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -13230,6 +13487,23 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_sockpair_1byte_hpack_size_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -13807,6 +14081,24 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uchannel_hpack_size_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -14371,6 +14663,22 @@
       "posix"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_hpack_size_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 
@@ -14839,6 +15147,18 @@
       "linux"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds+poll_hpack_size_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux"
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 48ebdf43b05321bea75a6b4f400a980374818889..d902ba8ff7bebd5dc6d666df91045a731390039f 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -394,6 +394,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "end2end_test_high_initial_s
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "end2end_test_hpack_size", "vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj", "{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}"
+	ProjectSection(myProperties) = preProject
+        	lib = "True"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "end2end_test_invoke_large_request", "vcxproj\test\end2end_test_invoke_large_request\end2end_test_invoke_large_request.vcxproj", "{30861F4C-E783-96E7-DB51-FD85757347C0}"
 	ProjectSection(myProperties) = preProject
         	lib = "True"
@@ -1506,6 +1517,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_compress_high_initial_se
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_compress_hpack_size_test", "vcxproj\test\h2_compress_hpack_size_test\h2_compress_hpack_size_test.vcxproj", "{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{C5D3C9A9-C0D2-CBAD-B433-710C5E89AE31} = {C5D3C9A9-C0D2-CBAD-B433-710C5E89AE31}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{80EA2691-C037-6DD3-D3AB-21510BF0E64B} = {80EA2691-C037-6DD3-D3AB-21510BF0E64B}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_compress_invoke_large_request_test", "vcxproj\test\h2_compress_invoke_large_request_test\h2_compress_invoke_large_request_test.vcxproj", "{FE9E76C0-74CB-5085-6CE6-862E49037F0B}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1996,6 +2021,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_fakesec_high_initial_seq
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_fakesec_hpack_size_test", "vcxproj\test\h2_fakesec_hpack_size_test\h2_fakesec_hpack_size_test.vcxproj", "{5CDFA7CB-09E1-E01E-E21D-7446146478CC}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{096ABF91-FEC8-9AC9-B877-C683BFD51984} = {096ABF91-FEC8-9AC9-B877-C683BFD51984}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{80EA2691-C037-6DD3-D3AB-21510BF0E64B} = {80EA2691-C037-6DD3-D3AB-21510BF0E64B}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_fakesec_invoke_large_request_test", "vcxproj\test\h2_fakesec_invoke_large_request_test\h2_fakesec_invoke_large_request_test.vcxproj", "{93980DE4-8935-C0F5-86F8-22B3F0811121}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -2486,6 +2525,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_full_high_initial_seqno_
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_full_hpack_size_test", "vcxproj\test\h2_full_hpack_size_test\h2_full_hpack_size_test.vcxproj", "{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{882B2933-F340-7027-7090-28CEAE9F1BE6} = {882B2933-F340-7027-7090-28CEAE9F1BE6}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{80EA2691-C037-6DD3-D3AB-21510BF0E64B} = {80EA2691-C037-6DD3-D3AB-21510BF0E64B}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_full_invoke_large_request_test", "vcxproj\test\h2_full_invoke_large_request_test\h2_full_invoke_large_request_test.vcxproj", "{F97198F5-D5EC-E06B-C51F-1BF7644D7422}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -2976,6 +3029,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_oauth2_high_initial_seqn
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_oauth2_hpack_size_test", "vcxproj\test\h2_oauth2_hpack_size_test\h2_oauth2_hpack_size_test.vcxproj", "{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{DDFE4EB8-CCD3-DA3F-461A-10F1B94D26AF} = {DDFE4EB8-CCD3-DA3F-461A-10F1B94D26AF}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{80EA2691-C037-6DD3-D3AB-21510BF0E64B} = {80EA2691-C037-6DD3-D3AB-21510BF0E64B}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_oauth2_invoke_large_request_test", "vcxproj\test\h2_oauth2_invoke_large_request_test\h2_oauth2_invoke_large_request_test.vcxproj", "{945F52A3-91ED-5891-9D11-D07A19E4FEA2}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -3858,6 +3925,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_high_initial_se
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_hpack_size_test", "vcxproj\test\h2_sockpair_hpack_size_test\h2_sockpair_hpack_size_test.vcxproj", "{E96735FF-B1CF-51D2-1923-53292AF72C4E}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{67A1675D-FF50-3B78-2706-155D69ADC290} = {67A1675D-FF50-3B78-2706-155D69ADC290}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{80EA2691-C037-6DD3-D3AB-21510BF0E64B} = {80EA2691-C037-6DD3-D3AB-21510BF0E64B}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_invoke_large_request_test", "vcxproj\test\h2_sockpair_invoke_large_request_test\h2_sockpair_invoke_large_request_test.vcxproj", "{1A1AA28B-D635-F4BD-DFFA-096D2E4BA9BF}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -4726,6 +4807,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_1byte_high_init
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_1byte_hpack_size_test", "vcxproj\test\h2_sockpair_1byte_hpack_size_test\h2_sockpair_1byte_hpack_size_test.vcxproj", "{0B07D219-39A5-729B-EB0F-8B81E562D808}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{B0F4BF34-3C82-EB67-990E-959CDDBEB734} = {B0F4BF34-3C82-EB67-990E-959CDDBEB734}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{80EA2691-C037-6DD3-D3AB-21510BF0E64B} = {80EA2691-C037-6DD3-D3AB-21510BF0E64B}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_1byte_invoke_large_request_test", "vcxproj\test\h2_sockpair_1byte_invoke_large_request_test\h2_sockpair_1byte_invoke_large_request_test.vcxproj", "{45EED825-B3C0-63AE-43FE-CFA8DD3164EC}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -5202,6 +5297,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_ssl_high_initial_seqno_t
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_ssl_hpack_size_test", "vcxproj\test\h2_ssl_hpack_size_test\h2_ssl_hpack_size_test.vcxproj", "{856DAD36-A161-9876-9548-48D06BFA35C1}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{207BE5BC-25D7-1D2A-C76E-279DB66A1205} = {207BE5BC-25D7-1D2A-C76E-279DB66A1205}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{80EA2691-C037-6DD3-D3AB-21510BF0E64B} = {80EA2691-C037-6DD3-D3AB-21510BF0E64B}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_ssl_invoke_large_request_test", "vcxproj\test\h2_ssl_invoke_large_request_test\h2_ssl_invoke_large_request_test.vcxproj", "{CB6E0DFE-7AA8-5F3A-431E-5D769E9339F7}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -6126,6 +6235,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_uchannel_high_initial_se
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_uchannel_hpack_size_test", "vcxproj\test\h2_uchannel_hpack_size_test\h2_uchannel_hpack_size_test.vcxproj", "{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{CE17F95F-4FD3-41C3-E1B9-9B85F1FE7D4A} = {CE17F95F-4FD3-41C3-E1B9-9B85F1FE7D4A}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{80EA2691-C037-6DD3-D3AB-21510BF0E64B} = {80EA2691-C037-6DD3-D3AB-21510BF0E64B}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_uchannel_invoke_large_request_test", "vcxproj\test\h2_uchannel_invoke_large_request_test\h2_uchannel_invoke_large_request_test.vcxproj", "{7B5AE7B2-6D7E-D97F-A6A4-721C7446171F}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -6586,6 +6709,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_compress_high_initial_se
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_compress_hpack_size_nosec_test", "vcxproj\test\h2_compress_hpack_size_nosec_test\h2_compress_hpack_size_nosec_test.vcxproj", "{5A641212-7C59-E552-0ED6-F05F710DD4F5}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{C5D3C9A9-C0D2-CBAD-B433-710C5E89AE31} = {C5D3C9A9-C0D2-CBAD-B433-710C5E89AE31}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_compress_invoke_large_request_nosec_test", "vcxproj\test\h2_compress_invoke_large_request_nosec_test\h2_compress_invoke_large_request_nosec_test.vcxproj", "{C3A6661F-806B-BDE6-AF91-032175B443F8}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -7028,6 +7164,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_full_high_initial_seqno_
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_full_hpack_size_nosec_test", "vcxproj\test\h2_full_hpack_size_nosec_test\h2_full_hpack_size_nosec_test.vcxproj", "{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{882B2933-F340-7027-7090-28CEAE9F1BE6} = {882B2933-F340-7027-7090-28CEAE9F1BE6}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_full_invoke_large_request_nosec_test", "vcxproj\test\h2_full_invoke_large_request_nosec_test\h2_full_invoke_large_request_nosec_test.vcxproj", "{96C59CF1-6E80-B88D-D99C-0AA4C32F6562}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -7821,6 +7970,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_high_initial_se
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_hpack_size_nosec_test", "vcxproj\test\h2_sockpair_hpack_size_nosec_test\h2_sockpair_hpack_size_nosec_test.vcxproj", "{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{67A1675D-FF50-3B78-2706-155D69ADC290} = {67A1675D-FF50-3B78-2706-155D69ADC290}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_invoke_large_request_nosec_test", "vcxproj\test\h2_sockpair_invoke_large_request_nosec_test\h2_sockpair_invoke_large_request_nosec_test.vcxproj", "{8BF0F1D5-3CF2-DFFD-D74D-E2D7D06A65AC}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -8601,6 +8763,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_1byte_high_init
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_1byte_hpack_size_nosec_test", "vcxproj\test\h2_sockpair_1byte_hpack_size_nosec_test\h2_sockpair_1byte_hpack_size_nosec_test.vcxproj", "{93AF9D45-51B5-A902-4537-709FE4ED9830}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{B0F4BF34-3C82-EB67-990E-959CDDBEB734} = {B0F4BF34-3C82-EB67-990E-959CDDBEB734}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_sockpair_1byte_invoke_large_request_nosec_test", "vcxproj\test\h2_sockpair_1byte_invoke_large_request_nosec_test\h2_sockpair_1byte_invoke_large_request_nosec_test.vcxproj", "{0733C2AA-D898-7145-3F2E-6304DC428C5F}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -9030,6 +9205,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_uchannel_high_initial_se
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_uchannel_hpack_size_nosec_test", "vcxproj\test\h2_uchannel_hpack_size_nosec_test\h2_uchannel_hpack_size_nosec_test.vcxproj", "{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{CE17F95F-4FD3-41C3-E1B9-9B85F1FE7D4A} = {CE17F95F-4FD3-41C3-E1B9-9B85F1FE7D4A}
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5} = {22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}
+		{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
+		{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "h2_uchannel_invoke_large_request_nosec_test", "vcxproj\test\h2_uchannel_invoke_large_request_nosec_test\h2_uchannel_invoke_large_request_nosec_test.vcxproj", "{0EC09350-0FB9-0208-000E-1B6C534B234C}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -9892,6 +10080,22 @@ Global
 		{C3647908-B80D-F566-5659-3E98B09D83F9}.Release-DLL|Win32.Build.0 = Release|Win32
 		{C3647908-B80D-F566-5659-3E98B09D83F9}.Release-DLL|x64.ActiveCfg = Release|x64
 		{C3647908-B80D-F566-5659-3E98B09D83F9}.Release-DLL|x64.Build.0 = Release|x64
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Debug|Win32.ActiveCfg = Debug|Win32
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Debug|x64.ActiveCfg = Debug|x64
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Release|Win32.ActiveCfg = Release|Win32
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Release|x64.ActiveCfg = Release|x64
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Debug|Win32.Build.0 = Debug|Win32
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Debug|x64.Build.0 = Debug|x64
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Release|Win32.Build.0 = Release|Win32
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Release|x64.Build.0 = Release|x64
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Debug-DLL|x64.Build.0 = Debug|x64
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Release-DLL|Win32.Build.0 = Release|Win32
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Release-DLL|x64.ActiveCfg = Release|x64
+		{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}.Release-DLL|x64.Build.0 = Release|x64
 		{30861F4C-E783-96E7-DB51-FD85757347C0}.Debug|Win32.ActiveCfg = Debug|Win32
 		{30861F4C-E783-96E7-DB51-FD85757347C0}.Debug|x64.ActiveCfg = Debug|x64
 		{30861F4C-E783-96E7-DB51-FD85757347C0}.Release|Win32.ActiveCfg = Release|Win32
@@ -11508,6 +11712,22 @@ Global
 		{1B8B71B0-ED48-43BF-0553-092CF96A330B}.Release-DLL|Win32.Build.0 = Release|Win32
 		{1B8B71B0-ED48-43BF-0553-092CF96A330B}.Release-DLL|x64.ActiveCfg = Release|x64
 		{1B8B71B0-ED48-43BF-0553-092CF96A330B}.Release-DLL|x64.Build.0 = Release|x64
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Debug|x64.ActiveCfg = Debug|x64
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Release|Win32.ActiveCfg = Release|Win32
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Release|x64.ActiveCfg = Release|x64
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Debug|Win32.Build.0 = Debug|Win32
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Debug|x64.Build.0 = Debug|x64
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Release|Win32.Build.0 = Release|Win32
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Release|x64.Build.0 = Release|x64
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Debug-DLL|x64.Build.0 = Debug|x64
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Release-DLL|Win32.Build.0 = Release|Win32
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Release-DLL|x64.ActiveCfg = Release|x64
+		{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}.Release-DLL|x64.Build.0 = Release|x64
 		{FE9E76C0-74CB-5085-6CE6-862E49037F0B}.Debug|Win32.ActiveCfg = Debug|Win32
 		{FE9E76C0-74CB-5085-6CE6-862E49037F0B}.Debug|x64.ActiveCfg = Debug|x64
 		{FE9E76C0-74CB-5085-6CE6-862E49037F0B}.Release|Win32.ActiveCfg = Release|Win32
@@ -12068,6 +12288,22 @@ Global
 		{65265C4A-46B8-F54C-96AB-10A292FE851F}.Release-DLL|Win32.Build.0 = Release|Win32
 		{65265C4A-46B8-F54C-96AB-10A292FE851F}.Release-DLL|x64.ActiveCfg = Release|x64
 		{65265C4A-46B8-F54C-96AB-10A292FE851F}.Release-DLL|x64.Build.0 = Release|x64
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Debug|Win32.ActiveCfg = Debug|Win32
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Debug|x64.ActiveCfg = Debug|x64
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Release|Win32.ActiveCfg = Release|Win32
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Release|x64.ActiveCfg = Release|x64
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Debug|Win32.Build.0 = Debug|Win32
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Debug|x64.Build.0 = Debug|x64
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Release|Win32.Build.0 = Release|Win32
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Release|x64.Build.0 = Release|x64
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Debug-DLL|x64.Build.0 = Debug|x64
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Release-DLL|Win32.Build.0 = Release|Win32
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Release-DLL|x64.ActiveCfg = Release|x64
+		{5CDFA7CB-09E1-E01E-E21D-7446146478CC}.Release-DLL|x64.Build.0 = Release|x64
 		{93980DE4-8935-C0F5-86F8-22B3F0811121}.Debug|Win32.ActiveCfg = Debug|Win32
 		{93980DE4-8935-C0F5-86F8-22B3F0811121}.Debug|x64.ActiveCfg = Debug|x64
 		{93980DE4-8935-C0F5-86F8-22B3F0811121}.Release|Win32.ActiveCfg = Release|Win32
@@ -12628,6 +12864,22 @@ Global
 		{87CE6537-F5DC-4AF1-6206-D9C31058226D}.Release-DLL|Win32.Build.0 = Release|Win32
 		{87CE6537-F5DC-4AF1-6206-D9C31058226D}.Release-DLL|x64.ActiveCfg = Release|x64
 		{87CE6537-F5DC-4AF1-6206-D9C31058226D}.Release-DLL|x64.Build.0 = Release|x64
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Debug|x64.ActiveCfg = Debug|x64
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Release|Win32.ActiveCfg = Release|Win32
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Release|x64.ActiveCfg = Release|x64
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Debug|Win32.Build.0 = Debug|Win32
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Debug|x64.Build.0 = Debug|x64
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Release|Win32.Build.0 = Release|Win32
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Release|x64.Build.0 = Release|x64
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Debug-DLL|x64.Build.0 = Debug|x64
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Release-DLL|Win32.Build.0 = Release|Win32
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Release-DLL|x64.ActiveCfg = Release|x64
+		{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}.Release-DLL|x64.Build.0 = Release|x64
 		{F97198F5-D5EC-E06B-C51F-1BF7644D7422}.Debug|Win32.ActiveCfg = Debug|Win32
 		{F97198F5-D5EC-E06B-C51F-1BF7644D7422}.Debug|x64.ActiveCfg = Debug|x64
 		{F97198F5-D5EC-E06B-C51F-1BF7644D7422}.Release|Win32.ActiveCfg = Release|Win32
@@ -13188,6 +13440,22 @@ Global
 		{7E1DDE0D-E68B-BF0B-2EE7-AAFE5C9CCD58}.Release-DLL|Win32.Build.0 = Release|Win32
 		{7E1DDE0D-E68B-BF0B-2EE7-AAFE5C9CCD58}.Release-DLL|x64.ActiveCfg = Release|x64
 		{7E1DDE0D-E68B-BF0B-2EE7-AAFE5C9CCD58}.Release-DLL|x64.Build.0 = Release|x64
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Debug|Win32.ActiveCfg = Debug|Win32
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Debug|x64.ActiveCfg = Debug|x64
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Release|Win32.ActiveCfg = Release|Win32
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Release|x64.ActiveCfg = Release|x64
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Debug|Win32.Build.0 = Debug|Win32
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Debug|x64.Build.0 = Debug|x64
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Release|Win32.Build.0 = Release|Win32
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Release|x64.Build.0 = Release|x64
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Debug-DLL|x64.Build.0 = Debug|x64
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Release-DLL|Win32.Build.0 = Release|Win32
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Release-DLL|x64.ActiveCfg = Release|x64
+		{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}.Release-DLL|x64.Build.0 = Release|x64
 		{945F52A3-91ED-5891-9D11-D07A19E4FEA2}.Debug|Win32.ActiveCfg = Debug|Win32
 		{945F52A3-91ED-5891-9D11-D07A19E4FEA2}.Debug|x64.ActiveCfg = Debug|x64
 		{945F52A3-91ED-5891-9D11-D07A19E4FEA2}.Release|Win32.ActiveCfg = Release|Win32
@@ -14196,6 +14464,22 @@ Global
 		{0AE39FD9-59E4-1F8A-E8DD-1FCBFC62D2B3}.Release-DLL|Win32.Build.0 = Release|Win32
 		{0AE39FD9-59E4-1F8A-E8DD-1FCBFC62D2B3}.Release-DLL|x64.ActiveCfg = Release|x64
 		{0AE39FD9-59E4-1F8A-E8DD-1FCBFC62D2B3}.Release-DLL|x64.Build.0 = Release|x64
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Debug|Win32.ActiveCfg = Debug|Win32
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Debug|x64.ActiveCfg = Debug|x64
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Release|Win32.ActiveCfg = Release|Win32
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Release|x64.ActiveCfg = Release|x64
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Debug|Win32.Build.0 = Debug|Win32
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Debug|x64.Build.0 = Debug|x64
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Release|Win32.Build.0 = Release|Win32
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Release|x64.Build.0 = Release|x64
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Debug-DLL|x64.Build.0 = Debug|x64
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Release-DLL|Win32.Build.0 = Release|Win32
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Release-DLL|x64.ActiveCfg = Release|x64
+		{E96735FF-B1CF-51D2-1923-53292AF72C4E}.Release-DLL|x64.Build.0 = Release|x64
 		{1A1AA28B-D635-F4BD-DFFA-096D2E4BA9BF}.Debug|Win32.ActiveCfg = Debug|Win32
 		{1A1AA28B-D635-F4BD-DFFA-096D2E4BA9BF}.Debug|x64.ActiveCfg = Debug|x64
 		{1A1AA28B-D635-F4BD-DFFA-096D2E4BA9BF}.Release|Win32.ActiveCfg = Release|Win32
@@ -15188,6 +15472,22 @@ Global
 		{81643723-BBFA-AA83-B6AC-9FF770B4ED34}.Release-DLL|Win32.Build.0 = Release|Win32
 		{81643723-BBFA-AA83-B6AC-9FF770B4ED34}.Release-DLL|x64.ActiveCfg = Release|x64
 		{81643723-BBFA-AA83-B6AC-9FF770B4ED34}.Release-DLL|x64.Build.0 = Release|x64
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Debug|x64.ActiveCfg = Debug|x64
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Release|Win32.ActiveCfg = Release|Win32
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Release|x64.ActiveCfg = Release|x64
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Debug|Win32.Build.0 = Debug|Win32
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Debug|x64.Build.0 = Debug|x64
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Release|Win32.Build.0 = Release|Win32
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Release|x64.Build.0 = Release|x64
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Debug-DLL|x64.Build.0 = Debug|x64
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Release-DLL|Win32.Build.0 = Release|Win32
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Release-DLL|x64.ActiveCfg = Release|x64
+		{0B07D219-39A5-729B-EB0F-8B81E562D808}.Release-DLL|x64.Build.0 = Release|x64
 		{45EED825-B3C0-63AE-43FE-CFA8DD3164EC}.Debug|Win32.ActiveCfg = Debug|Win32
 		{45EED825-B3C0-63AE-43FE-CFA8DD3164EC}.Debug|x64.ActiveCfg = Debug|x64
 		{45EED825-B3C0-63AE-43FE-CFA8DD3164EC}.Release|Win32.ActiveCfg = Release|Win32
@@ -15732,6 +16032,22 @@ Global
 		{82D02001-4051-0130-886D-6EED6E8180D9}.Release-DLL|Win32.Build.0 = Release|Win32
 		{82D02001-4051-0130-886D-6EED6E8180D9}.Release-DLL|x64.ActiveCfg = Release|x64
 		{82D02001-4051-0130-886D-6EED6E8180D9}.Release-DLL|x64.Build.0 = Release|x64
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Debug|Win32.ActiveCfg = Debug|Win32
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Debug|x64.ActiveCfg = Debug|x64
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Release|Win32.ActiveCfg = Release|Win32
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Release|x64.ActiveCfg = Release|x64
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Debug|Win32.Build.0 = Debug|Win32
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Debug|x64.Build.0 = Debug|x64
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Release|Win32.Build.0 = Release|Win32
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Release|x64.Build.0 = Release|x64
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Debug-DLL|x64.Build.0 = Debug|x64
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Release-DLL|Win32.Build.0 = Release|Win32
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Release-DLL|x64.ActiveCfg = Release|x64
+		{856DAD36-A161-9876-9548-48D06BFA35C1}.Release-DLL|x64.Build.0 = Release|x64
 		{CB6E0DFE-7AA8-5F3A-431E-5D769E9339F7}.Debug|Win32.ActiveCfg = Debug|Win32
 		{CB6E0DFE-7AA8-5F3A-431E-5D769E9339F7}.Debug|x64.ActiveCfg = Debug|x64
 		{CB6E0DFE-7AA8-5F3A-431E-5D769E9339F7}.Release|Win32.ActiveCfg = Release|Win32
@@ -16788,6 +17104,22 @@ Global
 		{359D18A0-DEE3-EDD5-1C4C-662EC638C910}.Release-DLL|Win32.Build.0 = Release|Win32
 		{359D18A0-DEE3-EDD5-1C4C-662EC638C910}.Release-DLL|x64.ActiveCfg = Release|x64
 		{359D18A0-DEE3-EDD5-1C4C-662EC638C910}.Release-DLL|x64.Build.0 = Release|x64
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Debug|x64.ActiveCfg = Debug|x64
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Release|Win32.ActiveCfg = Release|Win32
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Release|x64.ActiveCfg = Release|x64
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Debug|Win32.Build.0 = Debug|Win32
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Debug|x64.Build.0 = Debug|x64
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Release|Win32.Build.0 = Release|Win32
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Release|x64.Build.0 = Release|x64
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Debug-DLL|x64.Build.0 = Debug|x64
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Release-DLL|Win32.Build.0 = Release|Win32
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Release-DLL|x64.ActiveCfg = Release|x64
+		{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}.Release-DLL|x64.Build.0 = Release|x64
 		{7B5AE7B2-6D7E-D97F-A6A4-721C7446171F}.Debug|Win32.ActiveCfg = Debug|Win32
 		{7B5AE7B2-6D7E-D97F-A6A4-721C7446171F}.Debug|x64.ActiveCfg = Debug|x64
 		{7B5AE7B2-6D7E-D97F-A6A4-721C7446171F}.Release|Win32.ActiveCfg = Release|Win32
@@ -17332,6 +17664,22 @@ Global
 		{E6C18E4E-ABC4-1C26-BAD6-67F92B80942F}.Release-DLL|Win32.Build.0 = Release|Win32
 		{E6C18E4E-ABC4-1C26-BAD6-67F92B80942F}.Release-DLL|x64.ActiveCfg = Release|x64
 		{E6C18E4E-ABC4-1C26-BAD6-67F92B80942F}.Release-DLL|x64.Build.0 = Release|x64
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Debug|Win32.ActiveCfg = Debug|Win32
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Debug|x64.ActiveCfg = Debug|x64
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Release|Win32.ActiveCfg = Release|Win32
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Release|x64.ActiveCfg = Release|x64
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Debug|Win32.Build.0 = Debug|Win32
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Debug|x64.Build.0 = Debug|x64
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Release|Win32.Build.0 = Release|Win32
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Release|x64.Build.0 = Release|x64
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Debug-DLL|x64.Build.0 = Debug|x64
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Release-DLL|Win32.Build.0 = Release|Win32
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Release-DLL|x64.ActiveCfg = Release|x64
+		{5A641212-7C59-E552-0ED6-F05F710DD4F5}.Release-DLL|x64.Build.0 = Release|x64
 		{C3A6661F-806B-BDE6-AF91-032175B443F8}.Debug|Win32.ActiveCfg = Debug|Win32
 		{C3A6661F-806B-BDE6-AF91-032175B443F8}.Debug|x64.ActiveCfg = Debug|x64
 		{C3A6661F-806B-BDE6-AF91-032175B443F8}.Release|Win32.ActiveCfg = Release|Win32
@@ -17876,6 +18224,22 @@ Global
 		{FDA69240-B598-500E-8E6E-741A1290ECB9}.Release-DLL|Win32.Build.0 = Release|Win32
 		{FDA69240-B598-500E-8E6E-741A1290ECB9}.Release-DLL|x64.ActiveCfg = Release|x64
 		{FDA69240-B598-500E-8E6E-741A1290ECB9}.Release-DLL|x64.Build.0 = Release|x64
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Debug|x64.ActiveCfg = Debug|x64
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Release|Win32.ActiveCfg = Release|Win32
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Release|x64.ActiveCfg = Release|x64
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Debug|Win32.Build.0 = Debug|Win32
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Debug|x64.Build.0 = Debug|x64
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Release|Win32.Build.0 = Release|Win32
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Release|x64.Build.0 = Release|x64
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Debug-DLL|x64.Build.0 = Debug|x64
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Release-DLL|Win32.Build.0 = Release|Win32
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Release-DLL|x64.ActiveCfg = Release|x64
+		{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}.Release-DLL|x64.Build.0 = Release|x64
 		{96C59CF1-6E80-B88D-D99C-0AA4C32F6562}.Debug|Win32.ActiveCfg = Debug|Win32
 		{96C59CF1-6E80-B88D-D99C-0AA4C32F6562}.Debug|x64.ActiveCfg = Debug|x64
 		{96C59CF1-6E80-B88D-D99C-0AA4C32F6562}.Release|Win32.ActiveCfg = Release|Win32
@@ -18852,6 +19216,22 @@ Global
 		{D4F84CA0-7020-BDD6-2EB8-2F773A7884A5}.Release-DLL|Win32.Build.0 = Release|Win32
 		{D4F84CA0-7020-BDD6-2EB8-2F773A7884A5}.Release-DLL|x64.ActiveCfg = Release|x64
 		{D4F84CA0-7020-BDD6-2EB8-2F773A7884A5}.Release-DLL|x64.Build.0 = Release|x64
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Debug|Win32.ActiveCfg = Debug|Win32
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Debug|x64.ActiveCfg = Debug|x64
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Release|Win32.ActiveCfg = Release|Win32
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Release|x64.ActiveCfg = Release|x64
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Debug|Win32.Build.0 = Debug|Win32
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Debug|x64.Build.0 = Debug|x64
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Release|Win32.Build.0 = Release|Win32
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Release|x64.Build.0 = Release|x64
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Debug-DLL|x64.Build.0 = Debug|x64
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Release-DLL|Win32.Build.0 = Release|Win32
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Release-DLL|x64.ActiveCfg = Release|x64
+		{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}.Release-DLL|x64.Build.0 = Release|x64
 		{8BF0F1D5-3CF2-DFFD-D74D-E2D7D06A65AC}.Debug|Win32.ActiveCfg = Debug|Win32
 		{8BF0F1D5-3CF2-DFFD-D74D-E2D7D06A65AC}.Debug|x64.ActiveCfg = Debug|x64
 		{8BF0F1D5-3CF2-DFFD-D74D-E2D7D06A65AC}.Release|Win32.ActiveCfg = Release|Win32
@@ -19812,6 +20192,22 @@ Global
 		{0ACE1393-1D1C-9563-2EFD-258C38B2C5A5}.Release-DLL|Win32.Build.0 = Release|Win32
 		{0ACE1393-1D1C-9563-2EFD-258C38B2C5A5}.Release-DLL|x64.ActiveCfg = Release|x64
 		{0ACE1393-1D1C-9563-2EFD-258C38B2C5A5}.Release-DLL|x64.Build.0 = Release|x64
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Debug|Win32.ActiveCfg = Debug|Win32
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Debug|x64.ActiveCfg = Debug|x64
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Release|Win32.ActiveCfg = Release|Win32
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Release|x64.ActiveCfg = Release|x64
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Debug|Win32.Build.0 = Debug|Win32
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Debug|x64.Build.0 = Debug|x64
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Release|Win32.Build.0 = Release|Win32
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Release|x64.Build.0 = Release|x64
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Debug-DLL|x64.Build.0 = Debug|x64
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Release-DLL|Win32.Build.0 = Release|Win32
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Release-DLL|x64.ActiveCfg = Release|x64
+		{93AF9D45-51B5-A902-4537-709FE4ED9830}.Release-DLL|x64.Build.0 = Release|x64
 		{0733C2AA-D898-7145-3F2E-6304DC428C5F}.Debug|Win32.ActiveCfg = Debug|Win32
 		{0733C2AA-D898-7145-3F2E-6304DC428C5F}.Debug|x64.ActiveCfg = Debug|x64
 		{0733C2AA-D898-7145-3F2E-6304DC428C5F}.Release|Win32.ActiveCfg = Release|Win32
@@ -20340,6 +20736,22 @@ Global
 		{90CCC199-D242-7546-C1C0-4AA6899703DE}.Release-DLL|Win32.Build.0 = Release|Win32
 		{90CCC199-D242-7546-C1C0-4AA6899703DE}.Release-DLL|x64.ActiveCfg = Release|x64
 		{90CCC199-D242-7546-C1C0-4AA6899703DE}.Release-DLL|x64.Build.0 = Release|x64
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Debug|Win32.ActiveCfg = Debug|Win32
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Debug|x64.ActiveCfg = Debug|x64
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Release|Win32.ActiveCfg = Release|Win32
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Release|x64.ActiveCfg = Release|x64
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Debug|Win32.Build.0 = Debug|Win32
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Debug|x64.Build.0 = Debug|x64
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Release|Win32.Build.0 = Release|Win32
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Release|x64.Build.0 = Release|x64
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Debug-DLL|x64.Build.0 = Debug|x64
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Release-DLL|Win32.Build.0 = Release|Win32
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Release-DLL|x64.ActiveCfg = Release|x64
+		{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}.Release-DLL|x64.Build.0 = Release|x64
 		{0EC09350-0FB9-0208-000E-1B6C534B234C}.Debug|Win32.ActiveCfg = Debug|Win32
 		{0EC09350-0FB9-0208-000E-1B6C534B234C}.Debug|x64.ActiveCfg = Debug|x64
 		{0EC09350-0FB9-0208-000E-1B6C534B234C}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/test/end2end_test_hpack_size/end2end_test_hpack_size.vcxproj b/vsprojects/vcxproj/test/end2end_test_hpack_size/end2end_test_hpack_size.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..41c5b93d9b45c706eab781dbb3515c231ff48368
--- /dev/null
+++ b/vsprojects/vcxproj/test/end2end_test_hpack_size/end2end_test_hpack_size.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>end2end_test_hpack_size</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>end2end_test_hpack_size</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\test\core\end2end\tests\cancel_test_helpers.h" />
+    <ClInclude Include="..\..\..\..\test\core\end2end\end2end_tests.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\test\core\end2end\tests\hpack_size.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/end2end_test_hpack_size/end2end_test_hpack_size.vcxproj.filters b/vsprojects/vcxproj/test/end2end_test_hpack_size/end2end_test_hpack_size.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..03caae6addd7226e745397eab2aa5584c95d015c
--- /dev/null
+++ b/vsprojects/vcxproj/test/end2end_test_hpack_size/end2end_test_hpack_size.vcxproj.filters
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\test\core\end2end\tests\hpack_size.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\test\core\end2end\tests\cancel_test_helpers.h">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\..\test\core\end2end\end2end_tests.h">
+      <Filter>test\core\end2end</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{c23a0719-53a2-0560-4016-2e8869dd4787}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{061c394d-81e8-0ac3-7a25-ab563ba0abe3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\end2end">
+      <UniqueIdentifier>{8b8f1aa7-7645-4372-1d8a-61cda8284353}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\end2end\tests">
+      <UniqueIdentifier>{aa7c2d3e-58e5-6898-fb3a-ba5e8868ea09}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_compress_hpack_size_nosec_test/h2_compress_hpack_size_nosec_test.vcxproj b/vsprojects/vcxproj/test/h2_compress_hpack_size_nosec_test/h2_compress_hpack_size_nosec_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..116bf2fb9cbf47e7ea8afec67ed1b8f6141382e9
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_compress_hpack_size_nosec_test/h2_compress_hpack_size_nosec_test.vcxproj
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{5A641212-7C59-E552-0ED6-F05F710DD4F5}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_compress_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_compress_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_compress\end2end_fixture_h2_compress.vcxproj">
+      <Project>{C5D3C9A9-C0D2-CBAD-B433-710C5E89AE31}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_compress_hpack_size_nosec_test/h2_compress_hpack_size_nosec_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_compress_hpack_size_nosec_test/h2_compress_hpack_size_nosec_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_compress_hpack_size_nosec_test/h2_compress_hpack_size_nosec_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_compress_hpack_size_test/h2_compress_hpack_size_test.vcxproj b/vsprojects/vcxproj/test/h2_compress_hpack_size_test/h2_compress_hpack_size_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..61c35e5b8d8e9192f16c0b07a415b8f564af95af
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_compress_hpack_size_test/h2_compress_hpack_size_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{8E7B2D33-360B-9A26-8BFD-1BAD10769F33}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_compress_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_compress_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_compress\end2end_fixture_h2_compress.vcxproj">
+      <Project>{C5D3C9A9-C0D2-CBAD-B433-710C5E89AE31}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_certs\end2end_certs.vcxproj">
+      <Project>{80EA2691-C037-6DD3-D3AB-21510BF0E64B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_compress_hpack_size_test/h2_compress_hpack_size_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_compress_hpack_size_test/h2_compress_hpack_size_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_compress_hpack_size_test/h2_compress_hpack_size_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_fakesec_hpack_size_test/h2_fakesec_hpack_size_test.vcxproj b/vsprojects/vcxproj/test/h2_fakesec_hpack_size_test/h2_fakesec_hpack_size_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..e7c3a52cdc5f642063a8d91639456d11c08c1080
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_fakesec_hpack_size_test/h2_fakesec_hpack_size_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{5CDFA7CB-09E1-E01E-E21D-7446146478CC}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_fakesec_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_fakesec_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_fakesec\end2end_fixture_h2_fakesec.vcxproj">
+      <Project>{096ABF91-FEC8-9AC9-B877-C683BFD51984}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_certs\end2end_certs.vcxproj">
+      <Project>{80EA2691-C037-6DD3-D3AB-21510BF0E64B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_fakesec_hpack_size_test/h2_fakesec_hpack_size_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_fakesec_hpack_size_test/h2_fakesec_hpack_size_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_fakesec_hpack_size_test/h2_fakesec_hpack_size_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_full_hpack_size_nosec_test/h2_full_hpack_size_nosec_test.vcxproj b/vsprojects/vcxproj/test/h2_full_hpack_size_nosec_test/h2_full_hpack_size_nosec_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..03b06164a43dcfed39c186499127a20c8c48c531
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_full_hpack_size_nosec_test/h2_full_hpack_size_nosec_test.vcxproj
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{C355D9BD-F3C7-CA89-E125-44D1BAEE22C1}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_full_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_full_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_full\end2end_fixture_h2_full.vcxproj">
+      <Project>{882B2933-F340-7027-7090-28CEAE9F1BE6}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_full_hpack_size_nosec_test/h2_full_hpack_size_nosec_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_full_hpack_size_nosec_test/h2_full_hpack_size_nosec_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_full_hpack_size_nosec_test/h2_full_hpack_size_nosec_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_full_hpack_size_test/h2_full_hpack_size_test.vcxproj b/vsprojects/vcxproj/test/h2_full_hpack_size_test/h2_full_hpack_size_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..9e7fb88b712a318bf1b719ba12f6291ef538012d
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_full_hpack_size_test/h2_full_hpack_size_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{C655AED5-AF53-D09E-A8EA-60AE0F2D149A}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_full_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_full_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_full\end2end_fixture_h2_full.vcxproj">
+      <Project>{882B2933-F340-7027-7090-28CEAE9F1BE6}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_certs\end2end_certs.vcxproj">
+      <Project>{80EA2691-C037-6DD3-D3AB-21510BF0E64B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_full_hpack_size_test/h2_full_hpack_size_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_full_hpack_size_test/h2_full_hpack_size_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_full_hpack_size_test/h2_full_hpack_size_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_oauth2_hpack_size_test/h2_oauth2_hpack_size_test.vcxproj b/vsprojects/vcxproj/test/h2_oauth2_hpack_size_test/h2_oauth2_hpack_size_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..82c49fe85e3dd6a50147fa871e50568a2a98a106
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_oauth2_hpack_size_test/h2_oauth2_hpack_size_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{CA3C2D7E-58C7-C05E-6D3B-70383020D8C2}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_oauth2_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_oauth2_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_oauth2\end2end_fixture_h2_oauth2.vcxproj">
+      <Project>{DDFE4EB8-CCD3-DA3F-461A-10F1B94D26AF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_certs\end2end_certs.vcxproj">
+      <Project>{80EA2691-C037-6DD3-D3AB-21510BF0E64B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_oauth2_hpack_size_test/h2_oauth2_hpack_size_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_oauth2_hpack_size_test/h2_oauth2_hpack_size_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_oauth2_hpack_size_test/h2_oauth2_hpack_size_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_nosec_test/h2_sockpair_1byte_hpack_size_nosec_test.vcxproj b/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_nosec_test/h2_sockpair_1byte_hpack_size_nosec_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..c5a13ad91afe5cc40cc90f6677513c3bb641e4b2
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_nosec_test/h2_sockpair_1byte_hpack_size_nosec_test.vcxproj
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{93AF9D45-51B5-A902-4537-709FE4ED9830}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_sockpair_1byte_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_sockpair_1byte_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_sockpair_1byte\end2end_fixture_h2_sockpair_1byte.vcxproj">
+      <Project>{B0F4BF34-3C82-EB67-990E-959CDDBEB734}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_nosec_test/h2_sockpair_1byte_hpack_size_nosec_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_nosec_test/h2_sockpair_1byte_hpack_size_nosec_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_nosec_test/h2_sockpair_1byte_hpack_size_nosec_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_test/h2_sockpair_1byte_hpack_size_test.vcxproj b/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_test/h2_sockpair_1byte_hpack_size_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..de13e2666bf7bc08e2ccd14ccc6ced48c2eb5fdc
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_test/h2_sockpair_1byte_hpack_size_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{0B07D219-39A5-729B-EB0F-8B81E562D808}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_sockpair_1byte_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_sockpair_1byte_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_sockpair_1byte\end2end_fixture_h2_sockpair_1byte.vcxproj">
+      <Project>{B0F4BF34-3C82-EB67-990E-959CDDBEB734}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_certs\end2end_certs.vcxproj">
+      <Project>{80EA2691-C037-6DD3-D3AB-21510BF0E64B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_test/h2_sockpair_1byte_hpack_size_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_test/h2_sockpair_1byte_hpack_size_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_sockpair_1byte_hpack_size_test/h2_sockpair_1byte_hpack_size_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_sockpair_hpack_size_nosec_test/h2_sockpair_hpack_size_nosec_test.vcxproj b/vsprojects/vcxproj/test/h2_sockpair_hpack_size_nosec_test/h2_sockpair_hpack_size_nosec_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..fedcff890ae397b8899a111ce8e3c9cbeedaa1ea
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_sockpair_hpack_size_nosec_test/h2_sockpair_hpack_size_nosec_test.vcxproj
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{B35C9AC3-8160-BFCA-2EA7-0413A7A45EC4}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_sockpair_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_sockpair_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_sockpair\end2end_fixture_h2_sockpair.vcxproj">
+      <Project>{67A1675D-FF50-3B78-2706-155D69ADC290}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_sockpair_hpack_size_nosec_test/h2_sockpair_hpack_size_nosec_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_sockpair_hpack_size_nosec_test/h2_sockpair_hpack_size_nosec_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_sockpair_hpack_size_nosec_test/h2_sockpair_hpack_size_nosec_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_sockpair_hpack_size_test/h2_sockpair_hpack_size_test.vcxproj b/vsprojects/vcxproj/test/h2_sockpair_hpack_size_test/h2_sockpair_hpack_size_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..744cb13d027f7bf8268900004a492351df1bdccc
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_sockpair_hpack_size_test/h2_sockpair_hpack_size_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{E96735FF-B1CF-51D2-1923-53292AF72C4E}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_sockpair_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_sockpair_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_sockpair\end2end_fixture_h2_sockpair.vcxproj">
+      <Project>{67A1675D-FF50-3B78-2706-155D69ADC290}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_certs\end2end_certs.vcxproj">
+      <Project>{80EA2691-C037-6DD3-D3AB-21510BF0E64B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_sockpair_hpack_size_test/h2_sockpair_hpack_size_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_sockpair_hpack_size_test/h2_sockpair_hpack_size_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_sockpair_hpack_size_test/h2_sockpair_hpack_size_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_ssl_hpack_size_test/h2_ssl_hpack_size_test.vcxproj b/vsprojects/vcxproj/test/h2_ssl_hpack_size_test/h2_ssl_hpack_size_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..2ff0f47301904e9e86165a28c19afb77a8b7f119
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_ssl_hpack_size_test/h2_ssl_hpack_size_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{856DAD36-A161-9876-9548-48D06BFA35C1}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_ssl_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_ssl_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_ssl\end2end_fixture_h2_ssl.vcxproj">
+      <Project>{207BE5BC-25D7-1D2A-C76E-279DB66A1205}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_certs\end2end_certs.vcxproj">
+      <Project>{80EA2691-C037-6DD3-D3AB-21510BF0E64B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_ssl_hpack_size_test/h2_ssl_hpack_size_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_ssl_hpack_size_test/h2_ssl_hpack_size_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_ssl_hpack_size_test/h2_ssl_hpack_size_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_uchannel_hpack_size_nosec_test/h2_uchannel_hpack_size_nosec_test.vcxproj b/vsprojects/vcxproj/test/h2_uchannel_hpack_size_nosec_test/h2_uchannel_hpack_size_nosec_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..6985300e80454d6ac5cbbcd61d01ec6f1ae56a3b
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_uchannel_hpack_size_nosec_test/h2_uchannel_hpack_size_nosec_test.vcxproj
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{EA53DB0D-8BA3-3BCC-10E1-8B5FACB77CA1}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_uchannel_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_uchannel_hpack_size_nosec_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_uchannel\end2end_fixture_h2_uchannel.vcxproj">
+      <Project>{CE17F95F-4FD3-41C3-E1B9-9B85F1FE7D4A}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
+      <Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
+      <Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_uchannel_hpack_size_nosec_test/h2_uchannel_hpack_size_nosec_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_uchannel_hpack_size_nosec_test/h2_uchannel_hpack_size_nosec_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_uchannel_hpack_size_nosec_test/h2_uchannel_hpack_size_nosec_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_uchannel_hpack_size_test/h2_uchannel_hpack_size_test.vcxproj b/vsprojects/vcxproj/test/h2_uchannel_hpack_size_test/h2_uchannel_hpack_size_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..3b73900945f1e42c83da493f8e534c29ff4aee0c
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_uchannel_hpack_size_test/h2_uchannel_hpack_size_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{9CFB3202-D95F-E541-9A6F-BE561CAFE1AE}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>h2_uchannel_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>h2_uchannel_hpack_size_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\vsprojects\dummy.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_fixture_h2_uchannel\end2end_fixture_h2_uchannel.vcxproj">
+      <Project>{CE17F95F-4FD3-41C3-E1B9-9B85F1FE7D4A}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_test_hpack_size\end2end_test_hpack_size.vcxproj">
+      <Project>{22A644D5-9A2B-4EF8-7792-AEB0C66A10E5}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\test\end2end_certs\end2end_certs.vcxproj">
+      <Project>{80EA2691-C037-6DD3-D3AB-21510BF0E64B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/h2_uchannel_hpack_size_test/h2_uchannel_hpack_size_test.vcxproj.filters b/vsprojects/vcxproj/test/h2_uchannel_hpack_size_test/h2_uchannel_hpack_size_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..00e4276f1d4a4424020141e0c5296974350bd7ba
--- /dev/null
+++ b/vsprojects/vcxproj/test/h2_uchannel_hpack_size_test/h2_uchannel_hpack_size_test.vcxproj.filters
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <ItemGroup>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/metrics_client/metrics_client.vcxproj b/vsprojects/vcxproj/test/metrics_client/metrics_client.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..11a3e36448721406003dbee83bee79f5c35e3a19
--- /dev/null
+++ b/vsprojects/vcxproj/test/metrics_client/metrics_client.vcxproj
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{FE8631BA-DF40-EC70-6078-C2DAF316E329}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\cpptest.props" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\protobuf.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>metrics_client</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>metrics_client</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\test\cpp\util\metrics_server.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\test\proto\metrics.pb.cc">
+    </ClCompile>
+    <ClInclude Include="..\..\..\..\test\proto\metrics.pb.h">
+    </ClInclude>
+    <ClCompile Include="..\..\..\..\test\proto\metrics.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="..\..\..\..\test\proto\metrics.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="..\..\..\..\test\cpp\interop\metrics_client.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
+      <Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/metrics_client/metrics_client.vcxproj.filters b/vsprojects/vcxproj/test/metrics_client/metrics_client.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..73aaaa22c8f2b9c90ca18887ded97b845b42fbb1
--- /dev/null
+++ b/vsprojects/vcxproj/test/metrics_client/metrics_client.vcxproj.filters
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\test\proto\metrics.proto">
+      <Filter>test\proto</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\..\test\cpp\interop\metrics_client.cc">
+      <Filter>test\cpp\interop</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\..\test\cpp\util\metrics_server.h">
+      <Filter>test\cpp\util</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{2c00b6b1-865c-55b2-0d9d-8d7b42ad7d03}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{a62a5921-b3d4-6069-e9cc-73f34609c99b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\interop">
+      <UniqueIdentifier>{fbd5c6ac-f3a9-1b16-6310-c205aadc9075}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\util">
+      <UniqueIdentifier>{16f4e45d-a509-3e4d-4a19-9383576bec54}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\proto">
+      <UniqueIdentifier>{c638ed75-9aa0-ccc3-a8d2-a1a6203977b1}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/stress_test/stress_test.vcxproj b/vsprojects/vcxproj/test/stress_test/stress_test.vcxproj
index a385a6dce9e397ceedb1246d231288970ccfaf56..d449b62c756791fdd9695ce3c15c7cc8dd369ae5 100644
--- a/vsprojects/vcxproj/test/stress_test/stress_test.vcxproj
+++ b/vsprojects/vcxproj/test/stress_test/stress_test.vcxproj
@@ -148,6 +148,7 @@
     <ClInclude Include="..\..\..\..\test\cpp\interop\client_helper.h" />
     <ClInclude Include="..\..\..\..\test\cpp\interop\interop_client.h" />
     <ClInclude Include="..\..\..\..\test\cpp\interop\stress_interop_client.h" />
+    <ClInclude Include="..\..\..\..\test\cpp\util\metrics_server.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\..\test\proto\empty.pb.cc">
@@ -166,6 +167,14 @@
     </ClCompile>
     <ClInclude Include="..\..\..\..\test\proto\messages.grpc.pb.h">
     </ClInclude>
+    <ClCompile Include="..\..\..\..\test\proto\metrics.pb.cc">
+    </ClCompile>
+    <ClInclude Include="..\..\..\..\test\proto\metrics.pb.h">
+    </ClInclude>
+    <ClCompile Include="..\..\..\..\test\proto\metrics.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="..\..\..\..\test\proto\metrics.grpc.pb.h">
+    </ClInclude>
     <ClCompile Include="..\..\..\..\test\proto\test.pb.cc">
     </ClCompile>
     <ClInclude Include="..\..\..\..\test\proto\test.pb.h">
@@ -180,6 +189,8 @@
     </ClCompile>
     <ClCompile Include="..\..\..\..\test\cpp\interop\stress_test.cc">
     </ClCompile>
+    <ClCompile Include="..\..\..\..\test\cpp\util\metrics_server.cc">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
diff --git a/vsprojects/vcxproj/test/stress_test/stress_test.vcxproj.filters b/vsprojects/vcxproj/test/stress_test/stress_test.vcxproj.filters
index 839493a96e8ba5a5b01eac60cb5b5279b20f452f..b20bd35723a24b6fc97720f62c86c91938864d66 100644
--- a/vsprojects/vcxproj/test/stress_test/stress_test.vcxproj.filters
+++ b/vsprojects/vcxproj/test/stress_test/stress_test.vcxproj.filters
@@ -7,6 +7,9 @@
     <ClCompile Include="..\..\..\..\test\proto\messages.proto">
       <Filter>test\proto</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\..\test\proto\metrics.proto">
+      <Filter>test\proto</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\..\..\test\proto\test.proto">
       <Filter>test\proto</Filter>
     </ClCompile>
@@ -19,6 +22,9 @@
     <ClCompile Include="..\..\..\..\test\cpp\interop\stress_test.cc">
       <Filter>test\cpp\interop</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\..\test\cpp\util\metrics_server.cc">
+      <Filter>test\cpp\util</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\..\test\cpp\interop\client_helper.h">
@@ -30,6 +36,9 @@
     <ClInclude Include="..\..\..\..\test\cpp\interop\stress_interop_client.h">
       <Filter>test\cpp\interop</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\..\test\cpp\util\metrics_server.h">
+      <Filter>test\cpp\util</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
@@ -42,6 +51,9 @@
     <Filter Include="test\cpp\interop">
       <UniqueIdentifier>{7afcf5a8-556a-6be3-15d4-b00b2518f8fb}</UniqueIdentifier>
     </Filter>
+    <Filter Include="test\cpp\util">
+      <UniqueIdentifier>{e4704307-621e-0e9c-08c2-3c698c1b827f}</UniqueIdentifier>
+    </Filter>
     <Filter Include="test\proto">
       <UniqueIdentifier>{7172a335-47bf-8284-380d-a28a05c07311}</UniqueIdentifier>
     </Filter>