Merge pull request #14885 from ericgribkoff/android_cleanup

simplify CMake build
diff --git a/.gitignore b/.gitignore
index 0f3cd78..cde82bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,8 +15,10 @@
 htmlcov/
 dist/
 *.egg
-py27/
-py3[0-9]*/
+py27_gevent/
+py27_native/
+py3[0-9]_gevent/
+py3[0-9]_native/
 
 # Node installation output
 node_modules
diff --git a/BUILD b/BUILD
index 54215fe..f6ec921 100644
--- a/BUILD
+++ b/BUILD
@@ -307,16 +307,8 @@
     language = "c++",
     deps = [
         "grpc_base",
-        "grpc_deadline_filter",
-        "grpc_lb_policy_pick_first",
         "grpc_http_filters",
-        "grpc_max_age_filter",
-        "grpc_message_size_filter",
-        "grpc_resolver_dns_native",
-        "grpc_resolver_sockaddr",
-        "grpc_server_load_reporting",
         "grpc_transport_chttp2_client_secure",
-        "grpc_transport_chttp2_server_secure",
         "grpc_transport_cronet_client_secure",
     ],
 )
@@ -686,11 +678,11 @@
         "src/core/lib/channel/channel_stack_builder.cc",
         "src/core/lib/channel/channel_trace.cc",
         "src/core/lib/channel/channel_trace_registry.cc",
-        "src/core/lib/channel/status_util.cc",
         "src/core/lib/channel/connected_channel.cc",
         "src/core/lib/channel/handshaker.cc",
         "src/core/lib/channel/handshaker_factory.cc",
         "src/core/lib/channel/handshaker_registry.cc",
+        "src/core/lib/channel/status_util.cc",
         "src/core/lib/compression/compression.cc",
         "src/core/lib/compression/compression_internal.cc",
         "src/core/lib/compression/message_compress.cc",
@@ -833,12 +825,12 @@
         "src/core/lib/channel/channel_stack_builder.h",
         "src/core/lib/channel/channel_trace.h",
         "src/core/lib/channel/channel_trace_registry.h",
-        "src/core/lib/channel/status_util.h",
         "src/core/lib/channel/connected_channel.h",
         "src/core/lib/channel/context.h",
         "src/core/lib/channel/handshaker.h",
         "src/core/lib/channel/handshaker_factory.h",
         "src/core/lib/channel/handshaker_registry.h",
+        "src/core/lib/channel/status_util.h",
         "src/core/lib/compression/algorithm_metadata.h",
         "src/core/lib/compression/compression_internal.h",
         "src/core/lib/compression/message_compress.h",
@@ -992,6 +984,7 @@
         # standard plugins
         "census",
         "grpc_deadline_filter",
+        "grpc_client_authority_filter",
         "grpc_lb_policy_pick_first",
         "grpc_lb_policy_round_robin",
         "grpc_server_load_reporting",
@@ -1060,6 +1053,7 @@
     deps = [
         "gpr_base",
         "grpc_base",
+        "grpc_client_authority_filter",
         "grpc_deadline_filter",
         "inlined_vector",
         "orphanable",
@@ -1097,6 +1091,20 @@
 )
 
 grpc_cc_library(
+    name = "grpc_client_authority_filter",
+    srcs = [
+        "src/core/ext/filters/http/client_authority_filter.cc",
+    ],
+    hdrs = [
+        "src/core/ext/filters/http/client_authority_filter.h",
+    ],
+    language = "c++",
+    deps = [
+        "grpc_base",
+    ],
+)
+
+grpc_cc_library(
     name = "grpc_message_size_filter",
     srcs = [
         "src/core/ext/filters/message_size/message_size_filter.cc",
@@ -1340,6 +1348,7 @@
     srcs = [
         "src/core/lib/http/httpcli_security_connector.cc",
         "src/core/lib/security/context/security_context.cc",
+        "src/core/lib/security/credentials/alts/alts_credentials.cc",
         "src/core/lib/security/credentials/composite/composite_credentials.cc",
         "src/core/lib/security/credentials/credentials.cc",
         "src/core/lib/security/credentials/credentials_metadata.cc",
@@ -1353,7 +1362,6 @@
         "src/core/lib/security/credentials/oauth2/oauth2_credentials.cc",
         "src/core/lib/security/credentials/plugin/plugin_credentials.cc",
         "src/core/lib/security/credentials/ssl/ssl_credentials.cc",
-        "src/core/lib/security/credentials/alts/alts_credentials.cc",
         "src/core/lib/security/security_connector/alts_security_connector.cc",
         "src/core/lib/security/security_connector/security_connector.cc",
         "src/core/lib/security/transport/client_auth_filter.cc",
@@ -1367,6 +1375,7 @@
     ],
     hdrs = [
         "src/core/lib/security/context/security_context.h",
+        "src/core/lib/security/credentials/alts/alts_credentials.h",
         "src/core/lib/security/credentials/composite/composite_credentials.h",
         "src/core/lib/security/credentials/credentials.h",
         "src/core/lib/security/credentials/fake/fake_credentials.h",
@@ -1378,7 +1387,6 @@
         "src/core/lib/security/credentials/oauth2/oauth2_credentials.h",
         "src/core/lib/security/credentials/plugin/plugin_credentials.h",
         "src/core/lib/security/credentials/ssl/ssl_credentials.h",
-        "src/core/lib/security/credentials/alts/alts_credentials.h",
         "src/core/lib/security/security_connector/alts_security_connector.h",
         "src/core/lib/security/security_connector/security_connector.h",
         "src/core/lib/security/transport/auth_filters.h",
@@ -1472,9 +1480,11 @@
 grpc_cc_library(
     name = "grpc_transport_chttp2_client_connector",
     srcs = [
+        "src/core/ext/transport/chttp2/client/authority.cc",
         "src/core/ext/transport/chttp2/client/chttp2_connector.cc",
     ],
     hdrs = [
+        "src/core/ext/transport/chttp2/client/authority.h",
         "src/core/ext/transport/chttp2/client/chttp2_connector.h",
     ],
     language = "c++",
@@ -1641,8 +1651,8 @@
         "src/core/tsi/alts/frame_protector/frame_handler.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h",
-        "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h",
+        "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h",
         "src/core/tsi/transport_security_grpc.h",
@@ -1702,20 +1712,20 @@
     ],
     language = "c++",
     deps = [
-      "alts_proto",
-      "gpr",
-      "grpc_base",
+        "alts_proto",
+        "gpr",
+        "grpc_base",
     ],
 )
 
 grpc_cc_library(
     name = "tsi",
     srcs = [
-        "src/core/tsi/alts_transport_security.cc",
         "src/core/tsi/alts/handshaker/alts_handshaker_client.cc",
         "src/core/tsi/alts/handshaker/alts_tsi_event.cc",
         "src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc",
         "src/core/tsi/alts/handshaker/alts_tsi_utils.cc",
+        "src/core/tsi/alts_transport_security.cc",
         "src/core/tsi/fake_transport_security.cc",
         "src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc",
         "src/core/tsi/ssl/session_cache/ssl_session_cache.cc",
@@ -1724,12 +1734,12 @@
         "src/core/tsi/transport_security_grpc.cc",
     ],
     hdrs = [
-        "src/core/tsi/alts_transport_security.h",
         "src/core/tsi/alts/handshaker/alts_handshaker_client.h",
         "src/core/tsi/alts/handshaker/alts_tsi_event.h",
         "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h",
         "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h",
         "src/core/tsi/alts/handshaker/alts_tsi_utils.h",
+        "src/core/tsi/alts_transport_security.h",
         "src/core/tsi/fake_transport_security.h",
         "src/core/tsi/ssl/session_cache/ssl_session.h",
         "src/core/tsi/ssl/session_cache/ssl_session_cache.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 56dd61e..4fd9826 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -289,7 +289,6 @@
 add_dependencies(buildtests_c grpc_completion_queue_threading_test)
 add_dependencies(buildtests_c grpc_credentials_test)
 add_dependencies(buildtests_c grpc_fetch_oauth2)
-add_dependencies(buildtests_c grpc_invalid_channel_args_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_c grpc_json_token_test)
 endif()
@@ -605,6 +604,7 @@
 add_dependencies(buildtests_cxx reconnect_interop_server)
 add_dependencies(buildtests_cxx ref_counted_ptr_test)
 add_dependencies(buildtests_cxx ref_counted_test)
+add_dependencies(buildtests_cxx retry_throttle_test)
 add_dependencies(buildtests_cxx secure_auth_context_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_cxx secure_sync_unary_ping_pong_test)
@@ -1148,6 +1148,7 @@
   src/core/tsi/transport_security_adapter.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
+  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/ext/filters/client_channel/backup_poller.cc
   src/core/ext/filters/client_channel/channel_connectivity.cc
@@ -1205,6 +1206,7 @@
   src/core/ext/census/grpc_context.cc
   src/core/ext/filters/max_age/max_age_filter.cc
   src/core/ext/filters/message_size/message_size_filter.cc
+  src/core/ext/filters/http/client_authority_filter.cc
   src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
   src/core/ext/filters/workarounds/workaround_utils.cc
   src/core/plugin_registry/grpc_plugin_registry.cc
@@ -1449,36 +1451,6 @@
   src/core/lib/transport/transport.cc
   src/core/lib/transport/transport_op_string.cc
   src/core/lib/debug/trace.cc
-  src/core/ext/filters/deadline/deadline_filter.cc
-  src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
-  src/core/ext/filters/client_channel/backup_poller.cc
-  src/core/ext/filters/client_channel/channel_connectivity.cc
-  src/core/ext/filters/client_channel/client_channel.cc
-  src/core/ext/filters/client_channel/client_channel_factory.cc
-  src/core/ext/filters/client_channel/client_channel_plugin.cc
-  src/core/ext/filters/client_channel/connector.cc
-  src/core/ext/filters/client_channel/http_connect_handshaker.cc
-  src/core/ext/filters/client_channel/http_proxy.cc
-  src/core/ext/filters/client_channel/lb_policy.cc
-  src/core/ext/filters/client_channel/lb_policy_factory.cc
-  src/core/ext/filters/client_channel/lb_policy_registry.cc
-  src/core/ext/filters/client_channel/method_params.cc
-  src/core/ext/filters/client_channel/parse_address.cc
-  src/core/ext/filters/client_channel/proxy_mapper.cc
-  src/core/ext/filters/client_channel/proxy_mapper_registry.cc
-  src/core/ext/filters/client_channel/resolver.cc
-  src/core/ext/filters/client_channel/resolver_registry.cc
-  src/core/ext/filters/client_channel/retry_throttle.cc
-  src/core/ext/filters/client_channel/subchannel.cc
-  src/core/ext/filters/client_channel/subchannel_index.cc
-  src/core/ext/filters/client_channel/uri_parser.cc
-  src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
-  src/core/ext/filters/max_age/max_age_filter.cc
-  src/core/ext/filters/message_size/message_size_filter.cc
-  src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
-  src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
-  src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
-  src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
   src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc
   src/core/ext/transport/cronet/transport/cronet_api_dummy.cc
   src/core/ext/transport/cronet/transport/cronet_transport.cc
@@ -1510,6 +1482,28 @@
   src/core/ext/filters/http/http_filters_plugin.cc
   src/core/ext/filters/http/message_compress/message_compress_filter.cc
   src/core/ext/filters/http/server/http_server_filter.cc
+  src/core/ext/filters/client_channel/backup_poller.cc
+  src/core/ext/filters/client_channel/channel_connectivity.cc
+  src/core/ext/filters/client_channel/client_channel.cc
+  src/core/ext/filters/client_channel/client_channel_factory.cc
+  src/core/ext/filters/client_channel/client_channel_plugin.cc
+  src/core/ext/filters/client_channel/connector.cc
+  src/core/ext/filters/client_channel/http_connect_handshaker.cc
+  src/core/ext/filters/client_channel/http_proxy.cc
+  src/core/ext/filters/client_channel/lb_policy.cc
+  src/core/ext/filters/client_channel/lb_policy_factory.cc
+  src/core/ext/filters/client_channel/lb_policy_registry.cc
+  src/core/ext/filters/client_channel/method_params.cc
+  src/core/ext/filters/client_channel/parse_address.cc
+  src/core/ext/filters/client_channel/proxy_mapper.cc
+  src/core/ext/filters/client_channel/proxy_mapper_registry.cc
+  src/core/ext/filters/client_channel/resolver.cc
+  src/core/ext/filters/client_channel/resolver_registry.cc
+  src/core/ext/filters/client_channel/retry_throttle.cc
+  src/core/ext/filters/client_channel/subchannel.cc
+  src/core/ext/filters/client_channel/subchannel_index.cc
+  src/core/ext/filters/client_channel/uri_parser.cc
+  src/core/ext/filters/deadline/deadline_filter.cc
   src/core/lib/http/httpcli_security_connector.cc
   src/core/lib/security/context/security_context.cc
   src/core/lib/security/credentials/alts/alts_credentials.cc
@@ -1574,6 +1568,7 @@
   src/core/tsi/transport_security_adapter.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
+  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/tsi/alts_transport_security.cc
   src/core/tsi/fake_transport_security.cc
@@ -1582,8 +1577,8 @@
   src/core/tsi/ssl/session_cache/ssl_session_openssl.cc
   src/core/tsi/ssl_transport_security.cc
   src/core/tsi/transport_security_grpc.cc
-  src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc
-  src/core/ext/transport/chttp2/server/chttp2_server.cc
+  src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
+  src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
   src/core/plugin_registry/grpc_cronet_plugin_registry.cc
 )
 
@@ -1643,20 +1638,9 @@
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
-  include/grpc/byte_buffer.h
-  include/grpc/byte_buffer_reader.h
-  include/grpc/compression.h
-  include/grpc/fork.h
-  include/grpc/grpc.h
-  include/grpc/grpc_posix.h
-  include/grpc/grpc_security_constants.h
-  include/grpc/load_reporting.h
-  include/grpc/slice.h
-  include/grpc/slice_buffer.h
-  include/grpc/status.h
-  include/grpc/support/workaround_list.h
   include/grpc/grpc_cronet.h
   include/grpc/grpc_security.h
+  include/grpc/grpc_security_constants.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
   get_filename_component(_path ${_path} PATH)
@@ -2470,6 +2454,7 @@
   src/core/ext/transport/chttp2/server/chttp2_server.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
+  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/ext/filters/client_channel/backup_poller.cc
   src/core/ext/filters/client_channel/channel_connectivity.cc
@@ -2519,6 +2504,7 @@
   src/core/ext/census/grpc_context.cc
   src/core/ext/filters/max_age/max_age_filter.cc
   src/core/ext/filters/message_size/message_size_filter.cc
+  src/core/ext/filters/http/client_authority_filter.cc
   src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
   src/core/ext/filters/workarounds/workaround_utils.cc
   src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
@@ -3088,6 +3074,7 @@
   src/cpp/codegen/codegen_init.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
+  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/ext/transport/chttp2/transport/bin_decoder.cc
   src/core/ext/transport/chttp2/transport/bin_encoder.cc
@@ -5205,6 +5192,7 @@
   test/core/end2end/tests/bad_ping.cc
   test/core/end2end/tests/binary_metadata.cc
   test/core/end2end/tests/call_creds.cc
+  test/core/end2end/tests/call_host_override.cc
   test/core/end2end/tests/cancel_after_accept.cc
   test/core/end2end/tests/cancel_after_client_done.cc
   test/core/end2end/tests/cancel_after_invoke.cc
@@ -5321,6 +5309,7 @@
   test/core/end2end/tests/bad_hostname.cc
   test/core/end2end/tests/bad_ping.cc
   test/core/end2end/tests/binary_metadata.cc
+  test/core/end2end/tests/call_host_override.cc
   test/core/end2end/tests/cancel_after_accept.cc
   test/core/end2end/tests/cancel_after_client_done.cc
   test/core/end2end/tests/cancel_after_invoke.cc
@@ -5696,15 +5685,6 @@
   gpr
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS check_epollexclusive EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 
 add_executable(chttp2_hpack_encoder_test
@@ -6980,15 +6960,6 @@
   gpr
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS grpc_create_jwt EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 
 add_executable(grpc_credentials_test
@@ -7046,34 +7017,6 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
-
-add_executable(grpc_invalid_channel_args_test
-  test/core/surface/invalid_channel_args_test.cc
-)
-
-
-target_include_directories(grpc_invalid_channel_args_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
-  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
-  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
-  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
-  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
-  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
-  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-)
-
-target_link_libraries(grpc_invalid_channel_args_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-  grpc
-  gpr_test_util
-  gpr
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(grpc_json_token_test
@@ -7156,15 +7099,6 @@
   gpr
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS grpc_print_google_default_creds_token EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 
 add_executable(grpc_security_connector_test
@@ -7246,15 +7180,6 @@
   gpr
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS grpc_verify_jwt EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX)
 
@@ -12959,6 +12884,43 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(retry_throttle_test
+  test/core/client_channel/retry_throttle_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(retry_throttle_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(retry_throttle_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(secure_auth_context_test
   test/cpp/common/secure_auth_context_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -13916,15 +13878,6 @@
 )
 
 
-if (gRPC_INSTALL)
-  install(TARGETS gen_hpack_tables EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
-
 add_executable(gen_legal_metadata_characters
   tools/codegen/core/gen_legal_metadata_characters.cc
 )
@@ -13947,15 +13900,6 @@
 )
 
 
-if (gRPC_INSTALL)
-  install(TARGETS gen_legal_metadata_characters EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
-
 add_executable(gen_percent_encoding_tables
   tools/codegen/core/gen_percent_encoding_tables.cc
 )
@@ -13977,15 +13921,6 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS gen_percent_encoding_tables EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 
 add_executable(badreq_bad_client_test
diff --git a/INSTALL.md b/INSTALL.md
index 810f2b5..dde937e 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -142,7 +142,7 @@
 > call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x64
 > cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
 > cmake --build .
-> ninja
+> ninja install
 ```
 
 ### msys2 (with mingw)
diff --git a/Makefile b/Makefile
index a6275aa..64195ee 100644
--- a/Makefile
+++ b/Makefile
@@ -503,7 +503,7 @@
 OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
 OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
 ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
-PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.0.0 protobuf
+PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf
 CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares
 else # HAS_PKG_CONFIG
 
@@ -919,7 +919,7 @@
 	@echo
 	@echo "DEPENDENCY ERROR"
 	@echo
-	@echo "The target you are trying to run requires protobuf 3.0.0+"
+	@echo "The target you are trying to run requires protobuf 3.5.0+"
 	@echo "Your system doesn't have it, and neither does the third_party directory."
 	@echo
 	@echo "Please consult INSTALL to get more information."
@@ -933,7 +933,7 @@
 	@echo
 	@echo "DEPENDENCY ERROR"
 	@echo
-	@echo "The target you are trying to run requires protobuf-compiler 3.0.0+"
+	@echo "The target you are trying to run requires protobuf-compiler 3.5.0+"
 	@echo "Your system doesn't have it, and neither does the third_party directory."
 	@echo
 	@echo "Please consult INSTALL to get more information."
@@ -1017,7 +1017,6 @@
 grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt
 grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test
 grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2
-grpc_invalid_channel_args_test: $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test
 grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test
 grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test
 grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token
@@ -1195,6 +1194,7 @@
 reconnect_interop_server: $(BINDIR)/$(CONFIG)/reconnect_interop_server
 ref_counted_ptr_test: $(BINDIR)/$(CONFIG)/ref_counted_ptr_test
 ref_counted_test: $(BINDIR)/$(CONFIG)/ref_counted_test
+retry_throttle_test: $(BINDIR)/$(CONFIG)/retry_throttle_test
 secure_auth_context_test: $(BINDIR)/$(CONFIG)/secure_auth_context_test
 secure_sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test
 server_builder_plugin_test: $(BINDIR)/$(CONFIG)/server_builder_plugin_test
@@ -1455,7 +1455,6 @@
   $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test \
   $(BINDIR)/$(CONFIG)/grpc_credentials_test \
   $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \
-  $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test \
   $(BINDIR)/$(CONFIG)/grpc_json_token_test \
   $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test \
   $(BINDIR)/$(CONFIG)/grpc_security_connector_test \
@@ -1677,6 +1676,7 @@
   $(BINDIR)/$(CONFIG)/reconnect_interop_server \
   $(BINDIR)/$(CONFIG)/ref_counted_ptr_test \
   $(BINDIR)/$(CONFIG)/ref_counted_test \
+  $(BINDIR)/$(CONFIG)/retry_throttle_test \
   $(BINDIR)/$(CONFIG)/secure_auth_context_test \
   $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \
   $(BINDIR)/$(CONFIG)/server_builder_plugin_test \
@@ -1847,6 +1847,7 @@
   $(BINDIR)/$(CONFIG)/reconnect_interop_server \
   $(BINDIR)/$(CONFIG)/ref_counted_ptr_test \
   $(BINDIR)/$(CONFIG)/ref_counted_test \
+  $(BINDIR)/$(CONFIG)/retry_throttle_test \
   $(BINDIR)/$(CONFIG)/secure_auth_context_test \
   $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \
   $(BINDIR)/$(CONFIG)/server_builder_plugin_test \
@@ -1990,8 +1991,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test || ( echo test grpc_completion_queue_threading_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_credentials_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_credentials_test || ( echo test grpc_credentials_test failed ; exit 1 )
-	$(E) "[RUN]     Testing grpc_invalid_channel_args_test"
-	$(Q) $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test || ( echo test grpc_invalid_channel_args_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_json_token_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_json_token_test || ( echo test grpc_json_token_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_jwt_verifier_test"
@@ -2304,6 +2303,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/ref_counted_ptr_test || ( echo test ref_counted_ptr_test failed ; exit 1 )
 	$(E) "[RUN]     Testing ref_counted_test"
 	$(Q) $(BINDIR)/$(CONFIG)/ref_counted_test || ( echo test ref_counted_test failed ; exit 1 )
+	$(E) "[RUN]     Testing retry_throttle_test"
+	$(Q) $(BINDIR)/$(CONFIG)/retry_throttle_test || ( echo test retry_throttle_test failed ; exit 1 )
 	$(E) "[RUN]     Testing secure_auth_context_test"
 	$(Q) $(BINDIR)/$(CONFIG)/secure_auth_context_test || ( echo test secure_auth_context_test failed ; exit 1 )
 	$(E) "[RUN]     Testing secure_sync_unary_ping_pong_test"
@@ -3497,6 +3498,7 @@
     src/core/tsi/transport_security_adapter.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/filters/client_channel/backup_poller.cc \
     src/core/ext/filters/client_channel/channel_connectivity.cc \
@@ -3554,6 +3556,7 @@
     src/core/ext/census/grpc_context.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
+    src/core/ext/filters/http/client_authority_filter.cc \
     src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
     src/core/ext/filters/workarounds/workaround_utils.cc \
     src/core/plugin_registry/grpc_plugin_registry.cc \
@@ -3798,36 +3801,6 @@
     src/core/lib/transport/transport.cc \
     src/core/lib/transport/transport_op_string.cc \
     src/core/lib/debug/trace.cc \
-    src/core/ext/filters/deadline/deadline_filter.cc \
-    src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
-    src/core/ext/filters/client_channel/backup_poller.cc \
-    src/core/ext/filters/client_channel/channel_connectivity.cc \
-    src/core/ext/filters/client_channel/client_channel.cc \
-    src/core/ext/filters/client_channel/client_channel_factory.cc \
-    src/core/ext/filters/client_channel/client_channel_plugin.cc \
-    src/core/ext/filters/client_channel/connector.cc \
-    src/core/ext/filters/client_channel/http_connect_handshaker.cc \
-    src/core/ext/filters/client_channel/http_proxy.cc \
-    src/core/ext/filters/client_channel/lb_policy.cc \
-    src/core/ext/filters/client_channel/lb_policy_factory.cc \
-    src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
-    src/core/ext/filters/client_channel/parse_address.cc \
-    src/core/ext/filters/client_channel/proxy_mapper.cc \
-    src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
-    src/core/ext/filters/client_channel/resolver.cc \
-    src/core/ext/filters/client_channel/resolver_registry.cc \
-    src/core/ext/filters/client_channel/retry_throttle.cc \
-    src/core/ext/filters/client_channel/subchannel.cc \
-    src/core/ext/filters/client_channel/subchannel_index.cc \
-    src/core/ext/filters/client_channel/uri_parser.cc \
-    src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc \
-    src/core/ext/filters/max_age/max_age_filter.cc \
-    src/core/ext/filters/message_size/message_size_filter.cc \
-    src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \
-    src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \
-    src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
-    src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
     src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc \
     src/core/ext/transport/cronet/transport/cronet_api_dummy.cc \
     src/core/ext/transport/cronet/transport/cronet_transport.cc \
@@ -3859,6 +3832,28 @@
     src/core/ext/filters/http/http_filters_plugin.cc \
     src/core/ext/filters/http/message_compress/message_compress_filter.cc \
     src/core/ext/filters/http/server/http_server_filter.cc \
+    src/core/ext/filters/client_channel/backup_poller.cc \
+    src/core/ext/filters/client_channel/channel_connectivity.cc \
+    src/core/ext/filters/client_channel/client_channel.cc \
+    src/core/ext/filters/client_channel/client_channel_factory.cc \
+    src/core/ext/filters/client_channel/client_channel_plugin.cc \
+    src/core/ext/filters/client_channel/connector.cc \
+    src/core/ext/filters/client_channel/http_connect_handshaker.cc \
+    src/core/ext/filters/client_channel/http_proxy.cc \
+    src/core/ext/filters/client_channel/lb_policy.cc \
+    src/core/ext/filters/client_channel/lb_policy_factory.cc \
+    src/core/ext/filters/client_channel/lb_policy_registry.cc \
+    src/core/ext/filters/client_channel/method_params.cc \
+    src/core/ext/filters/client_channel/parse_address.cc \
+    src/core/ext/filters/client_channel/proxy_mapper.cc \
+    src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
+    src/core/ext/filters/client_channel/resolver.cc \
+    src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/retry_throttle.cc \
+    src/core/ext/filters/client_channel/subchannel.cc \
+    src/core/ext/filters/client_channel/subchannel_index.cc \
+    src/core/ext/filters/client_channel/uri_parser.cc \
+    src/core/ext/filters/deadline/deadline_filter.cc \
     src/core/lib/http/httpcli_security_connector.cc \
     src/core/lib/security/context/security_context.cc \
     src/core/lib/security/credentials/alts/alts_credentials.cc \
@@ -3923,6 +3918,7 @@
     src/core/tsi/transport_security_adapter.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/tsi/alts_transport_security.cc \
     src/core/tsi/fake_transport_security.cc \
@@ -3931,8 +3927,8 @@
     src/core/tsi/ssl/session_cache/ssl_session_openssl.cc \
     src/core/tsi/ssl_transport_security.cc \
     src/core/tsi/transport_security_grpc.cc \
-    src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc \
-    src/core/ext/transport/chttp2/server/chttp2_server.cc \
+    src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
+    src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
     src/core/plugin_registry/grpc_cronet_plugin_registry.cc \
 
 PUBLIC_HEADERS_C += \
@@ -3957,20 +3953,9 @@
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
-    include/grpc/byte_buffer.h \
-    include/grpc/byte_buffer_reader.h \
-    include/grpc/compression.h \
-    include/grpc/fork.h \
-    include/grpc/grpc.h \
-    include/grpc/grpc_posix.h \
-    include/grpc/grpc_security_constants.h \
-    include/grpc/load_reporting.h \
-    include/grpc/slice.h \
-    include/grpc/slice_buffer.h \
-    include/grpc/status.h \
-    include/grpc/support/workaround_list.h \
     include/grpc/grpc_cronet.h \
     include/grpc/grpc_security.h \
+    include/grpc/grpc_security_constants.h \
 
 LIBGRPC_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CRONET_SRC))))
 
@@ -4789,6 +4774,7 @@
     src/core/ext/transport/chttp2/server/chttp2_server.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/filters/client_channel/backup_poller.cc \
     src/core/ext/filters/client_channel/channel_connectivity.cc \
@@ -4838,6 +4824,7 @@
     src/core/ext/census/grpc_context.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
+    src/core/ext/filters/http/client_authority_filter.cc \
     src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
     src/core/ext/filters/workarounds/workaround_utils.cc \
     src/core/plugin_registry/grpc_unsecure_plugin_registry.cc \
@@ -5400,6 +5387,7 @@
     src/cpp/codegen/codegen_init.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/transport/chttp2/transport/bin_decoder.cc \
     src/core/ext/transport/chttp2/transport/bin_encoder.cc \
@@ -9832,6 +9820,7 @@
     test/core/end2end/tests/bad_ping.cc \
     test/core/end2end/tests/binary_metadata.cc \
     test/core/end2end/tests/call_creds.cc \
+    test/core/end2end/tests/call_host_override.cc \
     test/core/end2end/tests/cancel_after_accept.cc \
     test/core/end2end/tests/cancel_after_client_done.cc \
     test/core/end2end/tests/cancel_after_invoke.cc \
@@ -9946,6 +9935,7 @@
     test/core/end2end/tests/bad_hostname.cc \
     test/core/end2end/tests/bad_ping.cc \
     test/core/end2end/tests/binary_metadata.cc \
+    test/core/end2end/tests/call_host_override.cc \
     test/core/end2end/tests/cancel_after_accept.cc \
     test/core/end2end/tests/cancel_after_client_done.cc \
     test/core/end2end/tests/cancel_after_invoke.cc \
@@ -11969,38 +11959,6 @@
 endif
 
 
-GRPC_INVALID_CHANNEL_ARGS_TEST_SRC = \
-    test/core/surface/invalid_channel_args_test.cc \
-
-GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_INVALID_CHANNEL_ARGS_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test: $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/surface/invalid_channel_args_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_grpc_invalid_channel_args_test: $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 GRPC_JSON_TOKEN_TEST_SRC = \
     test/core/security/json_token_test.cc \
 
@@ -14625,7 +14583,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alarm_test: protobuf_dep_error
 
@@ -14668,7 +14626,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_counter_test: protobuf_dep_error
 
@@ -14711,7 +14669,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_crypt_test: protobuf_dep_error
 
@@ -14754,7 +14712,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_crypter_test: protobuf_dep_error
 
@@ -14797,7 +14755,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_frame_handler_test: protobuf_dep_error
 
@@ -14841,7 +14799,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_frame_protector_test: protobuf_dep_error
 
@@ -14886,7 +14844,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_grpc_record_protocol_test: protobuf_dep_error
 
@@ -14929,7 +14887,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_handshaker_client_test: protobuf_dep_error
 
@@ -14972,7 +14930,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_handshaker_service_api_test: protobuf_dep_error
 
@@ -15015,7 +14973,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_iovec_record_protocol_test: protobuf_dep_error
 
@@ -15058,7 +15016,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_security_connector_test: protobuf_dep_error
 
@@ -15101,7 +15059,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_tsi_handshaker_test: protobuf_dep_error
 
@@ -15144,7 +15102,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_tsi_utils_test: protobuf_dep_error
 
@@ -15187,7 +15145,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_zero_copy_grpc_protector_test: protobuf_dep_error
 
@@ -15230,7 +15188,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/async_end2end_test: protobuf_dep_error
 
@@ -15273,7 +15231,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/auth_property_iterator_test: protobuf_dep_error
 
@@ -15316,7 +15274,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/backoff_test: protobuf_dep_error
 
@@ -15359,7 +15317,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bdp_estimator_test: protobuf_dep_error
 
@@ -15402,7 +15360,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_arena: protobuf_dep_error
 
@@ -15446,7 +15404,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_call_create: protobuf_dep_error
 
@@ -15490,7 +15448,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_chttp2_hpack: protobuf_dep_error
 
@@ -15534,7 +15492,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_chttp2_transport: protobuf_dep_error
 
@@ -15578,7 +15536,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_closure: protobuf_dep_error
 
@@ -15622,7 +15580,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_cq: protobuf_dep_error
 
@@ -15666,7 +15624,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: protobuf_dep_error
 
@@ -15710,7 +15668,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_error: protobuf_dep_error
 
@@ -15754,7 +15712,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong: protobuf_dep_error
 
@@ -15798,7 +15756,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump: protobuf_dep_error
 
@@ -15842,7 +15800,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_fullstack_trickle: protobuf_dep_error
 
@@ -15886,7 +15844,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong: protobuf_dep_error
 
@@ -15930,7 +15888,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_metadata: protobuf_dep_error
 
@@ -15974,7 +15932,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_pollset: protobuf_dep_error
 
@@ -16018,7 +15976,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/byte_stream_test: protobuf_dep_error
 
@@ -16061,7 +16019,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/channel_arguments_test: protobuf_dep_error
 
@@ -16104,7 +16062,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/channel_filter_test: protobuf_dep_error
 
@@ -16148,7 +16106,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/channel_trace_test: protobuf_dep_error
 
@@ -16194,7 +16152,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/check_gcp_environment_linux_test: protobuf_dep_error
 
@@ -16237,7 +16195,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test: protobuf_dep_error
 
@@ -16280,7 +16238,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test: protobuf_dep_error
 
@@ -16323,7 +16281,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cli_call_test: protobuf_dep_error
 
@@ -16367,7 +16325,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/client_channel_stress_test: protobuf_dep_error
 
@@ -16413,7 +16371,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/client_crash_test: protobuf_dep_error
 
@@ -16456,7 +16414,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/client_crash_test_server: protobuf_dep_error
 
@@ -16499,7 +16457,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/client_lb_end2end_test: protobuf_dep_error
 
@@ -16547,7 +16505,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/codegen_test_full: protobuf_dep_error
 
@@ -16607,7 +16565,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/codegen_test_minimal: protobuf_dep_error
 
@@ -16664,7 +16622,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/credentials_test: protobuf_dep_error
 
@@ -16707,7 +16665,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test: protobuf_dep_error
 
@@ -16750,7 +16708,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cxx_slice_test: protobuf_dep_error
 
@@ -16793,7 +16751,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cxx_string_ref_test: protobuf_dep_error
 
@@ -16836,7 +16794,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cxx_time_test: protobuf_dep_error
 
@@ -16879,7 +16837,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/end2end_test: protobuf_dep_error
 
@@ -16923,7 +16881,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/error_details_test: protobuf_dep_error
 
@@ -16969,7 +16927,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/exception_test: protobuf_dep_error
 
@@ -17012,7 +16970,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/filter_end2end_test: protobuf_dep_error
 
@@ -17055,7 +17013,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/generic_end2end_test: protobuf_dep_error
 
@@ -17099,7 +17057,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/golden_file_test: protobuf_dep_error
 
@@ -17145,7 +17103,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test: protobuf_dep_error
 
@@ -17188,7 +17146,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_cli: protobuf_dep_error
 
@@ -17223,7 +17181,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_cpp_plugin: protobuf_dep_error
 
@@ -17254,7 +17212,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_csharp_plugin: protobuf_dep_error
 
@@ -17285,7 +17243,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_node_plugin: protobuf_dep_error
 
@@ -17316,7 +17274,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin: protobuf_dep_error
 
@@ -17347,7 +17305,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_php_plugin: protobuf_dep_error
 
@@ -17378,7 +17336,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_python_plugin: protobuf_dep_error
 
@@ -17409,7 +17367,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_ruby_plugin: protobuf_dep_error
 
@@ -17450,7 +17408,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_tool_test: protobuf_dep_error
 
@@ -17499,7 +17457,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpclb_api_test: protobuf_dep_error
 
@@ -17546,7 +17504,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpclb_end2end_test: protobuf_dep_error
 
@@ -17592,7 +17550,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/h2_ssl_cert_test: protobuf_dep_error
 
@@ -17635,7 +17593,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/h2_ssl_session_reuse_test: protobuf_dep_error
 
@@ -17678,7 +17636,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/health_service_end2end_test: protobuf_dep_error
 
@@ -17717,7 +17675,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/http2_client: protobuf_dep_error
 
@@ -17752,7 +17710,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/hybrid_end2end_test: protobuf_dep_error
 
@@ -17795,7 +17753,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/inlined_vector_test: protobuf_dep_error
 
@@ -17838,7 +17796,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test: protobuf_dep_error
 
@@ -17877,7 +17835,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/interop_client: protobuf_dep_error
 
@@ -17908,7 +17866,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/interop_server: protobuf_dep_error
 
@@ -17943,7 +17901,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/interop_test: protobuf_dep_error
 
@@ -17986,7 +17944,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/json_run_localhost: protobuf_dep_error
 
@@ -18029,7 +17987,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/memory_test: protobuf_dep_error
 
@@ -18073,7 +18031,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/metrics_client: protobuf_dep_error
 
@@ -18119,7 +18077,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/mock_test: protobuf_dep_error
 
@@ -18162,7 +18120,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/nonblocking_test: protobuf_dep_error
 
@@ -18205,7 +18163,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/noop-benchmark: protobuf_dep_error
 
@@ -18249,7 +18207,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/orphanable_test: protobuf_dep_error
 
@@ -18292,7 +18250,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/proto_server_reflection_test: protobuf_dep_error
 
@@ -18335,7 +18293,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/proto_utils_test: protobuf_dep_error
 
@@ -18378,7 +18336,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/qps_interarrival_test: protobuf_dep_error
 
@@ -18421,7 +18379,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/qps_json_driver: protobuf_dep_error
 
@@ -18464,7 +18422,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/qps_openloop_test: protobuf_dep_error
 
@@ -18507,7 +18465,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/qps_worker: protobuf_dep_error
 
@@ -18553,7 +18511,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/reconnect_interop_client: protobuf_dep_error
 
@@ -18606,7 +18564,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/reconnect_interop_server: protobuf_dep_error
 
@@ -18656,7 +18614,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/ref_counted_ptr_test: protobuf_dep_error
 
@@ -18699,7 +18657,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/ref_counted_test: protobuf_dep_error
 
@@ -18725,6 +18683,49 @@
 endif
 
 
+RETRY_THROTTLE_TEST_SRC = \
+    test/core/client_channel/retry_throttle_test.cc \
+
+RETRY_THROTTLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RETRY_THROTTLE_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/retry_throttle_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/retry_throttle_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/retry_throttle_test: $(PROTOBUF_DEP) $(RETRY_THROTTLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(RETRY_THROTTLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/retry_throttle_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/client_channel/retry_throttle_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_retry_throttle_test: $(RETRY_THROTTLE_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(RETRY_THROTTLE_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 SECURE_AUTH_CONTEXT_TEST_SRC = \
     test/cpp/common/secure_auth_context_test.cc \
 
@@ -18742,7 +18743,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/secure_auth_context_test: protobuf_dep_error
 
@@ -18785,7 +18786,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test: protobuf_dep_error
 
@@ -18828,7 +18829,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_builder_plugin_test: protobuf_dep_error
 
@@ -18873,7 +18874,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_builder_test: protobuf_dep_error
 
@@ -18921,7 +18922,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_context_test_spouse_test: protobuf_dep_error
 
@@ -18964,7 +18965,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_crash_test: protobuf_dep_error
 
@@ -19007,7 +19008,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_crash_test_client: protobuf_dep_error
 
@@ -19050,7 +19051,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_early_return_test: protobuf_dep_error
 
@@ -19095,7 +19096,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_request_call_test: protobuf_dep_error
 
@@ -19143,7 +19144,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/shutdown_test: protobuf_dep_error
 
@@ -19186,7 +19187,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/slice_hash_table_test: protobuf_dep_error
 
@@ -19229,7 +19230,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/slice_weak_hash_table_test: protobuf_dep_error
 
@@ -19272,7 +19273,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/stats_test: protobuf_dep_error
 
@@ -19315,7 +19316,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/status_metadata_test: protobuf_dep_error
 
@@ -19358,7 +19359,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/status_util_test: protobuf_dep_error
 
@@ -19401,7 +19402,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/streaming_throughput_test: protobuf_dep_error
 
@@ -19451,7 +19452,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/stress_test: protobuf_dep_error
 
@@ -19512,7 +19513,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/thread_manager_test: protobuf_dep_error
 
@@ -19555,7 +19556,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/thread_stress_test: protobuf_dep_error
 
@@ -19598,7 +19599,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/transport_pid_controller_test: protobuf_dep_error
 
@@ -19641,7 +19642,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/transport_security_common_api_test: protobuf_dep_error
 
@@ -19684,7 +19685,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/writes_per_rpc_test: protobuf_dep_error
 
@@ -19857,7 +19858,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_crypto_test_data: protobuf_dep_error
 
@@ -19897,7 +19898,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_asn1_test: protobuf_dep_error
 
@@ -19937,7 +19938,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_base64_test: protobuf_dep_error
 
@@ -19977,7 +19978,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_bio_test: protobuf_dep_error
 
@@ -20017,7 +20018,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_buf_test: protobuf_dep_error
 
@@ -20057,7 +20058,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_bytestring_test: protobuf_dep_error
 
@@ -20097,7 +20098,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_chacha_test: protobuf_dep_error
 
@@ -20137,7 +20138,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_aead_test: protobuf_dep_error
 
@@ -20177,7 +20178,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_cipher_test: protobuf_dep_error
 
@@ -20217,7 +20218,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_cmac_test: protobuf_dep_error
 
@@ -20257,7 +20258,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_compiler_test: protobuf_dep_error
 
@@ -20297,7 +20298,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_constant_time_test: protobuf_dep_error
 
@@ -20337,7 +20338,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ed25519_test: protobuf_dep_error
 
@@ -20377,7 +20378,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_spake25519_test: protobuf_dep_error
 
@@ -20417,7 +20418,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_x25519_test: protobuf_dep_error
 
@@ -20457,7 +20458,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_dh_test: protobuf_dep_error
 
@@ -20497,7 +20498,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_digest_test: protobuf_dep_error
 
@@ -20537,7 +20538,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_dsa_test: protobuf_dep_error
 
@@ -20577,7 +20578,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ecdh_test: protobuf_dep_error
 
@@ -20617,7 +20618,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_err_test: protobuf_dep_error
 
@@ -20657,7 +20658,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_evp_extra_test: protobuf_dep_error
 
@@ -20697,7 +20698,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_evp_test: protobuf_dep_error
 
@@ -20737,7 +20738,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pbkdf_test: protobuf_dep_error
 
@@ -20777,7 +20778,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_scrypt_test: protobuf_dep_error
 
@@ -20817,7 +20818,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_aes_test: protobuf_dep_error
 
@@ -20857,7 +20858,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_bn_test: protobuf_dep_error
 
@@ -20897,7 +20898,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ec_test: protobuf_dep_error
 
@@ -20937,7 +20938,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_p256-x86_64_test: protobuf_dep_error
 
@@ -20977,7 +20978,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ecdsa_test: protobuf_dep_error
 
@@ -21017,7 +21018,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_gcm_test: protobuf_dep_error
 
@@ -21057,7 +21058,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ctrdrbg_test: protobuf_dep_error
 
@@ -21097,7 +21098,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_hkdf_test: protobuf_dep_error
 
@@ -21137,7 +21138,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_hmac_test: protobuf_dep_error
 
@@ -21177,7 +21178,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_lhash_test: protobuf_dep_error
 
@@ -21217,7 +21218,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_obj_test: protobuf_dep_error
 
@@ -21257,7 +21258,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test: protobuf_dep_error
 
@@ -21297,7 +21298,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pkcs12_test: protobuf_dep_error
 
@@ -21337,7 +21338,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pkcs8_test: protobuf_dep_error
 
@@ -21377,7 +21378,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_poly1305_test: protobuf_dep_error
 
@@ -21417,7 +21418,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pool_test: protobuf_dep_error
 
@@ -21457,7 +21458,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_refcount_test: protobuf_dep_error
 
@@ -21497,7 +21498,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_rsa_test: protobuf_dep_error
 
@@ -21537,7 +21538,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_file_test_gtest: protobuf_dep_error
 
@@ -21577,7 +21578,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_gtest_main: protobuf_dep_error
 
@@ -21617,7 +21618,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_thread_test: protobuf_dep_error
 
@@ -21657,7 +21658,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_x509_test: protobuf_dep_error
 
@@ -21697,7 +21698,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_tab_test: protobuf_dep_error
 
@@ -21737,7 +21738,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_v3name_test: protobuf_dep_error
 
@@ -21777,7 +21778,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_span_test: protobuf_dep_error
 
@@ -21817,7 +21818,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ssl_test: protobuf_dep_error
 
@@ -23051,7 +23052,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure: protobuf_dep_error
 
@@ -23094,7 +23095,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/resolver_component_test: protobuf_dep_error
 
@@ -23137,7 +23138,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure: protobuf_dep_error
 
@@ -23180,7 +23181,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker: protobuf_dep_error
 
@@ -23223,7 +23224,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/address_sorting_test_unsecure: protobuf_dep_error
 
@@ -23266,7 +23267,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/address_sorting_test: protobuf_dep_error
 
diff --git a/Rakefile b/Rakefile
index 1eac37d..0068a3b 100755
--- a/Rakefile
+++ b/Rakefile
@@ -23,6 +23,12 @@
 
 # Add the extension compiler task
 Rake::ExtensionTask.new('grpc_c', spec) do |ext|
+  unless RUBY_PLATFORM =~ /darwin/
+    # TODO: also set "no_native to true" for mac if possible. As is,
+    # "no_native" can only be set if the RUBY_PLATFORM doing
+    # cross-compilation is contained in the "ext.cross_platform" array.
+    ext.no_native = true
+  end
   ext.source_pattern = '**/*.{c,h}'
   ext.ext_dir = File.join('src', 'ruby', 'ext', 'grpc')
   ext.lib_dir = File.join('src', 'ruby', 'lib', 'grpc')
diff --git a/bazel/generate_cc.bzl b/bazel/generate_cc.bzl
index e610123..ae747aa 100644
--- a/bazel/generate_cc.bzl
+++ b/bazel/generate_cc.bzl
@@ -10,7 +10,16 @@
   includes = [f for src in ctx.attr.srcs for f in src.proto.transitive_imports]
   outs = []
   # label_len is length of the path from WORKSPACE root to the location of this build file
-  label_len = len(ctx.label.package) + 1
+  label_len = 0
+  # proto_root is the directory relative to which generated include paths should be
+  proto_root = ""
+  if ctx.label.package:
+    # The +1 is for the trailing slash.
+    label_len += len(ctx.label.package) + 1
+  if ctx.label.workspace_root:
+    label_len += len(ctx.label.workspace_root) + 1
+    proto_root = "/" + ctx.label.workspace_root
+
   if ctx.executable.plugin:
     outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.h" for proto in protos]
     outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.cc" for proto in protos]
@@ -20,7 +29,7 @@
     outs += [proto.path[label_len:-len(".proto")] + ".pb.h" for proto in protos]
     outs += [proto.path[label_len:-len(".proto")] + ".pb.cc" for proto in protos]
   out_files = [ctx.new_file(out) for out in outs]
-  dir_out = str(ctx.genfiles_dir.path)
+  dir_out = str(ctx.genfiles_dir.path + proto_root)
 
   arguments = []
   if ctx.executable.plugin:
@@ -33,7 +42,20 @@
   else:
     arguments += ["--cpp_out=" + ",".join(ctx.attr.flags) + ":" + dir_out]
     additional_input = []
-  arguments += ["-I{0}={0}".format(include.path) for include in includes]
+
+  # Import protos relative to their workspace root so that protoc prints the
+  # right include paths.
+  for include in includes:
+    directory = include.path
+    if directory.startswith("external"):
+      external_sep = directory.find("/")
+      repository_sep = directory.find("/", external_sep + 1)
+      arguments += ["--proto_path=" + directory[:repository_sep]]
+    else:
+      arguments += ["--proto_path=."]
+  # Include the output directory so that protoc puts the generated code in the
+  # right directory.
+  arguments += ["--proto_path={0}{1}".format(dir_out, proto_root)]
   arguments += [proto.path for proto in protos]
 
   # create a list of well known proto files if the argument is non-None
diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl
index a441c3f..6b3a553 100644
--- a/bazel/grpc_deps.bzl
+++ b/bazel/grpc_deps.bzl
@@ -57,6 +57,16 @@
         actual = "@com_github_gflags_gflags//:gflags",
     )
 
+    native.bind(
+        name = "grpc_cpp_plugin",
+        actual = "@com_github_grpc_grpc//:grpc_cpp_plugin"
+    )
+
+    native.bind(
+        name = "grpc++_codegen_proto",
+        actual = "@com_github_grpc_grpc//:grpc++_codegen_proto"
+    )
+
     if "boringssl" not in native.existing_rules():
         native.http_archive(
             name = "boringssl",
diff --git a/build.yaml b/build.yaml
index 88f2283..6a6f234 100644
--- a/build.yaml
+++ b/build.yaml
@@ -534,6 +534,14 @@
   uses:
   - grpc_codegen
   - grpc_trace_headers
+- name: grpc_client_authority_filter
+  headers:
+  - src/core/ext/filters/http/client_authority_filter.h
+  src:
+  - src/core/ext/filters/http/client_authority_filter.cc
+  plugin: grpc_client_authority_filter
+  uses:
+  - grpc_base
 - name: grpc_client_channel
   headers:
   - src/core/ext/filters/client_channel/backup_poller.h
@@ -929,8 +937,10 @@
   - gpr
 - name: grpc_transport_chttp2_client_connector
   headers:
+  - src/core/ext/transport/chttp2/client/authority.h
   - src/core/ext/transport/chttp2/client/chttp2_connector.h
   src:
+  - src/core/ext/transport/chttp2/client/authority.cc
   - src/core/ext/transport/chttp2/client/chttp2_connector.cc
   uses:
   - grpc_transport_chttp2
@@ -1389,6 +1399,7 @@
   - grpc_max_age_filter
   - grpc_message_size_filter
   - grpc_deadline_filter
+  - grpc_client_authority_filter
   - grpc_workaround_cronet_compression_filter
   - grpc_server_backward_compatibility
   generate_plugin_registry: true
@@ -1407,17 +1418,9 @@
   dll: true
   filegroups:
   - grpc_base
-  - grpc_base_headers
-  - grpc_deadline_filter
-  - grpc_lb_policy_pick_first
-  - grpc_max_age_filter
-  - grpc_message_size_filter
-  - grpc_resolver_dns_native
-  - grpc_resolver_sockaddr
-  - grpc_server_load_reporting
   - grpc_transport_cronet_client_secure
   - grpc_transport_chttp2_client_secure
-  - grpc_transport_chttp2_server_secure
+  - grpc_server_load_reporting
   generate_plugin_registry: true
   platforms:
   - linux
@@ -1499,6 +1502,7 @@
   - grpc_max_age_filter
   - grpc_message_size_filter
   - grpc_deadline_filter
+  - grpc_client_authority_filter
   - grpc_workaround_cronet_compression_filter
   - grpc_server_backward_compatibility
   generate_plugin_registry: true
@@ -2613,17 +2617,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: grpc_invalid_channel_args_test
-  build: test
-  language: c
-  src:
-  - test/core/surface/invalid_channel_args_test.cc
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
-  uses_polling: false
 - name: grpc_json_token_test
   build: test
   language: c
@@ -4996,6 +4989,18 @@
   - gpr
   uses:
   - grpc++_test
+- name: retry_throttle_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - test/core/client_channel/retry_throttle_test.cc
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  uses_polling: false
 - name: secure_auth_context_test
   gtest: true
   build: test
diff --git a/config.m4 b/config.m4
index d7cda0b..0dc4825 100644
--- a/config.m4
+++ b/config.m4
@@ -8,6 +8,7 @@
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
+  PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/address_sorting/include)
 
   LIBS="-lpthread $LIBS"
 
@@ -323,6 +324,7 @@
     src/core/tsi/transport_security_adapter.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/filters/client_channel/backup_poller.cc \
     src/core/ext/filters/client_channel/channel_connectivity.cc \
@@ -380,6 +382,7 @@
     src/core/ext/census/grpc_context.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
+    src/core/ext/filters/http/client_authority_filter.cc \
     src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
     src/core/ext/filters/workarounds/workaround_utils.cc \
     src/core/plugin_registry/grpc_plugin_registry.cc \
diff --git a/config.w32 b/config.w32
index 5e80781..bb9cb3f 100644
--- a/config.w32
+++ b/config.w32
@@ -300,6 +300,7 @@
     "src\\core\\tsi\\transport_security_adapter.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create_posix.cc " +
+    "src\\core\\ext\\transport\\chttp2\\client\\authority.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\chttp2_connector.cc " +
     "src\\core\\ext\\filters\\client_channel\\backup_poller.cc " +
     "src\\core\\ext\\filters\\client_channel\\channel_connectivity.cc " +
@@ -357,6 +358,7 @@
     "src\\core\\ext\\census\\grpc_context.cc " +
     "src\\core\\ext\\filters\\max_age\\max_age_filter.cc " +
     "src\\core\\ext\\filters\\message_size\\message_size_filter.cc " +
+    "src\\core\\ext\\filters\\http\\client_authority_filter.cc " +
     "src\\core\\ext\\filters\\workarounds\\workaround_cronet_compression_filter.cc " +
     "src\\core\\ext\\filters\\workarounds\\workaround_utils.cc " +
     "src\\core\\plugin_registry\\grpc_plugin_registry.cc " +
diff --git a/doc/PROTOCOL-WEB.md b/doc/PROTOCOL-WEB.md
index c31a048..5100c9b 100644
--- a/doc/PROTOCOL-WEB.md
+++ b/doc/PROTOCOL-WEB.md
@@ -29,7 +29,7 @@
 * evolve over time, mainly to optimize for browser clients or support
 web-specific features such as CORS, XSRF
 * become optional (in 1-2 years) when browsers are able to speak the native
-gRPC protocol via the new [whatwg fetch/streams API](https://github.com/whatwg/fetch)
+gRPC protocol via the new [whatwg streams API](https://github.com/whatwg/streams)
 
 # Protocol differences vs [gRPC over HTTP2](PROTOCOL-HTTP2.md)
 
@@ -106,19 +106,6 @@
 
 # Other features
 
-Compression
-
-* Full-body compression is supported and expected for all unary
-requests/responses. The compression/decompression will be done
-by browsers, using standard Content-Encoding headers
-  * “grpc-encoding” header is not used
-  * SDCH, Brotli will be supported
-* Message-level compression for streamed requests/responses is not supported
-because manual compression/decompression is prohibitively expensive using JS
-  * Per-message compression may be feasible in future with wasm
-
----
-
 Retries, caching
 
 * Will spec out the support after their respective gRPC spec extensions
@@ -128,24 +115,6 @@
 
 ---
 
-Security
-
-* XSRF, XSS etc to be specified
-
----
-
-CORS preflight
-
-* Should follow the [CORS spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control)
-  * Access-Control-Allow-Credentials to allow Authorization headers
-  * Access-Control-Allow-Methods to allow POST and (preflight) OPTIONS only
-  * Access-Control-Allow-Headers to whatever the preflight request carries
-* The client library may support header overwrites to avoid preflight
-  * https://github.com/whatwg/fetch/issues/210
-* CSP support to be specified
-
----
-
 Keep-alive
 
 * HTTP/2 PING is not supported or used
@@ -165,3 +134,8 @@
 
 * Special headers may be introduced to support features that may break compatiblity.
 
+---
+
+Browser-specific features
+
+* For features that are unique to browser or HTML clients, check the [spec doc](https://github.com/grpc/grpc-web/blob/master/PROTOCOL-WEB.md) published in the grpc/grpc-web repo.
diff --git a/examples/cpp/helloworld/CMakeLists.txt b/examples/cpp/helloworld/CMakeLists.txt
index c3ce4d5..d0f705f 100644
--- a/examples/cpp/helloworld/CMakeLists.txt
+++ b/examples/cpp/helloworld/CMakeLists.txt
@@ -1,7 +1,24 @@
-# Minimum CMake required

+# Copyright 2018 gRPC authors.

+#

+# Licensed under the Apache License, Version 2.0 (the "License");

+# you may not use this file except in compliance with the License.

+# You may obtain a copy of the License at

+#

+#     http://www.apache.org/licenses/LICENSE-2.0

+#

+# Unless required by applicable law or agreed to in writing, software

+# distributed under the License is distributed on an "AS IS" BASIS,

+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+# See the License for the specific language governing permissions and

+# limitations under the License.

+#

+# cmake build file for C++ helloworld example.

+# Assumes protobuf and gRPC have been installed using cmake.

+# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build

+# that automatically builds all the dependencies before building helloworld.

+

 cmake_minimum_required(VERSION 2.8)

 

-# Project

 project(HelloWorld C CXX)

 

 if(NOT MSVC)

@@ -10,57 +27,76 @@
   add_definitions(-D_WIN32_WINNT=0x600)

 endif()

 

-# Protobuf

-# NOTE: we cannot use "CONFIG" mode here because protobuf-config.cmake

-# is broken when used with CMAKE_INSTALL_PREFIX

-find_package(Protobuf REQUIRED)

-message(STATUS "Using protobuf ${protobuf_VERSION}")

-

-# {Protobuf,PROTOBUF}_FOUND is defined based on find_package type ("MODULE" vs "CONFIG").

-# For "MODULE", the case has also changed between cmake 3.5 and 3.6.

-# We use the legacy uppercase version for *_LIBRARIES AND *_INCLUDE_DIRS variables

-# as newer cmake versions provide them too for backward compatibility.

-if(Protobuf_FOUND OR PROTOBUF_FOUND)

-  if(TARGET protobuf::libprotobuf)

-    set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)

-  else()

-    set(_PROTOBUF_LIBPROTOBUF ${PROTOBUF_LIBRARIES})

-    include_directories(${PROTOBUF_INCLUDE_DIRS})

-  endif()

-  if(TARGET protobuf::protoc)

-    set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)

-  else()

-    set(_PROTOBUF_PROTOC ${PROTOBUF_PROTOC_EXECUTABLE})

-  endif()

+if(GRPC_AS_SUBMODULE)

+  # One way to build a projects that uses gRPC is to just include the

+  # entire gRPC project tree via "add_subdirectory".

+  # This approach is very simple to use, but the are some potential

+  # disadvantages:

+  # * it includes gRPC's CMakeLists.txt directly into your build script

+  #   without and that can make gRPC's internal setting interfere with your

+  #   own build.

+  # * depending on what's installed on your system, the contents of submodules

+  #   in gRPC's third_party/* might need to be available (and there might be

+  #   additional prerequisites required to build them). Consider using

+  #   the gRPC_*_PROVIDER options to fine-tune the expected behavior.

+  #

+  # A more robust approach to add dependency on gRPC is using

+  # cmake's ExternalProject_Add (see cmake_externalproject/CMakeLists.txt).

+  

+  # Include the gRPC's cmake build (normally grpc source code would live

+  # in a git submodule called "third_party/grpc", but this example lives in

+  # the same repository as gRPC sources, so we just look a few directories up)

+  add_subdirectory(../../.. ${CMAKE_CURRENT_BINARY_DIR}/grpc EXCLUDE_FROM_ALL)

+  message(STATUS "Using gRPC via add_subdirectory.")

+  

+  # After using add_subdirectory, we can now use the grpc targets directly from

+  # this build.

+  set(_PROTOBUF_LIBPROTOBUF libprotobuf)

+  set(_PROTOBUF_PROTOC $<TARGET_FILE:protoc>)

+  set(_GRPC_GRPCPP_UNSECURE grpc++_unsecure)

+  set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:grpc_cpp_plugin>)

 else()

-  message(WARNING "Failed to locate libprotobuf and protoc!")

+  # This branch assumes that gRPC and all its dependencies are already installed

+  # on this system, so they can be located by find_package().

+

+  # Find Protobuf installation

+  # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation.

+  set(protobuf_MODULE_COMPATIBLE TRUE)

+  find_package(Protobuf CONFIG REQUIRED)

+  message(STATUS "Using protobuf ${protobuf_VERSION}")

+

+  set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)

+  set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)

+

+  # Find gRPC installation

+  # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.

+  find_package(gRPC CONFIG REQUIRED)

+  message(STATUS "Using gRPC ${gRPC_VERSION}")

+

+  set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure)

+  set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)

 endif()

 

-# gRPC

-find_package(gRPC CONFIG REQUIRED)

-message(STATUS "Using gRPC ${gRPC_VERSION}")

-

-# gRPC C++ plugin

-get_target_property(gRPC_CPP_PLUGIN_EXECUTABLE gRPC::grpc_cpp_plugin

-    IMPORTED_LOCATION_RELEASE)

-

 # Proto file

 get_filename_component(hw_proto "../../protos/helloworld.proto" ABSOLUTE)

 get_filename_component(hw_proto_path "${hw_proto}" PATH)

 

 # Generated sources

-protobuf_generate_cpp(hw_proto_srcs hw_proto_hdrs "${hw_proto}")

+set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.cc")

+set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.h")

 set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc")

 set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h")

 add_custom_command(

-      OUTPUT "${hw_grpc_srcs}" "${hw_grpc_hdrs}"

+      OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}"

       COMMAND ${_PROTOBUF_PROTOC}

-      ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" -I "${hw_proto_path}"

-        --plugin=protoc-gen-grpc="${gRPC_CPP_PLUGIN_EXECUTABLE}"

+      ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"

+        --cpp_out "${CMAKE_CURRENT_BINARY_DIR}"

+        -I "${hw_proto_path}"

+        --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"

         "${hw_proto}"

       DEPENDS "${hw_proto}")

 

-# Generated include directory

+# Include generated *.pb.h files

 include_directories("${CMAKE_CURRENT_BINARY_DIR}")

 

 # Targets greeter_[async_](client|server)

@@ -71,6 +107,6 @@
     ${hw_proto_srcs}

     ${hw_grpc_srcs})

   target_link_libraries(${_target}

-    ${_PROTOBUF_LIBPROTOBUF}

-    gRPC::grpc++_unsecure)

+    ${_GRPC_GRPCPP_UNSECURE}

+    ${_PROTOBUF_LIBPROTOBUF})

 endforeach()

diff --git a/examples/cpp/helloworld/cmake_externalproject/CMakeLists.txt b/examples/cpp/helloworld/cmake_externalproject/CMakeLists.txt
new file mode 100644
index 0000000..9fbdf07
--- /dev/null
+++ b/examples/cpp/helloworld/cmake_externalproject/CMakeLists.txt
@@ -0,0 +1,116 @@
+# Copyright 2018 gRPC authors.

+#

+# Licensed under the Apache License, Version 2.0 (the "License");

+# you may not use this file except in compliance with the License.

+# You may obtain a copy of the License at

+#

+#     http://www.apache.org/licenses/LICENSE-2.0

+#

+# Unless required by applicable law or agreed to in writing, software

+# distributed under the License is distributed on an "AS IS" BASIS,

+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+# See the License for the specific language governing permissions and

+# limitations under the License.

+#

+# cmake "superbuild" file for C++ helloworld example.

+# This build file demonstrates how to build the helloworld project

+# and all its dependencies in a single cmake build (hence "superbuild")

+# that is easy to build and maintain.

+# cmake's ExternalProject_Add() is used to import all the sub-projects,

+# including the "helloworld" project itself.

+# See https://blog.kitware.com/cmake-superbuilds-git-submodules/

+

+cmake_minimum_required(VERSION 2.8)

+

+# Project

+project(HelloWorld-SuperBuild C CXX)

+

+include(ExternalProject)

+

+# Builds c-ares project from the git submodule.

+# Note: For all external projects, instead of using checked-out code, one could

+# specify GIT_REPOSITORY and GIT_TAG to have cmake download the dependency directly,

+# without needing to add a submodule to your project.

+ExternalProject_Add(c-ares

+  PREFIX c-ares

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../third_party/cares/cares"

+  CMAKE_CACHE_ARGS

+        -DCARES_SHARED:BOOL=OFF

+        -DCARES_STATIC:BOOL=ON

+        -DCARES_STATIC_PIC:BOOL=ON

+        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/c-ares

+)

+

+# Builds protobuf project from the git submodule.

+ExternalProject_Add(protobuf

+  PREFIX protobuf

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../third_party/protobuf/cmake"

+  CMAKE_CACHE_ARGS

+        -Dprotobuf_BUILD_TESTS:BOOL=OFF

+        -Dprotobuf_WITH_ZLIB:BOOL=OFF

+        -Dprotobuf_MSVC_STATIC_RUNTIME:BOOL=OFF

+        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/protobuf

+)

+

+# Builds zlib project from the git submodule.

+ExternalProject_Add(zlib

+  PREFIX zlib

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../third_party/zlib"

+  CMAKE_CACHE_ARGS

+        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/zlib

+)

+

+# the location where protobuf-config.cmake will be installed varies by platform

+if (WIN32)

+  set(_FINDPACKAGE_PROTOBUF_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/protobuf/cmake")

+else()

+  set(_FINDPACKAGE_PROTOBUF_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/protobuf/lib/cmake/protobuf")

+endif()

+

+# if OPENSSL_ROOT_DIR is set, propagate that hint path to the external projects with OpenSSL dependency.

+set(_CMAKE_ARGS_OPENSSL_ROOT_DIR "")

+if (OPENSSL_ROOT_DIR)

+  set(_CMAKE_ARGS_OPENSSL_ROOT_DIR "-DOPENSSL_ROOT_DIR:PATH=${OPENSSL_ROOT_DIR}")

+endif()

+

+# Builds gRPC based on locally checked-out sources and set arguments so that all the dependencies

+# are correctly located.

+ExternalProject_Add(grpc

+  PREFIX grpc

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../.."

+  CMAKE_CACHE_ARGS

+        -DgRPC_INSTALL:BOOL=ON

+        -DgRPC_BUILD_TESTS:BOOL=OFF

+        -DgRPC_PROTOBUF_PROVIDER:STRING=package

+        -DgRPC_PROTOBUF_PACKAGE_TYPE:STRING=CONFIG

+        -DProtobuf_DIR:PATH=${_FINDPACKAGE_PROTOBUF_CONFIG_DIR}

+        -DgRPC_ZLIB_PROVIDER:STRING=package

+        -DZLIB_ROOT:STRING=${CMAKE_CURRENT_BINARY_DIR}/zlib

+        -DgRPC_CARES_PROVIDER:STRING=package

+        -Dc-ares_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}/c-ares/lib/cmake/c-ares

+        -DgRPC_SSL_PROVIDER:STRING=package

+        ${_CMAKE_ARGS_OPENSSL_ROOT_DIR}

+        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/grpc

+  DEPENDS c-ares protobuf zlib

+)

+

+# Build the helloworld projects itself using a CMakeLists.txt that assumes all the dependencies

+# have already been installed.

+# Even though helloworld is not really an "external project" from perspective of this build,

+# we are still importing it using ExternalProject_Add because that allows us to use find_package()

+# to locate all the dependencies (if we were building helloworld directly in this build we,

+# we would have needed to manually import the libraries as opposed to reusing targets exported by

+# gRPC and protobuf).

+ExternalProject_Add(helloworld

+  PREFIX helloworld

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.."

+  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/helloworld"

+  INSTALL_COMMAND ""

+  CMAKE_CACHE_ARGS

+        -DProtobuf_DIR:PATH=${_FINDPACKAGE_PROTOBUF_CONFIG_DIR}

+        -Dc-ares_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}/c-ares/lib/cmake/c-ares

+        -DZLIB_ROOT:STRING=${CMAKE_CURRENT_BINARY_DIR}/zlib

+        ${_CMAKE_ARGS_OPENSSL_ROOT_DIR}

+        -DgRPC_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}/grpc/lib/cmake/grpc

+  DEPENDS protobuf grpc

+)

diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index f53e9db..9d4d15a 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -308,6 +308,7 @@
                       'src/core/tsi/transport_security.h',
                       'src/core/tsi/transport_security_adapter.h',
                       'src/core/tsi/transport_security_interface.h',
+                      'src/core/ext/transport/chttp2/client/authority.h',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                       'src/core/ext/filters/client_channel/backup_poller.h',
                       'src/core/ext/filters/client_channel/client_channel.h',
@@ -485,6 +486,7 @@
                       'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
                       'src/core/ext/filters/max_age/max_age_filter.h',
                       'src/core/ext/filters/message_size/message_size_filter.h',
+                      'src/core/ext/filters/http/client_authority_filter.h',
                       'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
                       'src/core/ext/filters/workarounds/workaround_utils.h'
 
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index f93dded..0eadbb5 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -182,6 +182,7 @@
     ss.dependency 'BoringSSL', '~> 10.0'
     ss.dependency 'nanopb', '~> 0.3'
 
+    # To save you from scrolling, this is the last part of the podspec.
     ss.source_files = 'src/core/lib/gpr/arena.h',
                       'src/core/lib/gpr/env.h',
                       'src/core/lib/gpr/fork.h',
@@ -318,6 +319,7 @@
                       'src/core/tsi/transport_security.h',
                       'src/core/tsi/transport_security_adapter.h',
                       'src/core/tsi/transport_security_interface.h',
+                      'src/core/ext/transport/chttp2/client/authority.h',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                       'src/core/ext/filters/client_channel/backup_poller.h',
                       'src/core/ext/filters/client_channel/client_channel.h',
@@ -495,6 +497,7 @@
                       'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
                       'src/core/ext/filters/max_age/max_age_filter.h',
                       'src/core/ext/filters/message_size/message_size_filter.h',
+                      'src/core/ext/filters/http/client_authority_filter.h',
                       'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
                       'src/core/ext/filters/workarounds/workaround_utils.h',
                       'src/core/lib/surface/init.cc',
@@ -736,6 +739,7 @@
                       'src/core/tsi/transport_security_adapter.cc',
                       'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
                       'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+                      'src/core/ext/transport/chttp2/client/authority.cc',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
                       'src/core/ext/filters/client_channel/backup_poller.cc',
                       'src/core/ext/filters/client_channel/channel_connectivity.cc',
@@ -793,6 +797,7 @@
                       'src/core/ext/census/grpc_context.cc',
                       'src/core/ext/filters/max_age/max_age_filter.cc',
                       'src/core/ext/filters/message_size/message_size_filter.cc',
+                      'src/core/ext/filters/http/client_authority_filter.cc',
                       'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
                       'src/core/ext/filters/workarounds/workaround_utils.cc',
                       'src/core/plugin_registry/grpc_plugin_registry.cc'
@@ -894,6 +899,7 @@
                               'src/core/tsi/transport_security.h',
                               'src/core/tsi/transport_security_adapter.h',
                               'src/core/tsi/transport_security_interface.h',
+                              'src/core/ext/transport/chttp2/client/authority.h',
                               'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                               'src/core/ext/filters/client_channel/backup_poller.h',
                               'src/core/ext/filters/client_channel/client_channel.h',
@@ -1071,960 +1077,41 @@
                               'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
                               'src/core/ext/filters/max_age/max_age_filter.h',
                               'src/core/ext/filters/message_size/message_size_filter.h',
+                              'src/core/ext/filters/http/client_authority_filter.h',
                               'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
                               'src/core/ext/filters/workarounds/workaround_utils.h'
   end
 
   s.subspec 'Cronet-Interface' do |ss|
     ss.header_mappings_dir = 'include/grpc'
-    ss.source_files = 'include/grpc/support/alloc.h',
-                      'include/grpc/support/atm.h',
-                      'include/grpc/support/atm_gcc_atomic.h',
-                      'include/grpc/support/atm_gcc_sync.h',
-                      'include/grpc/support/atm_windows.h',
-                      'include/grpc/support/cpu.h',
-                      'include/grpc/support/log.h',
-                      'include/grpc/support/log_windows.h',
-                      'include/grpc/support/port_platform.h',
-                      'include/grpc/support/string_util.h',
-                      'include/grpc/support/sync.h',
-                      'include/grpc/support/sync_custom.h',
-                      'include/grpc/support/sync_generic.h',
-                      'include/grpc/support/sync_posix.h',
-                      'include/grpc/support/sync_windows.h',
-                      'include/grpc/support/thd_id.h',
-                      'include/grpc/support/time.h',
-                      'include/grpc/impl/codegen/atm.h',
-                      'include/grpc/impl/codegen/atm_gcc_atomic.h',
-                      'include/grpc/impl/codegen/atm_gcc_sync.h',
-                      'include/grpc/impl/codegen/atm_windows.h',
-                      'include/grpc/impl/codegen/fork.h',
-                      'include/grpc/impl/codegen/gpr_slice.h',
-                      'include/grpc/impl/codegen/gpr_types.h',
-                      'include/grpc/impl/codegen/port_platform.h',
-                      'include/grpc/impl/codegen/sync.h',
-                      'include/grpc/impl/codegen/sync_custom.h',
-                      'include/grpc/impl/codegen/sync_generic.h',
-                      'include/grpc/impl/codegen/sync_posix.h',
-                      'include/grpc/impl/codegen/sync_windows.h',
-                      'include/grpc/impl/codegen/byte_buffer.h',
-                      'include/grpc/impl/codegen/byte_buffer_reader.h',
-                      'include/grpc/impl/codegen/compression_types.h',
-                      'include/grpc/impl/codegen/connectivity_state.h',
-                      'include/grpc/impl/codegen/grpc_types.h',
-                      'include/grpc/impl/codegen/propagation_bits.h',
-                      'include/grpc/impl/codegen/slice.h',
-                      'include/grpc/impl/codegen/status.h',
-                      'include/grpc/impl/codegen/atm.h',
-                      'include/grpc/impl/codegen/atm_gcc_atomic.h',
-                      'include/grpc/impl/codegen/atm_gcc_sync.h',
-                      'include/grpc/impl/codegen/atm_windows.h',
-                      'include/grpc/impl/codegen/fork.h',
-                      'include/grpc/impl/codegen/gpr_slice.h',
-                      'include/grpc/impl/codegen/gpr_types.h',
-                      'include/grpc/impl/codegen/port_platform.h',
-                      'include/grpc/impl/codegen/sync.h',
-                      'include/grpc/impl/codegen/sync_custom.h',
-                      'include/grpc/impl/codegen/sync_generic.h',
-                      'include/grpc/impl/codegen/sync_posix.h',
-                      'include/grpc/impl/codegen/sync_windows.h',
-                      'include/grpc/byte_buffer.h',
-                      'include/grpc/byte_buffer_reader.h',
-                      'include/grpc/compression.h',
-                      'include/grpc/fork.h',
-                      'include/grpc/grpc.h',
-                      'include/grpc/grpc_posix.h',
-                      'include/grpc/grpc_security_constants.h',
-                      'include/grpc/load_reporting.h',
-                      'include/grpc/slice.h',
-                      'include/grpc/slice_buffer.h',
-                      'include/grpc/status.h',
-                      'include/grpc/support/workaround_list.h',
-                      'include/grpc/grpc_cronet.h',
-                      'include/grpc/grpc_security.h'
+    ss.source_files = 'include/grpc/grpc_cronet.h'
   end
 
   s.subspec 'Cronet-Implementation' do |ss|
     ss.header_mappings_dir = '.'
-    ss.libraries = 'z'
-    ss.dependency "#{s.name}/Cronet-Interface", version
-    ss.dependency 'BoringSSL', '~> 10.0'
-    ss.dependency 'nanopb', '~> 0.3'
 
-    ss.source_files = 'src/core/lib/gpr/arena.h',
-                      'src/core/lib/gpr/env.h',
-                      'src/core/lib/gpr/fork.h',
-                      'src/core/lib/gpr/host_port.h',
-                      'src/core/lib/gpr/mpscq.h',
-                      'src/core/lib/gpr/murmur_hash.h',
-                      'src/core/lib/gpr/spinlock.h',
-                      'src/core/lib/gpr/string.h',
-                      'src/core/lib/gpr/string_windows.h',
-                      'src/core/lib/gpr/time_precise.h',
-                      'src/core/lib/gpr/tls.h',
-                      'src/core/lib/gpr/tls_gcc.h',
-                      'src/core/lib/gpr/tls_msvc.h',
-                      'src/core/lib/gpr/tls_pthread.h',
-                      'src/core/lib/gpr/tmpfile.h',
-                      'src/core/lib/gpr/useful.h',
-                      'src/core/lib/gprpp/abstract.h',
-                      'src/core/lib/gprpp/atomic.h',
-                      'src/core/lib/gprpp/atomic_with_atm.h',
-                      'src/core/lib/gprpp/atomic_with_std.h',
-                      'src/core/lib/gprpp/manual_constructor.h',
-                      'src/core/lib/gprpp/memory.h',
-                      'src/core/lib/gprpp/thd.h',
-                      'src/core/lib/profiling/timers.h',
-                      'src/core/lib/gpr/alloc.cc',
-                      'src/core/lib/gpr/arena.cc',
-                      'src/core/lib/gpr/atm.cc',
-                      'src/core/lib/gpr/cpu_iphone.cc',
-                      'src/core/lib/gpr/cpu_linux.cc',
-                      'src/core/lib/gpr/cpu_posix.cc',
-                      'src/core/lib/gpr/cpu_windows.cc',
-                      'src/core/lib/gpr/env_linux.cc',
-                      'src/core/lib/gpr/env_posix.cc',
-                      'src/core/lib/gpr/env_windows.cc',
-                      'src/core/lib/gpr/fork.cc',
-                      'src/core/lib/gpr/host_port.cc',
-                      'src/core/lib/gpr/log.cc',
-                      'src/core/lib/gpr/log_android.cc',
-                      'src/core/lib/gpr/log_linux.cc',
-                      'src/core/lib/gpr/log_posix.cc',
-                      'src/core/lib/gpr/log_windows.cc',
-                      'src/core/lib/gpr/mpscq.cc',
-                      'src/core/lib/gpr/murmur_hash.cc',
-                      'src/core/lib/gpr/string.cc',
-                      'src/core/lib/gpr/string_posix.cc',
-                      'src/core/lib/gpr/string_util_windows.cc',
-                      'src/core/lib/gpr/string_windows.cc',
-                      'src/core/lib/gpr/sync.cc',
-                      'src/core/lib/gpr/sync_posix.cc',
-                      'src/core/lib/gpr/sync_windows.cc',
-                      'src/core/lib/gpr/time.cc',
-                      'src/core/lib/gpr/time_posix.cc',
-                      'src/core/lib/gpr/time_precise.cc',
-                      'src/core/lib/gpr/time_windows.cc',
-                      'src/core/lib/gpr/tls_pthread.cc',
-                      'src/core/lib/gpr/tmpfile_msys.cc',
-                      'src/core/lib/gpr/tmpfile_posix.cc',
-                      'src/core/lib/gpr/tmpfile_windows.cc',
-                      'src/core/lib/gpr/wrap_memcpy.cc',
-                      'src/core/lib/gprpp/thd_posix.cc',
-                      'src/core/lib/gprpp/thd_windows.cc',
-                      'src/core/lib/profiling/basic_timers.cc',
-                      'src/core/lib/profiling/stap_timers.cc',
-                      'src/core/lib/avl/avl.h',
-                      'src/core/lib/backoff/backoff.h',
-                      'src/core/lib/channel/channel_args.h',
-                      'src/core/lib/channel/channel_stack.h',
-                      'src/core/lib/channel/channel_stack_builder.h',
-                      'src/core/lib/channel/channel_trace.h',
-                      'src/core/lib/channel/channel_trace_registry.h',
-                      'src/core/lib/channel/connected_channel.h',
-                      'src/core/lib/channel/context.h',
-                      'src/core/lib/channel/handshaker.h',
-                      'src/core/lib/channel/handshaker_factory.h',
-                      'src/core/lib/channel/handshaker_registry.h',
-                      'src/core/lib/channel/status_util.h',
-                      'src/core/lib/compression/algorithm_metadata.h',
-                      'src/core/lib/compression/compression_internal.h',
-                      'src/core/lib/compression/message_compress.h',
-                      'src/core/lib/compression/stream_compression.h',
-                      'src/core/lib/compression/stream_compression_gzip.h',
-                      'src/core/lib/compression/stream_compression_identity.h',
-                      'src/core/lib/debug/stats.h',
-                      'src/core/lib/debug/stats_data.h',
-                      'src/core/lib/gprpp/debug_location.h',
-                      'src/core/lib/gprpp/inlined_vector.h',
-                      'src/core/lib/gprpp/orphanable.h',
-                      'src/core/lib/gprpp/ref_counted.h',
-                      'src/core/lib/gprpp/ref_counted_ptr.h',
-                      'src/core/lib/http/format_request.h',
-                      'src/core/lib/http/httpcli.h',
-                      'src/core/lib/http/parser.h',
-                      'src/core/lib/iomgr/block_annotate.h',
-                      'src/core/lib/iomgr/call_combiner.h',
-                      'src/core/lib/iomgr/closure.h',
-                      'src/core/lib/iomgr/combiner.h',
-                      'src/core/lib/iomgr/endpoint.h',
-                      'src/core/lib/iomgr/endpoint_pair.h',
-                      'src/core/lib/iomgr/error.h',
-                      'src/core/lib/iomgr/error_internal.h',
-                      'src/core/lib/iomgr/ev_epoll1_linux.h',
-                      'src/core/lib/iomgr/ev_epollex_linux.h',
-                      'src/core/lib/iomgr/ev_epollsig_linux.h',
-                      'src/core/lib/iomgr/ev_poll_posix.h',
-                      'src/core/lib/iomgr/ev_posix.h',
-                      'src/core/lib/iomgr/exec_ctx.h',
-                      'src/core/lib/iomgr/executor.h',
-                      'src/core/lib/iomgr/gethostname.h',
-                      'src/core/lib/iomgr/iocp_windows.h',
-                      'src/core/lib/iomgr/iomgr.h',
-                      'src/core/lib/iomgr/iomgr_custom.h',
-                      'src/core/lib/iomgr/iomgr_internal.h',
-                      'src/core/lib/iomgr/iomgr_posix.h',
-                      'src/core/lib/iomgr/is_epollexclusive_available.h',
-                      'src/core/lib/iomgr/load_file.h',
-                      'src/core/lib/iomgr/lockfree_event.h',
-                      'src/core/lib/iomgr/nameser.h',
-                      'src/core/lib/iomgr/network_status_tracker.h',
-                      'src/core/lib/iomgr/polling_entity.h',
-                      'src/core/lib/iomgr/pollset.h',
-                      'src/core/lib/iomgr/pollset_custom.h',
-                      'src/core/lib/iomgr/pollset_set.h',
-                      'src/core/lib/iomgr/pollset_set_custom.h',
-                      'src/core/lib/iomgr/pollset_set_windows.h',
-                      'src/core/lib/iomgr/pollset_windows.h',
-                      'src/core/lib/iomgr/port.h',
-                      'src/core/lib/iomgr/resolve_address.h',
-                      'src/core/lib/iomgr/resolve_address_custom.h',
-                      'src/core/lib/iomgr/resource_quota.h',
-                      'src/core/lib/iomgr/sockaddr.h',
-                      'src/core/lib/iomgr/sockaddr_custom.h',
-                      'src/core/lib/iomgr/sockaddr_posix.h',
-                      'src/core/lib/iomgr/sockaddr_utils.h',
-                      'src/core/lib/iomgr/sockaddr_windows.h',
-                      'src/core/lib/iomgr/socket_factory_posix.h',
-                      'src/core/lib/iomgr/socket_mutator.h',
-                      'src/core/lib/iomgr/socket_utils.h',
-                      'src/core/lib/iomgr/socket_utils_posix.h',
-                      'src/core/lib/iomgr/socket_windows.h',
-                      'src/core/lib/iomgr/sys_epoll_wrapper.h',
-                      'src/core/lib/iomgr/tcp_client.h',
-                      'src/core/lib/iomgr/tcp_client_posix.h',
-                      'src/core/lib/iomgr/tcp_custom.h',
-                      'src/core/lib/iomgr/tcp_posix.h',
-                      'src/core/lib/iomgr/tcp_server.h',
-                      'src/core/lib/iomgr/tcp_server_utils_posix.h',
-                      'src/core/lib/iomgr/tcp_windows.h',
-                      'src/core/lib/iomgr/time_averaged_stats.h',
-                      'src/core/lib/iomgr/timer.h',
-                      'src/core/lib/iomgr/timer_custom.h',
-                      'src/core/lib/iomgr/timer_heap.h',
-                      'src/core/lib/iomgr/timer_manager.h',
-                      'src/core/lib/iomgr/udp_server.h',
-                      'src/core/lib/iomgr/unix_sockets_posix.h',
-                      'src/core/lib/iomgr/wakeup_fd_cv.h',
-                      'src/core/lib/iomgr/wakeup_fd_pipe.h',
-                      'src/core/lib/iomgr/wakeup_fd_posix.h',
-                      'src/core/lib/json/json.h',
-                      'src/core/lib/json/json_common.h',
-                      'src/core/lib/json/json_reader.h',
-                      'src/core/lib/json/json_writer.h',
-                      'src/core/lib/slice/b64.h',
-                      'src/core/lib/slice/percent_encoding.h',
-                      'src/core/lib/slice/slice_hash_table.h',
-                      'src/core/lib/slice/slice_internal.h',
-                      'src/core/lib/slice/slice_string_helpers.h',
-                      'src/core/lib/slice/slice_weak_hash_table.h',
-                      'src/core/lib/surface/api_trace.h',
-                      'src/core/lib/surface/call.h',
-                      'src/core/lib/surface/call_test_only.h',
-                      'src/core/lib/surface/channel.h',
-                      'src/core/lib/surface/channel_init.h',
-                      'src/core/lib/surface/channel_stack_type.h',
-                      'src/core/lib/surface/completion_queue.h',
-                      'src/core/lib/surface/completion_queue_factory.h',
-                      'src/core/lib/surface/event_string.h',
-                      'src/core/lib/surface/init.h',
-                      'src/core/lib/surface/lame_client.h',
-                      'src/core/lib/surface/server.h',
-                      'src/core/lib/surface/validate_metadata.h',
-                      'src/core/lib/transport/bdp_estimator.h',
-                      'src/core/lib/transport/byte_stream.h',
-                      'src/core/lib/transport/connectivity_state.h',
-                      'src/core/lib/transport/error_utils.h',
-                      'src/core/lib/transport/http2_errors.h',
-                      'src/core/lib/transport/metadata.h',
-                      'src/core/lib/transport/metadata_batch.h',
-                      'src/core/lib/transport/pid_controller.h',
-                      'src/core/lib/transport/service_config.h',
-                      'src/core/lib/transport/static_metadata.h',
-                      'src/core/lib/transport/status_conversion.h',
-                      'src/core/lib/transport/status_metadata.h',
-                      'src/core/lib/transport/timeout_encoding.h',
-                      'src/core/lib/transport/transport.h',
-                      'src/core/lib/transport/transport_impl.h',
-                      'src/core/lib/debug/trace.h',
-                      'src/core/ext/filters/deadline/deadline_filter.h',
-                      'src/core/ext/filters/client_channel/backup_poller.h',
-                      'src/core/ext/filters/client_channel/client_channel.h',
-                      'src/core/ext/filters/client_channel/client_channel_factory.h',
-                      'src/core/ext/filters/client_channel/connector.h',
-                      'src/core/ext/filters/client_channel/http_connect_handshaker.h',
-                      'src/core/ext/filters/client_channel/http_proxy.h',
-                      'src/core/ext/filters/client_channel/lb_policy.h',
-                      'src/core/ext/filters/client_channel/lb_policy_factory.h',
-                      'src/core/ext/filters/client_channel/lb_policy_registry.h',
-                      'src/core/ext/filters/client_channel/method_params.h',
-                      'src/core/ext/filters/client_channel/parse_address.h',
-                      'src/core/ext/filters/client_channel/proxy_mapper.h',
-                      'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
-                      'src/core/ext/filters/client_channel/resolver.h',
-                      'src/core/ext/filters/client_channel/resolver_factory.h',
-                      'src/core/ext/filters/client_channel/resolver_registry.h',
-                      'src/core/ext/filters/client_channel/retry_throttle.h',
-                      'src/core/ext/filters/client_channel/subchannel.h',
-                      'src/core/ext/filters/client_channel/subchannel_index.h',
-                      'src/core/ext/filters/client_channel/uri_parser.h',
-                      'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
-                      'src/core/ext/filters/max_age/max_age_filter.h',
-                      'src/core/ext/filters/message_size/message_size_filter.h',
-                      'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
-                      'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
-                      'src/core/ext/transport/cronet/transport/cronet_transport.h',
-                      'third_party/objective_c/Cronet/bidirectional_stream_c.h',
-                      'src/core/ext/transport/chttp2/transport/bin_decoder.h',
-                      'src/core/ext/transport/chttp2/transport/bin_encoder.h',
-                      'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
-                      'src/core/ext/transport/chttp2/transport/flow_control.h',
-                      'src/core/ext/transport/chttp2/transport/frame.h',
-                      'src/core/ext/transport/chttp2/transport/frame_data.h',
-                      'src/core/ext/transport/chttp2/transport/frame_goaway.h',
-                      'src/core/ext/transport/chttp2/transport/frame_ping.h',
-                      'src/core/ext/transport/chttp2/transport/frame_rst_stream.h',
-                      'src/core/ext/transport/chttp2/transport/frame_settings.h',
-                      'src/core/ext/transport/chttp2/transport/frame_window_update.h',
-                      'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
-                      'src/core/ext/transport/chttp2/transport/hpack_parser.h',
-                      'src/core/ext/transport/chttp2/transport/hpack_table.h',
-                      'src/core/ext/transport/chttp2/transport/http2_settings.h',
-                      'src/core/ext/transport/chttp2/transport/huffsyms.h',
-                      'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
-                      'src/core/ext/transport/chttp2/transport/internal.h',
-                      'src/core/ext/transport/chttp2/transport/stream_map.h',
-                      'src/core/ext/transport/chttp2/transport/varint.h',
-                      'src/core/ext/transport/chttp2/alpn/alpn.h',
-                      'src/core/ext/filters/http/client/http_client_filter.h',
-                      'src/core/ext/filters/http/message_compress/message_compress_filter.h',
-                      'src/core/ext/filters/http/server/http_server_filter.h',
-                      'src/core/lib/security/context/security_context.h',
-                      'src/core/lib/security/credentials/alts/alts_credentials.h',
-                      'src/core/lib/security/credentials/composite/composite_credentials.h',
-                      'src/core/lib/security/credentials/credentials.h',
-                      'src/core/lib/security/credentials/fake/fake_credentials.h',
-                      'src/core/lib/security/credentials/google_default/google_default_credentials.h',
-                      'src/core/lib/security/credentials/iam/iam_credentials.h',
-                      'src/core/lib/security/credentials/jwt/json_token.h',
-                      'src/core/lib/security/credentials/jwt/jwt_credentials.h',
-                      'src/core/lib/security/credentials/jwt/jwt_verifier.h',
-                      'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
-                      'src/core/lib/security/credentials/plugin/plugin_credentials.h',
-                      'src/core/lib/security/credentials/ssl/ssl_credentials.h',
-                      'src/core/lib/security/security_connector/alts_security_connector.h',
-                      'src/core/lib/security/security_connector/security_connector.h',
-                      'src/core/lib/security/transport/auth_filters.h',
-                      'src/core/lib/security/transport/secure_endpoint.h',
-                      'src/core/lib/security/transport/security_handshaker.h',
-                      'src/core/lib/security/transport/target_authority_table.h',
-                      'src/core/lib/security/transport/tsi_error.h',
-                      'src/core/lib/security/util/json_util.h',
-                      'src/core/tsi/alts/crypt/gsec.h',
-                      'src/core/tsi/alts/frame_protector/alts_counter.h',
-                      'src/core/tsi/alts/frame_protector/alts_crypter.h',
-                      'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
-                      'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
-                      'src/core/tsi/alts/frame_protector/frame_handler.h',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
-                      'src/core/tsi/alts/handshaker/alts_tsi_event.h',
-                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
-                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment.h',
-                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
-                      'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
-                      'src/core/tsi/alts/handshaker/transport_security_common_api.h',
-                      'src/core/tsi/alts/handshaker/altscontext.pb.h',
-                      'src/core/tsi/alts/handshaker/handshaker.pb.h',
-                      'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
-                      'third_party/nanopb/pb.h',
-                      'third_party/nanopb/pb_common.h',
-                      'third_party/nanopb/pb_decode.h',
-                      'third_party/nanopb/pb_encode.h',
-                      'src/core/tsi/transport_security.h',
-                      'src/core/tsi/transport_security_adapter.h',
-                      'src/core/tsi/transport_security_interface.h',
-                      'src/core/ext/transport/chttp2/client/chttp2_connector.h',
-                      'src/core/tsi/alts_transport_security.h',
-                      'src/core/tsi/fake_transport_security.h',
-                      'src/core/tsi/ssl/session_cache/ssl_session.h',
-                      'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
-                      'src/core/tsi/ssl_transport_security.h',
-                      'src/core/tsi/ssl_types.h',
-                      'src/core/tsi/transport_security_grpc.h',
-                      'src/core/ext/transport/chttp2/server/chttp2_server.h',
-                      'src/core/lib/surface/init.cc',
-                      'src/core/lib/avl/avl.cc',
-                      'src/core/lib/backoff/backoff.cc',
-                      'src/core/lib/channel/channel_args.cc',
-                      'src/core/lib/channel/channel_stack.cc',
-                      'src/core/lib/channel/channel_stack_builder.cc',
-                      'src/core/lib/channel/channel_trace.cc',
-                      'src/core/lib/channel/channel_trace_registry.cc',
-                      'src/core/lib/channel/connected_channel.cc',
-                      'src/core/lib/channel/handshaker.cc',
-                      'src/core/lib/channel/handshaker_factory.cc',
-                      'src/core/lib/channel/handshaker_registry.cc',
-                      'src/core/lib/channel/status_util.cc',
-                      'src/core/lib/compression/compression.cc',
-                      'src/core/lib/compression/compression_internal.cc',
-                      'src/core/lib/compression/message_compress.cc',
-                      'src/core/lib/compression/stream_compression.cc',
-                      'src/core/lib/compression/stream_compression_gzip.cc',
-                      'src/core/lib/compression/stream_compression_identity.cc',
-                      'src/core/lib/debug/stats.cc',
-                      'src/core/lib/debug/stats_data.cc',
-                      'src/core/lib/http/format_request.cc',
-                      'src/core/lib/http/httpcli.cc',
-                      'src/core/lib/http/parser.cc',
-                      'src/core/lib/iomgr/call_combiner.cc',
-                      'src/core/lib/iomgr/combiner.cc',
-                      'src/core/lib/iomgr/endpoint.cc',
-                      'src/core/lib/iomgr/endpoint_pair_posix.cc',
-                      'src/core/lib/iomgr/endpoint_pair_uv.cc',
-                      'src/core/lib/iomgr/endpoint_pair_windows.cc',
-                      'src/core/lib/iomgr/error.cc',
-                      'src/core/lib/iomgr/ev_epoll1_linux.cc',
-                      'src/core/lib/iomgr/ev_epollex_linux.cc',
-                      'src/core/lib/iomgr/ev_epollsig_linux.cc',
-                      'src/core/lib/iomgr/ev_poll_posix.cc',
-                      'src/core/lib/iomgr/ev_posix.cc',
-                      'src/core/lib/iomgr/ev_windows.cc',
-                      'src/core/lib/iomgr/exec_ctx.cc',
-                      'src/core/lib/iomgr/executor.cc',
-                      'src/core/lib/iomgr/fork_posix.cc',
-                      'src/core/lib/iomgr/fork_windows.cc',
-                      'src/core/lib/iomgr/gethostname_fallback.cc',
-                      'src/core/lib/iomgr/gethostname_host_name_max.cc',
-                      'src/core/lib/iomgr/gethostname_sysconf.cc',
-                      'src/core/lib/iomgr/iocp_windows.cc',
-                      'src/core/lib/iomgr/iomgr.cc',
-                      'src/core/lib/iomgr/iomgr_custom.cc',
-                      'src/core/lib/iomgr/iomgr_internal.cc',
-                      'src/core/lib/iomgr/iomgr_posix.cc',
-                      'src/core/lib/iomgr/iomgr_uv.cc',
-                      'src/core/lib/iomgr/iomgr_windows.cc',
-                      'src/core/lib/iomgr/is_epollexclusive_available.cc',
-                      'src/core/lib/iomgr/load_file.cc',
-                      'src/core/lib/iomgr/lockfree_event.cc',
-                      'src/core/lib/iomgr/network_status_tracker.cc',
-                      'src/core/lib/iomgr/polling_entity.cc',
-                      'src/core/lib/iomgr/pollset.cc',
-                      'src/core/lib/iomgr/pollset_custom.cc',
-                      'src/core/lib/iomgr/pollset_set.cc',
-                      'src/core/lib/iomgr/pollset_set_custom.cc',
-                      'src/core/lib/iomgr/pollset_set_windows.cc',
-                      'src/core/lib/iomgr/pollset_uv.cc',
-                      'src/core/lib/iomgr/pollset_windows.cc',
-                      'src/core/lib/iomgr/resolve_address.cc',
-                      'src/core/lib/iomgr/resolve_address_custom.cc',
-                      'src/core/lib/iomgr/resolve_address_posix.cc',
-                      'src/core/lib/iomgr/resolve_address_windows.cc',
-                      'src/core/lib/iomgr/resource_quota.cc',
-                      'src/core/lib/iomgr/sockaddr_utils.cc',
-                      'src/core/lib/iomgr/socket_factory_posix.cc',
-                      'src/core/lib/iomgr/socket_mutator.cc',
-                      'src/core/lib/iomgr/socket_utils_common_posix.cc',
-                      'src/core/lib/iomgr/socket_utils_linux.cc',
-                      'src/core/lib/iomgr/socket_utils_posix.cc',
-                      'src/core/lib/iomgr/socket_utils_uv.cc',
-                      'src/core/lib/iomgr/socket_utils_windows.cc',
-                      'src/core/lib/iomgr/socket_windows.cc',
-                      'src/core/lib/iomgr/tcp_client.cc',
-                      'src/core/lib/iomgr/tcp_client_custom.cc',
-                      'src/core/lib/iomgr/tcp_client_posix.cc',
-                      'src/core/lib/iomgr/tcp_client_windows.cc',
-                      'src/core/lib/iomgr/tcp_custom.cc',
-                      'src/core/lib/iomgr/tcp_posix.cc',
-                      'src/core/lib/iomgr/tcp_server.cc',
-                      'src/core/lib/iomgr/tcp_server_custom.cc',
-                      'src/core/lib/iomgr/tcp_server_posix.cc',
-                      'src/core/lib/iomgr/tcp_server_utils_posix_common.cc',
-                      'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc',
-                      'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc',
-                      'src/core/lib/iomgr/tcp_server_windows.cc',
-                      'src/core/lib/iomgr/tcp_uv.cc',
-                      'src/core/lib/iomgr/tcp_windows.cc',
-                      'src/core/lib/iomgr/time_averaged_stats.cc',
-                      'src/core/lib/iomgr/timer.cc',
-                      'src/core/lib/iomgr/timer_custom.cc',
-                      'src/core/lib/iomgr/timer_generic.cc',
-                      'src/core/lib/iomgr/timer_heap.cc',
-                      'src/core/lib/iomgr/timer_manager.cc',
-                      'src/core/lib/iomgr/timer_uv.cc',
-                      'src/core/lib/iomgr/udp_server.cc',
-                      'src/core/lib/iomgr/unix_sockets_posix.cc',
-                      'src/core/lib/iomgr/unix_sockets_posix_noop.cc',
-                      'src/core/lib/iomgr/wakeup_fd_cv.cc',
-                      'src/core/lib/iomgr/wakeup_fd_eventfd.cc',
-                      'src/core/lib/iomgr/wakeup_fd_nospecial.cc',
-                      'src/core/lib/iomgr/wakeup_fd_pipe.cc',
-                      'src/core/lib/iomgr/wakeup_fd_posix.cc',
-                      'src/core/lib/json/json.cc',
-                      'src/core/lib/json/json_reader.cc',
-                      'src/core/lib/json/json_string.cc',
-                      'src/core/lib/json/json_writer.cc',
-                      'src/core/lib/slice/b64.cc',
-                      'src/core/lib/slice/percent_encoding.cc',
-                      'src/core/lib/slice/slice.cc',
-                      'src/core/lib/slice/slice_buffer.cc',
-                      'src/core/lib/slice/slice_intern.cc',
-                      'src/core/lib/slice/slice_string_helpers.cc',
-                      'src/core/lib/surface/api_trace.cc',
-                      'src/core/lib/surface/byte_buffer.cc',
-                      'src/core/lib/surface/byte_buffer_reader.cc',
-                      'src/core/lib/surface/call.cc',
-                      'src/core/lib/surface/call_details.cc',
-                      'src/core/lib/surface/call_log_batch.cc',
-                      'src/core/lib/surface/channel.cc',
-                      'src/core/lib/surface/channel_init.cc',
-                      'src/core/lib/surface/channel_ping.cc',
-                      'src/core/lib/surface/channel_stack_type.cc',
-                      'src/core/lib/surface/completion_queue.cc',
-                      'src/core/lib/surface/completion_queue_factory.cc',
-                      'src/core/lib/surface/event_string.cc',
-                      'src/core/lib/surface/lame_client.cc',
-                      'src/core/lib/surface/metadata_array.cc',
-                      'src/core/lib/surface/server.cc',
-                      'src/core/lib/surface/validate_metadata.cc',
-                      'src/core/lib/surface/version.cc',
-                      'src/core/lib/transport/bdp_estimator.cc',
-                      'src/core/lib/transport/byte_stream.cc',
-                      'src/core/lib/transport/connectivity_state.cc',
-                      'src/core/lib/transport/error_utils.cc',
-                      'src/core/lib/transport/metadata.cc',
-                      'src/core/lib/transport/metadata_batch.cc',
-                      'src/core/lib/transport/pid_controller.cc',
-                      'src/core/lib/transport/service_config.cc',
-                      'src/core/lib/transport/static_metadata.cc',
-                      'src/core/lib/transport/status_conversion.cc',
-                      'src/core/lib/transport/status_metadata.cc',
-                      'src/core/lib/transport/timeout_encoding.cc',
-                      'src/core/lib/transport/transport.cc',
-                      'src/core/lib/transport/transport_op_string.cc',
-                      'src/core/lib/debug/trace.cc',
-                      'src/core/ext/filters/deadline/deadline_filter.cc',
-                      'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
-                      'src/core/ext/filters/client_channel/backup_poller.cc',
-                      'src/core/ext/filters/client_channel/channel_connectivity.cc',
-                      'src/core/ext/filters/client_channel/client_channel.cc',
-                      'src/core/ext/filters/client_channel/client_channel_factory.cc',
-                      'src/core/ext/filters/client_channel/client_channel_plugin.cc',
-                      'src/core/ext/filters/client_channel/connector.cc',
-                      'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
-                      'src/core/ext/filters/client_channel/http_proxy.cc',
-                      'src/core/ext/filters/client_channel/lb_policy.cc',
-                      'src/core/ext/filters/client_channel/lb_policy_factory.cc',
-                      'src/core/ext/filters/client_channel/lb_policy_registry.cc',
-                      'src/core/ext/filters/client_channel/method_params.cc',
-                      'src/core/ext/filters/client_channel/parse_address.cc',
-                      'src/core/ext/filters/client_channel/proxy_mapper.cc',
-                      'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
-                      'src/core/ext/filters/client_channel/resolver.cc',
-                      'src/core/ext/filters/client_channel/resolver_registry.cc',
-                      'src/core/ext/filters/client_channel/retry_throttle.cc',
-                      'src/core/ext/filters/client_channel/subchannel.cc',
-                      'src/core/ext/filters/client_channel/subchannel_index.cc',
-                      'src/core/ext/filters/client_channel/uri_parser.cc',
-                      'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',
-                      'src/core/ext/filters/max_age/max_age_filter.cc',
-                      'src/core/ext/filters/message_size/message_size_filter.cc',
-                      'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc',
-                      'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
-                      'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
-                      'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
-                      'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc',
+    ss.dependency "#{s.name}/Interface", version
+    ss.dependency "#{s.name}/Implementation", version
+    ss.dependency "#{s.name}/Cronet-Interface", version
+
+    ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc',
                       'src/core/ext/transport/cronet/transport/cronet_transport.cc',
-                      'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
-                      'src/core/ext/transport/chttp2/transport/bin_decoder.cc',
-                      'src/core/ext/transport/chttp2/transport/bin_encoder.cc',
-                      'src/core/ext/transport/chttp2/transport/chttp2_plugin.cc',
-                      'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
-                      'src/core/ext/transport/chttp2/transport/flow_control.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_data.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_goaway.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_ping.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_rst_stream.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_settings.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_window_update.cc',
-                      'src/core/ext/transport/chttp2/transport/hpack_encoder.cc',
-                      'src/core/ext/transport/chttp2/transport/hpack_parser.cc',
-                      'src/core/ext/transport/chttp2/transport/hpack_table.cc',
-                      'src/core/ext/transport/chttp2/transport/http2_settings.cc',
-                      'src/core/ext/transport/chttp2/transport/huffsyms.cc',
-                      'src/core/ext/transport/chttp2/transport/incoming_metadata.cc',
-                      'src/core/ext/transport/chttp2/transport/parsing.cc',
-                      'src/core/ext/transport/chttp2/transport/stream_lists.cc',
-                      'src/core/ext/transport/chttp2/transport/stream_map.cc',
-                      'src/core/ext/transport/chttp2/transport/varint.cc',
-                      'src/core/ext/transport/chttp2/transport/writing.cc',
-                      'src/core/ext/transport/chttp2/alpn/alpn.cc',
-                      'src/core/ext/filters/http/client/http_client_filter.cc',
-                      'src/core/ext/filters/http/http_filters_plugin.cc',
-                      'src/core/ext/filters/http/message_compress/message_compress_filter.cc',
-                      'src/core/ext/filters/http/server/http_server_filter.cc',
-                      'src/core/lib/http/httpcli_security_connector.cc',
-                      'src/core/lib/security/context/security_context.cc',
-                      'src/core/lib/security/credentials/alts/alts_credentials.cc',
-                      'src/core/lib/security/credentials/composite/composite_credentials.cc',
-                      'src/core/lib/security/credentials/credentials.cc',
-                      'src/core/lib/security/credentials/credentials_metadata.cc',
-                      'src/core/lib/security/credentials/fake/fake_credentials.cc',
-                      'src/core/lib/security/credentials/google_default/credentials_generic.cc',
-                      'src/core/lib/security/credentials/google_default/google_default_credentials.cc',
-                      'src/core/lib/security/credentials/iam/iam_credentials.cc',
-                      'src/core/lib/security/credentials/jwt/json_token.cc',
-                      'src/core/lib/security/credentials/jwt/jwt_credentials.cc',
-                      'src/core/lib/security/credentials/jwt/jwt_verifier.cc',
-                      'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc',
-                      'src/core/lib/security/credentials/plugin/plugin_credentials.cc',
-                      'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
-                      'src/core/lib/security/security_connector/alts_security_connector.cc',
-                      'src/core/lib/security/security_connector/security_connector.cc',
-                      'src/core/lib/security/transport/client_auth_filter.cc',
-                      'src/core/lib/security/transport/secure_endpoint.cc',
-                      'src/core/lib/security/transport/security_handshaker.cc',
-                      'src/core/lib/security/transport/server_auth_filter.cc',
-                      'src/core/lib/security/transport/target_authority_table.cc',
-                      'src/core/lib/security/transport/tsi_error.cc',
-                      'src/core/lib/security/util/json_util.cc',
-                      'src/core/lib/surface/init_secure.cc',
-                      'src/core/tsi/alts/crypt/aes_gcm.cc',
-                      'src/core/tsi/alts/crypt/gsec.cc',
-                      'src/core/tsi/alts/frame_protector/alts_counter.cc',
-                      'src/core/tsi/alts/frame_protector/alts_crypter.cc',
-                      'src/core/tsi/alts/frame_protector/alts_frame_protector.cc',
-                      'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc',
-                      'src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc',
-                      'src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc',
-                      'src/core/tsi/alts/frame_protector/frame_handler.cc',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_client.cc',
-                      'src/core/tsi/alts/handshaker/alts_tsi_event.cc',
-                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment.cc',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc',
-                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc',
-                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc',
-                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc',
-                      'src/core/tsi/alts/handshaker/alts_tsi_utils.cc',
-                      'src/core/tsi/alts/handshaker/transport_security_common_api.cc',
-                      'src/core/tsi/alts/handshaker/altscontext.pb.c',
-                      'src/core/tsi/alts/handshaker/handshaker.pb.c',
-                      'src/core/tsi/alts/handshaker/transport_security_common.pb.c',
                       'third_party/nanopb/pb_common.c',
                       'third_party/nanopb/pb_decode.c',
                       'third_party/nanopb/pb_encode.c',
-                      'src/core/tsi/transport_security.cc',
-                      'src/core/tsi/transport_security_adapter.cc',
-                      'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
-                      'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
-                      'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
-                      'src/core/tsi/alts_transport_security.cc',
-                      'src/core/tsi/fake_transport_security.cc',
-                      'src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc',
-                      'src/core/tsi/ssl/session_cache/ssl_session_cache.cc',
-                      'src/core/tsi/ssl/session_cache/ssl_session_openssl.cc',
-                      'src/core/tsi/ssl_transport_security.cc',
-                      'src/core/tsi/transport_security_grpc.cc',
-                      'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc',
-                      'src/core/ext/transport/chttp2/server/chttp2_server.cc',
-                      'src/core/plugin_registry/grpc_cronet_plugin_registry.cc'
-
-    ss.private_header_files = 'src/core/lib/gpr/arena.h',
-                              'src/core/lib/gpr/env.h',
-                              'src/core/lib/gpr/fork.h',
-                              'src/core/lib/gpr/host_port.h',
-                              'src/core/lib/gpr/mpscq.h',
-                              'src/core/lib/gpr/murmur_hash.h',
-                              'src/core/lib/gpr/spinlock.h',
-                              'src/core/lib/gpr/string.h',
-                              'src/core/lib/gpr/string_windows.h',
-                              'src/core/lib/gpr/time_precise.h',
-                              'src/core/lib/gpr/tls.h',
-                              'src/core/lib/gpr/tls_gcc.h',
-                              'src/core/lib/gpr/tls_msvc.h',
-                              'src/core/lib/gpr/tls_pthread.h',
-                              'src/core/lib/gpr/tmpfile.h',
-                              'src/core/lib/gpr/useful.h',
-                              'src/core/lib/gprpp/abstract.h',
-                              'src/core/lib/gprpp/atomic.h',
-                              'src/core/lib/gprpp/atomic_with_atm.h',
-                              'src/core/lib/gprpp/atomic_with_std.h',
-                              'src/core/lib/gprpp/manual_constructor.h',
-                              'src/core/lib/gprpp/memory.h',
-                              'src/core/lib/gprpp/thd.h',
-                              'src/core/lib/profiling/timers.h',
-                              'src/core/lib/avl/avl.h',
-                              'src/core/lib/backoff/backoff.h',
-                              'src/core/lib/channel/channel_args.h',
-                              'src/core/lib/channel/channel_stack.h',
-                              'src/core/lib/channel/channel_stack_builder.h',
-                              'src/core/lib/channel/channel_trace.h',
-                              'src/core/lib/channel/channel_trace_registry.h',
-                              'src/core/lib/channel/connected_channel.h',
-                              'src/core/lib/channel/context.h',
-                              'src/core/lib/channel/handshaker.h',
-                              'src/core/lib/channel/handshaker_factory.h',
-                              'src/core/lib/channel/handshaker_registry.h',
-                              'src/core/lib/channel/status_util.h',
-                              'src/core/lib/compression/algorithm_metadata.h',
-                              'src/core/lib/compression/compression_internal.h',
-                              'src/core/lib/compression/message_compress.h',
-                              'src/core/lib/compression/stream_compression.h',
-                              'src/core/lib/compression/stream_compression_gzip.h',
-                              'src/core/lib/compression/stream_compression_identity.h',
-                              'src/core/lib/debug/stats.h',
-                              'src/core/lib/debug/stats_data.h',
-                              'src/core/lib/gprpp/debug_location.h',
-                              'src/core/lib/gprpp/inlined_vector.h',
-                              'src/core/lib/gprpp/orphanable.h',
-                              'src/core/lib/gprpp/ref_counted.h',
-                              'src/core/lib/gprpp/ref_counted_ptr.h',
-                              'src/core/lib/http/format_request.h',
-                              'src/core/lib/http/httpcli.h',
-                              'src/core/lib/http/parser.h',
-                              'src/core/lib/iomgr/block_annotate.h',
-                              'src/core/lib/iomgr/call_combiner.h',
-                              'src/core/lib/iomgr/closure.h',
-                              'src/core/lib/iomgr/combiner.h',
-                              'src/core/lib/iomgr/endpoint.h',
-                              'src/core/lib/iomgr/endpoint_pair.h',
-                              'src/core/lib/iomgr/error.h',
-                              'src/core/lib/iomgr/error_internal.h',
-                              'src/core/lib/iomgr/ev_epoll1_linux.h',
-                              'src/core/lib/iomgr/ev_epollex_linux.h',
-                              'src/core/lib/iomgr/ev_epollsig_linux.h',
-                              'src/core/lib/iomgr/ev_poll_posix.h',
-                              'src/core/lib/iomgr/ev_posix.h',
-                              'src/core/lib/iomgr/exec_ctx.h',
-                              'src/core/lib/iomgr/executor.h',
-                              'src/core/lib/iomgr/gethostname.h',
-                              'src/core/lib/iomgr/iocp_windows.h',
-                              'src/core/lib/iomgr/iomgr.h',
-                              'src/core/lib/iomgr/iomgr_custom.h',
-                              'src/core/lib/iomgr/iomgr_internal.h',
-                              'src/core/lib/iomgr/iomgr_posix.h',
-                              'src/core/lib/iomgr/is_epollexclusive_available.h',
-                              'src/core/lib/iomgr/load_file.h',
-                              'src/core/lib/iomgr/lockfree_event.h',
-                              'src/core/lib/iomgr/nameser.h',
-                              'src/core/lib/iomgr/network_status_tracker.h',
-                              'src/core/lib/iomgr/polling_entity.h',
-                              'src/core/lib/iomgr/pollset.h',
-                              'src/core/lib/iomgr/pollset_custom.h',
-                              'src/core/lib/iomgr/pollset_set.h',
-                              'src/core/lib/iomgr/pollset_set_custom.h',
-                              'src/core/lib/iomgr/pollset_set_windows.h',
-                              'src/core/lib/iomgr/pollset_windows.h',
-                              'src/core/lib/iomgr/port.h',
-                              'src/core/lib/iomgr/resolve_address.h',
-                              'src/core/lib/iomgr/resolve_address_custom.h',
-                              'src/core/lib/iomgr/resource_quota.h',
-                              'src/core/lib/iomgr/sockaddr.h',
-                              'src/core/lib/iomgr/sockaddr_custom.h',
-                              'src/core/lib/iomgr/sockaddr_posix.h',
-                              'src/core/lib/iomgr/sockaddr_utils.h',
-                              'src/core/lib/iomgr/sockaddr_windows.h',
-                              'src/core/lib/iomgr/socket_factory_posix.h',
-                              'src/core/lib/iomgr/socket_mutator.h',
-                              'src/core/lib/iomgr/socket_utils.h',
-                              'src/core/lib/iomgr/socket_utils_posix.h',
-                              'src/core/lib/iomgr/socket_windows.h',
-                              'src/core/lib/iomgr/sys_epoll_wrapper.h',
-                              'src/core/lib/iomgr/tcp_client.h',
-                              'src/core/lib/iomgr/tcp_client_posix.h',
-                              'src/core/lib/iomgr/tcp_custom.h',
-                              'src/core/lib/iomgr/tcp_posix.h',
-                              'src/core/lib/iomgr/tcp_server.h',
-                              'src/core/lib/iomgr/tcp_server_utils_posix.h',
-                              'src/core/lib/iomgr/tcp_windows.h',
-                              'src/core/lib/iomgr/time_averaged_stats.h',
-                              'src/core/lib/iomgr/timer.h',
-                              'src/core/lib/iomgr/timer_custom.h',
-                              'src/core/lib/iomgr/timer_heap.h',
-                              'src/core/lib/iomgr/timer_manager.h',
-                              'src/core/lib/iomgr/udp_server.h',
-                              'src/core/lib/iomgr/unix_sockets_posix.h',
-                              'src/core/lib/iomgr/wakeup_fd_cv.h',
-                              'src/core/lib/iomgr/wakeup_fd_pipe.h',
-                              'src/core/lib/iomgr/wakeup_fd_posix.h',
-                              'src/core/lib/json/json.h',
-                              'src/core/lib/json/json_common.h',
-                              'src/core/lib/json/json_reader.h',
-                              'src/core/lib/json/json_writer.h',
-                              'src/core/lib/slice/b64.h',
-                              'src/core/lib/slice/percent_encoding.h',
-                              'src/core/lib/slice/slice_hash_table.h',
-                              'src/core/lib/slice/slice_internal.h',
-                              'src/core/lib/slice/slice_string_helpers.h',
-                              'src/core/lib/slice/slice_weak_hash_table.h',
-                              'src/core/lib/surface/api_trace.h',
-                              'src/core/lib/surface/call.h',
-                              'src/core/lib/surface/call_test_only.h',
-                              'src/core/lib/surface/channel.h',
-                              'src/core/lib/surface/channel_init.h',
-                              'src/core/lib/surface/channel_stack_type.h',
-                              'src/core/lib/surface/completion_queue.h',
-                              'src/core/lib/surface/completion_queue_factory.h',
-                              'src/core/lib/surface/event_string.h',
-                              'src/core/lib/surface/init.h',
-                              'src/core/lib/surface/lame_client.h',
-                              'src/core/lib/surface/server.h',
-                              'src/core/lib/surface/validate_metadata.h',
-                              'src/core/lib/transport/bdp_estimator.h',
-                              'src/core/lib/transport/byte_stream.h',
-                              'src/core/lib/transport/connectivity_state.h',
-                              'src/core/lib/transport/error_utils.h',
-                              'src/core/lib/transport/http2_errors.h',
-                              'src/core/lib/transport/metadata.h',
-                              'src/core/lib/transport/metadata_batch.h',
-                              'src/core/lib/transport/pid_controller.h',
-                              'src/core/lib/transport/service_config.h',
-                              'src/core/lib/transport/static_metadata.h',
-                              'src/core/lib/transport/status_conversion.h',
-                              'src/core/lib/transport/status_metadata.h',
-                              'src/core/lib/transport/timeout_encoding.h',
-                              'src/core/lib/transport/transport.h',
-                              'src/core/lib/transport/transport_impl.h',
-                              'src/core/lib/debug/trace.h',
-                              'src/core/ext/filters/deadline/deadline_filter.h',
-                              'src/core/ext/filters/client_channel/backup_poller.h',
-                              'src/core/ext/filters/client_channel/client_channel.h',
-                              'src/core/ext/filters/client_channel/client_channel_factory.h',
-                              'src/core/ext/filters/client_channel/connector.h',
-                              'src/core/ext/filters/client_channel/http_connect_handshaker.h',
-                              'src/core/ext/filters/client_channel/http_proxy.h',
-                              'src/core/ext/filters/client_channel/lb_policy.h',
-                              'src/core/ext/filters/client_channel/lb_policy_factory.h',
-                              'src/core/ext/filters/client_channel/lb_policy_registry.h',
-                              'src/core/ext/filters/client_channel/method_params.h',
-                              'src/core/ext/filters/client_channel/parse_address.h',
-                              'src/core/ext/filters/client_channel/proxy_mapper.h',
-                              'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
-                              'src/core/ext/filters/client_channel/resolver.h',
-                              'src/core/ext/filters/client_channel/resolver_factory.h',
-                              'src/core/ext/filters/client_channel/resolver_registry.h',
-                              'src/core/ext/filters/client_channel/retry_throttle.h',
-                              'src/core/ext/filters/client_channel/subchannel.h',
-                              'src/core/ext/filters/client_channel/subchannel_index.h',
-                              'src/core/ext/filters/client_channel/uri_parser.h',
-                              'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
-                              'src/core/ext/filters/max_age/max_age_filter.h',
-                              'src/core/ext/filters/message_size/message_size_filter.h',
-                              'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
-                              'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
-                              'src/core/ext/transport/cronet/transport/cronet_transport.h',
-                              'third_party/objective_c/Cronet/bidirectional_stream_c.h',
-                              'src/core/ext/transport/chttp2/transport/bin_decoder.h',
-                              'src/core/ext/transport/chttp2/transport/bin_encoder.h',
-                              'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
-                              'src/core/ext/transport/chttp2/transport/flow_control.h',
-                              'src/core/ext/transport/chttp2/transport/frame.h',
-                              'src/core/ext/transport/chttp2/transport/frame_data.h',
-                              'src/core/ext/transport/chttp2/transport/frame_goaway.h',
-                              'src/core/ext/transport/chttp2/transport/frame_ping.h',
-                              'src/core/ext/transport/chttp2/transport/frame_rst_stream.h',
-                              'src/core/ext/transport/chttp2/transport/frame_settings.h',
-                              'src/core/ext/transport/chttp2/transport/frame_window_update.h',
-                              'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
-                              'src/core/ext/transport/chttp2/transport/hpack_parser.h',
-                              'src/core/ext/transport/chttp2/transport/hpack_table.h',
-                              'src/core/ext/transport/chttp2/transport/http2_settings.h',
-                              'src/core/ext/transport/chttp2/transport/huffsyms.h',
-                              'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
-                              'src/core/ext/transport/chttp2/transport/internal.h',
-                              'src/core/ext/transport/chttp2/transport/stream_map.h',
-                              'src/core/ext/transport/chttp2/transport/varint.h',
-                              'src/core/ext/transport/chttp2/alpn/alpn.h',
-                              'src/core/ext/filters/http/client/http_client_filter.h',
-                              'src/core/ext/filters/http/message_compress/message_compress_filter.h',
-                              'src/core/ext/filters/http/server/http_server_filter.h',
-                              'src/core/lib/security/context/security_context.h',
-                              'src/core/lib/security/credentials/alts/alts_credentials.h',
-                              'src/core/lib/security/credentials/composite/composite_credentials.h',
-                              'src/core/lib/security/credentials/credentials.h',
-                              'src/core/lib/security/credentials/fake/fake_credentials.h',
-                              'src/core/lib/security/credentials/google_default/google_default_credentials.h',
-                              'src/core/lib/security/credentials/iam/iam_credentials.h',
-                              'src/core/lib/security/credentials/jwt/json_token.h',
-                              'src/core/lib/security/credentials/jwt/jwt_credentials.h',
-                              'src/core/lib/security/credentials/jwt/jwt_verifier.h',
-                              'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
-                              'src/core/lib/security/credentials/plugin/plugin_credentials.h',
-                              'src/core/lib/security/credentials/ssl/ssl_credentials.h',
-                              'src/core/lib/security/security_connector/alts_security_connector.h',
-                              'src/core/lib/security/security_connector/security_connector.h',
-                              'src/core/lib/security/transport/auth_filters.h',
-                              'src/core/lib/security/transport/secure_endpoint.h',
-                              'src/core/lib/security/transport/security_handshaker.h',
-                              'src/core/lib/security/transport/target_authority_table.h',
-                              'src/core/lib/security/transport/tsi_error.h',
-                              'src/core/lib/security/util/json_util.h',
-                              'src/core/tsi/alts/crypt/gsec.h',
-                              'src/core/tsi/alts/frame_protector/alts_counter.h',
-                              'src/core/tsi/alts/frame_protector/alts_crypter.h',
-                              'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
-                              'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
-                              'src/core/tsi/alts/frame_protector/frame_handler.h',
-                              'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
-                              'src/core/tsi/alts/handshaker/alts_tsi_event.h',
-                              'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
-                              'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
-                              'src/core/lib/security/credentials/alts/check_gcp_environment.h',
-                              'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
-                              'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
-                              'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
-                              'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
-                              'src/core/tsi/alts/handshaker/transport_security_common_api.h',
-                              'src/core/tsi/alts/handshaker/altscontext.pb.h',
-                              'src/core/tsi/alts/handshaker/handshaker.pb.h',
-                              'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
-                              'third_party/nanopb/pb.h',
-                              'third_party/nanopb/pb_common.h',
-                              'third_party/nanopb/pb_decode.h',
-                              'third_party/nanopb/pb_encode.h',
-                              'src/core/tsi/transport_security.h',
-                              'src/core/tsi/transport_security_adapter.h',
-                              'src/core/tsi/transport_security_interface.h',
-                              'src/core/ext/transport/chttp2/client/chttp2_connector.h',
-                              'src/core/tsi/alts_transport_security.h',
-                              'src/core/tsi/fake_transport_security.h',
-                              'src/core/tsi/ssl/session_cache/ssl_session.h',
-                              'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
-                              'src/core/tsi/ssl_transport_security.h',
-                              'src/core/tsi/ssl_types.h',
-                              'src/core/tsi/transport_security_grpc.h',
-                              'src/core/ext/transport/chttp2/server/chttp2_server.h'
+                      'src/core/ext/transport/cronet/transport/cronet_transport.h',
+                      'third_party/objective_c/Cronet/bidirectional_stream_c.h',
+                      'third_party/nanopb/pb.h',
+                      'third_party/nanopb/pb_common.h',
+                      'third_party/nanopb/pb_decode.h',
+                      'third_party/nanopb/pb_encode.h'
   end
 
-  s.subspec 'Cronet-Tests' do |ss|
+  s.subspec 'Tests' do |ss|
     ss.header_mappings_dir = '.'
 
-    ss.dependency "#{s.name}/Cronet-Interface", version
-    ss.dependency "#{s.name}/Cronet-Implementation", version
+    ss.dependency "#{s.name}/Interface", version
+    ss.dependency "#{s.name}/Implementation", version
 
     ss.source_files = 'test/core/util/test_config.cc',
                       'test/core/util/test_config.h',
@@ -2080,6 +1167,7 @@
                       'test/core/end2end/tests/bad_ping.cc',
                       'test/core/end2end/tests/binary_metadata.cc',
                       'test/core/end2end/tests/call_creds.cc',
+                      'test/core/end2end/tests/call_host_override.cc',
                       'test/core/end2end/tests/cancel_after_accept.cc',
                       'test/core/end2end/tests/cancel_after_client_done.cc',
                       'test/core/end2end/tests/cancel_after_invoke.cc',
diff --git a/grpc.gemspec b/grpc.gemspec
index 920254a..4e309f1 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -254,6 +254,7 @@
   s.files += %w( src/core/tsi/transport_security.h )
   s.files += %w( src/core/tsi/transport_security_adapter.h )
   s.files += %w( src/core/tsi/transport_security_interface.h )
+  s.files += %w( src/core/ext/transport/chttp2/client/authority.h )
   s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
   s.files += %w( src/core/ext/filters/client_channel/backup_poller.h )
   s.files += %w( src/core/ext/filters/client_channel/client_channel.h )
@@ -431,6 +432,7 @@
   s.files += %w( src/core/ext/filters/load_reporting/server_load_reporting_plugin.h )
   s.files += %w( src/core/ext/filters/max_age/max_age_filter.h )
   s.files += %w( src/core/ext/filters/message_size/message_size_filter.h )
+  s.files += %w( src/core/ext/filters/http/client_authority_filter.h )
   s.files += %w( src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h )
   s.files += %w( src/core/ext/filters/workarounds/workaround_utils.h )
   s.files += %w( src/core/lib/surface/init.cc )
@@ -675,6 +677,7 @@
   s.files += %w( src/core/tsi/transport_security_adapter.cc )
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.cc )
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc )
+  s.files += %w( src/core/ext/transport/chttp2/client/authority.cc )
   s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.cc )
   s.files += %w( src/core/ext/filters/client_channel/backup_poller.cc )
   s.files += %w( src/core/ext/filters/client_channel/channel_connectivity.cc )
@@ -732,6 +735,7 @@
   s.files += %w( src/core/ext/census/grpc_context.cc )
   s.files += %w( src/core/ext/filters/max_age/max_age_filter.cc )
   s.files += %w( src/core/ext/filters/message_size/message_size_filter.cc )
+  s.files += %w( src/core/ext/filters/http/client_authority_filter.cc )
   s.files += %w( src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc )
   s.files += %w( src/core/ext/filters/workarounds/workaround_utils.cc )
   s.files += %w( src/core/plugin_registry/grpc_plugin_registry.cc )
diff --git a/grpc.gyp b/grpc.gyp
index 36b89f3..3066469 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -484,6 +484,7 @@
         'src/core/tsi/transport_security_adapter.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+        'src/core/ext/transport/chttp2/client/authority.cc',
         'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
         'src/core/ext/filters/client_channel/backup_poller.cc',
         'src/core/ext/filters/client_channel/channel_connectivity.cc',
@@ -541,6 +542,7 @@
         'src/core/ext/census/grpc_context.cc',
         'src/core/ext/filters/max_age/max_age_filter.cc',
         'src/core/ext/filters/message_size/message_size_filter.cc',
+        'src/core/ext/filters/http/client_authority_filter.cc',
         'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
         'src/core/ext/filters/workarounds/workaround_utils.cc',
         'src/core/plugin_registry/grpc_plugin_registry.cc',
@@ -1211,6 +1213,7 @@
         'src/core/ext/transport/chttp2/server/chttp2_server.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+        'src/core/ext/transport/chttp2/client/authority.cc',
         'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
         'src/core/ext/filters/client_channel/backup_poller.cc',
         'src/core/ext/filters/client_channel/channel_connectivity.cc',
@@ -1260,6 +1263,7 @@
         'src/core/ext/census/grpc_context.cc',
         'src/core/ext/filters/max_age/max_age_filter.cc',
         'src/core/ext/filters/message_size/message_size_filter.cc',
+        'src/core/ext/filters/http/client_authority_filter.cc',
         'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
         'src/core/ext/filters/workarounds/workaround_utils.cc',
         'src/core/plugin_registry/grpc_unsecure_plugin_registry.cc',
@@ -2573,6 +2577,7 @@
         'test/core/end2end/tests/bad_ping.cc',
         'test/core/end2end/tests/binary_metadata.cc',
         'test/core/end2end/tests/call_creds.cc',
+        'test/core/end2end/tests/call_host_override.cc',
         'test/core/end2end/tests/cancel_after_accept.cc',
         'test/core/end2end/tests/cancel_after_client_done.cc',
         'test/core/end2end/tests/cancel_after_invoke.cc',
@@ -2661,6 +2666,7 @@
         'test/core/end2end/tests/bad_hostname.cc',
         'test/core/end2end/tests/bad_ping.cc',
         'test/core/end2end/tests/binary_metadata.cc',
+        'test/core/end2end/tests/call_host_override.cc',
         'test/core/end2end/tests/cancel_after_accept.cc',
         'test/core/end2end/tests/cancel_after_client_done.cc',
         'test/core/end2end/tests/cancel_after_invoke.cc',
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 03aaa9f..022be5f 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -333,6 +333,9 @@
 /** Channel arg that carries the bridged objective c object for custom metrics
  * logging filter. */
 #define GRPC_ARG_MOBILE_LOG_CONFIG "grpc.mobile_log_config"
+/** If non-zero, client authority filter is disabled for the channel */
+#define GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER \
+  "grpc.disable_client_authority_filter"
 /** \} */
 
 /** Result of a grpc call. If the caller satisfies the prerequisites of a
diff --git a/include/grpcpp/impl/codegen/byte_buffer.h b/include/grpcpp/impl/codegen/byte_buffer.h
index 8d6a169..e637efe 100644
--- a/include/grpcpp/impl/codegen/byte_buffer.h
+++ b/include/grpcpp/impl/codegen/byte_buffer.h
@@ -31,6 +31,8 @@
 
 namespace grpc {
 
+class ServerInterface;
+
 namespace internal {
 class CallOpSendMessage;
 template <class R>
@@ -98,6 +100,7 @@
 
  private:
   friend class SerializationTraits<ByteBuffer, void>;
+  friend class ServerInterface;
   friend class internal::CallOpSendMessage;
   template <class R>
   friend class internal::CallOpRecvMessage;
diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h
index 4700763..cf330ac 100644
--- a/include/grpcpp/impl/codegen/server_interface.h
+++ b/include/grpcpp/impl/codegen/server_interface.h
@@ -20,6 +20,7 @@
 #define GRPCPP_IMPL_CODEGEN_SERVER_INTERFACE_H
 
 #include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
 #include <grpcpp/impl/codegen/call_hook.h>
 #include <grpcpp/impl/codegen/completion_queue_tag.h>
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
@@ -185,14 +186,18 @@
           notification_cq_(notification_cq),
           tag_(tag),
           request_(request) {
-      IssueRequest(registered_method, &payload_, notification_cq);
+      IssueRequest(registered_method, payload_.bbuf_ptr(), notification_cq);
+    }
+
+    ~PayloadAsyncRequest() {
+      payload_.Release();  // We do not own the payload_
     }
 
     bool FinalizeResult(void** tag, bool* status) override {
       if (*status) {
-        if (payload_ == nullptr ||
-            !SerializationTraits<Message>::Deserialize(payload_, request_)
-                 .ok()) {
+        if (!payload_.Valid() || !SerializationTraits<Message>::Deserialize(
+                                      payload_.bbuf_ptr(), request_)
+                                      .ok()) {
           // If deserialization fails, we cancel the call and instantiate
           // a new instance of ourselves to request another call.  We then
           // return false, which prevents the call from being returned to
@@ -219,7 +224,7 @@
     ServerCompletionQueue* const notification_cq_;
     void* const tag_;
     Message* const request_;
-    grpc_byte_buffer* payload_;
+    ByteBuffer payload_;
   };
 
   class GenericAsyncRequest : public BaseAsyncRequest {
diff --git a/package.xml b/package.xml
index 52d5cc9..fd43006 100644
--- a/package.xml
+++ b/package.xml
@@ -261,6 +261,7 @@
     <file baseinstalldir="/" name="src/core/tsi/transport_security.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security_adapter.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security_interface.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/authority.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/backup_poller.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel.h" role="src" />
@@ -438,6 +439,7 @@
     <file baseinstalldir="/" name="src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/http/client_authority_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_utils.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init.cc" role="src" />
@@ -682,6 +684,7 @@
     <file baseinstalldir="/" name="src/core/tsi/transport_security_adapter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/authority.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/backup_poller.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/channel_connectivity.cc" role="src" />
@@ -739,6 +742,7 @@
     <file baseinstalldir="/" name="src/core/ext/census/grpc_context.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/http/client_authority_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_utils.cc" role="src" />
     <file baseinstalldir="/" name="src/core/plugin_registry/grpc_plugin_registry.cc" role="src" />
diff --git a/setup.py b/setup.py
index 97a3107..67c36a9 100644
--- a/setup.py
+++ b/setup.py
@@ -104,9 +104,9 @@
 EXTRA_ENV_COMPILE_ARGS = os.environ.get('GRPC_PYTHON_CFLAGS', None)
 EXTRA_ENV_LINK_ARGS = os.environ.get('GRPC_PYTHON_LDFLAGS', None)
 if EXTRA_ENV_COMPILE_ARGS is None:
-  EXTRA_ENV_COMPILE_ARGS = ''
+  EXTRA_ENV_COMPILE_ARGS = ' -std=c++11'
   if 'win32' in sys.platform and sys.version_info < (3, 5):
-    EXTRA_ENV_COMPILE_ARGS += ' -std=c++11'
+    EXTRA_ENV_COMPILE_ARGS += ' -D_hypot=hypot'
     # We use define flags here and don't directly add to DEFINE_MACROS below to
     # ensure that the expert user/builder has a way of turning it off (via the
     # envvars) without adding yet more GRPC-specific envvars.
@@ -116,10 +116,10 @@
     else:
       EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
   elif "linux" in sys.platform:
-    EXTRA_ENV_COMPILE_ARGS += ' -std=c++11 -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
+    EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
   elif "darwin" in sys.platform:
     EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv -fno-exceptions'
-EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_16BIT'	
+EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_16BIT'
 
 if EXTRA_ENV_LINK_ARGS is None:
   EXTRA_ENV_LINK_ARGS = ''
@@ -182,7 +182,7 @@
 CFLAGS = tuple(EXTRA_COMPILE_ARGS)
 if "linux" in sys.platform or "darwin" in sys.platform:
   pymodinit_type = 'PyObject*' if PY3 else 'void'
-  pymodinit = '__attribute__((visibility ("default"))) {}'.format(pymodinit_type)
+  pymodinit = 'extern "C" __attribute__((visibility ("default"))) {}'.format(pymodinit_type)
   DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
   DEFINE_MACROS += (('GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK', 1),)
 
diff --git a/src/compiler/ruby_generator.cc b/src/compiler/ruby_generator.cc
index e81dea6..c7af9c3 100644
--- a/src/compiler/ruby_generator.cc
+++ b/src/compiler/ruby_generator.cc
@@ -73,7 +73,7 @@
   // Begin the service module
   std::map<grpc::string, grpc::string> module_vars = ListToDict({
       "module.name",
-      CapitalizeFirst(service->name()),
+      Modularize(service->name()),
   });
   out->Print(module_vars, "module $module.name$\n");
   out->Indent();
diff --git a/src/compiler/ruby_generator_string-inl.h b/src/compiler/ruby_generator_string-inl.h
index fb42978..ecfe796 100644
--- a/src/compiler/ruby_generator_string-inl.h
+++ b/src/compiler/ruby_generator_string-inl.h
@@ -81,13 +81,23 @@
   return true;
 }
 
-// CapitalizeFirst capitalizes the first char in a string.
-inline grpc::string CapitalizeFirst(grpc::string s) {
+// Modularize converts a string into a ruby module compatible name
+inline grpc::string Modularize(grpc::string s) {
   if (s.empty()) {
     return s;
   }
-  s[0] = ::toupper(s[0]);
-  return s;
+  grpc::string new_string = "";
+  bool was_last_underscore = false;
+  new_string.append(1, ::toupper(s[0]));
+  for (grpc::string::size_type i = 1; i < s.size(); ++i) {
+    if (was_last_underscore && s[i] != '_') {
+      new_string.append(1, ::toupper(s[i]));
+    } else if (s[i] != '_') {
+      new_string.append(1, s[i]);
+    }
+    was_last_underscore = s[i] == '_';
+  }
+  return new_string;
 }
 
 // RubyTypeOf updates a proto type to the required ruby equivalent.
@@ -106,7 +116,7 @@
         res += "::";  // switch '.' to the ruby module delim
       }
       if (i < prefixes_and_type.size() - 1) {
-        res += CapitalizeFirst(prefixes_and_type[i]);  // capitalize pkgs
+        res += Modularize(prefixes_and_type[i]);  // capitalize pkgs
       } else {
         res += prefixes_and_type[i];
       }
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 67dd3a1..51f9ae0 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -63,6 +63,7 @@
 #include "src/core/lib/transport/status_metadata.h"
 
 using grpc_core::internal::ClientChannelMethodParams;
+using grpc_core::internal::ServerRetryThrottleData;
 
 /* Client channel implementation */
 
@@ -99,7 +100,7 @@
   /** currently active load balancer */
   grpc_core::OrphanablePtr<grpc_core::LoadBalancingPolicy> lb_policy;
   /** retry throttle data */
-  grpc_server_retry_throttle_data* retry_throttle_data;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
   /** maps method names to method_parameters structs */
   grpc_core::RefCountedPtr<MethodParamsTable> method_params_table;
   /** incoming resolver result - set by resolver.next() */
@@ -225,7 +226,7 @@
 
 typedef struct {
   char* server_name;
-  grpc_server_retry_throttle_data* retry_throttle_data;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
 } service_config_parsing_state;
 
 static void parse_retry_throttle_params(
@@ -278,7 +279,7 @@
       }
     }
     parsing_state->retry_throttle_data =
-        grpc_retry_throttle_map_get_data_for_server(
+        grpc_core::internal::ServerRetryThrottleMap::GetDataForServer(
             parsing_state->server_name, max_milli_tokens, milli_token_ratio);
   }
 }
@@ -321,7 +322,7 @@
   bool lb_policy_name_changed = false;
   grpc_core::OrphanablePtr<grpc_core::LoadBalancingPolicy> new_lb_policy;
   char* service_config_json = nullptr;
-  grpc_server_retry_throttle_data* retry_throttle_data = nullptr;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
   grpc_core::RefCountedPtr<MethodParamsTable> method_params_table;
   if (chand->resolver_result != nullptr) {
     if (chand->resolver != nullptr) {
@@ -421,7 +422,7 @@
             service_config->ParseGlobalParams(parse_retry_throttle_params,
                                               &parsing_state);
             grpc_uri_destroy(uri);
-            retry_throttle_data = parsing_state.retry_throttle_data;
+            retry_throttle_data = std::move(parsing_state.retry_throttle_data);
           }
           method_params_table = service_config->CreateMethodConfigTable(
               ClientChannelMethodParams::CreateFromJson);
@@ -452,10 +453,7 @@
   }
   gpr_mu_unlock(&chand->info_mu);
   // Swap out the retry throttle data.
-  if (chand->retry_throttle_data != nullptr) {
-    grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
-  }
-  chand->retry_throttle_data = retry_throttle_data;
+  chand->retry_throttle_data = std::move(retry_throttle_data);
   // Swap out the method params table.
   chand->method_params_table = std::move(method_params_table);
   // If we have a new LB policy or are shutting down (in which case
@@ -725,12 +723,8 @@
   }
   gpr_free(chand->info_lb_policy_name);
   gpr_free(chand->info_service_config_json);
-  if (chand->retry_throttle_data != nullptr) {
-    grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
-  }
-  if (chand->method_params_table != nullptr) {
-    chand->method_params_table.reset();
-  }
+  chand->retry_throttle_data.reset();
+  chand->method_params_table.reset();
   grpc_client_channel_stop_backup_polling(chand->interested_parties);
   grpc_connectivity_state_destroy(&chand->state_tracker);
   grpc_pollset_set_destroy(chand->interested_parties);
@@ -883,7 +877,7 @@
   grpc_call_stack* owning_call;
   grpc_call_combiner* call_combiner;
 
-  grpc_server_retry_throttle_data* retry_throttle_data;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
   grpc_core::RefCountedPtr<ClientChannelMethodParams> method_params;
 
   grpc_subchannel_call* subchannel_call;
@@ -1443,7 +1437,9 @@
   }
   // Check status.
   if (status == GRPC_STATUS_OK) {
-    grpc_server_retry_throttle_data_record_success(calld->retry_throttle_data);
+    if (calld->retry_throttle_data != nullptr) {
+      calld->retry_throttle_data->RecordSuccess();
+    }
     if (grpc_client_channel_trace.enabled()) {
       gpr_log(GPR_DEBUG, "chand=%p calld=%p: call succeeded", chand, calld);
     }
@@ -1465,8 +1461,8 @@
   // things like failures due to malformed requests (INVALID_ARGUMENT).
   // Conversely, it's important for this to come before the remaining
   // checks, so that we don't fail to record failures due to other factors.
-  if (!grpc_server_retry_throttle_data_record_failure(
-          calld->retry_throttle_data)) {
+  if (calld->retry_throttle_data != nullptr &&
+      !calld->retry_throttle_data->RecordFailure()) {
     if (grpc_client_channel_trace.enabled()) {
       gpr_log(GPR_DEBUG, "chand=%p calld=%p: retries throttled", chand, calld);
     }
@@ -2601,8 +2597,7 @@
             chand, calld);
   }
   if (chand->retry_throttle_data != nullptr) {
-    calld->retry_throttle_data =
-        grpc_server_retry_throttle_data_ref(chand->retry_throttle_data);
+    calld->retry_throttle_data = chand->retry_throttle_data->Ref();
   }
   if (chand->method_params_table != nullptr) {
     calld->method_params = grpc_core::ServiceConfig::MethodConfigTableLookup(
@@ -2994,6 +2989,7 @@
     grpc_deadline_state_destroy(elem);
   }
   grpc_slice_unref_internal(calld->path);
+  calld->retry_throttle_data.reset();
   calld->method_params.reset();
   GRPC_ERROR_UNREF(calld->cancel_error);
   if (calld->subchannel_call != nullptr) {
diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.cc b/src/core/ext/filters/client_channel/client_channel_plugin.cc
index 3c3a975..8385852 100644
--- a/src/core/ext/filters/client_channel/client_channel_plugin.cc
+++ b/src/core/ext/filters/client_channel/client_channel_plugin.cc
@@ -39,38 +39,13 @@
       builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
 }
 
-static bool set_default_host_if_unset(grpc_channel_stack_builder* builder,
-                                      void* unused) {
-  const grpc_channel_args* args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  for (size_t i = 0; i < args->num_args; i++) {
-    if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY) ||
-        0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
-      return true;
-    }
-  }
-  grpc_core::UniquePtr<char> default_authority =
-      grpc_core::ResolverRegistry::GetDefaultAuthority(
-          grpc_channel_stack_builder_get_target(builder));
-  if (default_authority.get() != nullptr) {
-    grpc_arg arg = grpc_channel_arg_string_create(
-        (char*)GRPC_ARG_DEFAULT_AUTHORITY, default_authority.get());
-    grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
-    grpc_channel_stack_builder_set_channel_arguments(builder, new_args);
-    grpc_channel_args_destroy(new_args);
-  }
-  return true;
-}
-
 void grpc_client_channel_init(void) {
   grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry();
   grpc_core::ResolverRegistry::Builder::InitRegistry();
-  grpc_retry_throttle_map_init();
+  grpc_core::internal::ServerRetryThrottleMap::Init();
   grpc_proxy_mapper_registry_init();
   grpc_register_http_proxy_mapper();
   grpc_subchannel_index_init();
-  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN,
-                                   set_default_host_if_unset, nullptr);
   grpc_channel_init_register_stage(
       GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter,
       (void*)&grpc_client_channel_filter);
@@ -81,7 +56,7 @@
   grpc_subchannel_index_shutdown();
   grpc_channel_init_shutdown();
   grpc_proxy_mapper_registry_shutdown();
-  grpc_retry_throttle_map_shutdown();
+  grpc_core::internal::ServerRetryThrottleMap::Shutdown();
   grpc_core::ResolverRegistry::Builder::ShutdownRegistry();
   grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry();
 }
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index e805593..0b2a308 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -505,9 +505,7 @@
   // the polling entities from client_channel.
   GPR_ASSERT(grpclb_policy()->server_name_ != nullptr);
   GPR_ASSERT(grpclb_policy()->server_name_[0] != '\0');
-  grpc_slice host =
-      grpc_slice_from_copied_string(grpclb_policy()->server_name_);
-  grpc_millis deadline =
+  const grpc_millis deadline =
       grpclb_policy()->lb_call_timeout_ms_ == 0
           ? GRPC_MILLIS_INF_FUTURE
           : ExecCtx::Get()->Now() + grpclb_policy()->lb_call_timeout_ms_;
@@ -515,8 +513,7 @@
       grpclb_policy()->lb_channel_, nullptr, GRPC_PROPAGATE_DEFAULTS,
       grpclb_policy_->interested_parties(),
       GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
-      &host, deadline, nullptr);
-  grpc_slice_unref_internal(host);
+      nullptr, deadline, nullptr);
   // Init the LB call request payload.
   grpc_grpclb_request* request =
       grpc_grpclb_request_create(grpclb_policy()->server_name_);
@@ -983,6 +980,14 @@
       // with the one from the grpclb policy, used to propagate updates to
       // the LB channel.
       GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR,
+      // The LB channel should use the authority indicated by the target
+      // authority table (see \a grpc_lb_policy_grpclb_modify_lb_channel_args),
+      // as opposed to the authority from the parent channel.
+      GRPC_ARG_DEFAULT_AUTHORITY,
+      // Just as for \a GRPC_ARG_DEFAULT_AUTHORITY, the LB channel should be
+      // treated as a stand-alone channel and not inherit this argument from the
+      // args of the parent channel.
+      GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
   };
   // Channel args to add.
   const grpc_arg args_to_add[] = {
diff --git a/src/core/ext/filters/client_channel/retry_throttle.cc b/src/core/ext/filters/client_channel/retry_throttle.cc
index 45de666..bdeb7e4 100644
--- a/src/core/ext/filters/client_channel/retry_throttle.cc
+++ b/src/core/ext/filters/client_channel/retry_throttle.cc
@@ -30,184 +30,162 @@
 
 #include "src/core/lib/avl/avl.h"
 
+namespace grpc_core {
+namespace internal {
+
 //
-// server_retry_throttle_data
+// ServerRetryThrottleData
 //
 
-struct grpc_server_retry_throttle_data {
-  gpr_refcount refs;
-  int max_milli_tokens;
-  int milli_token_ratio;
-  gpr_atm milli_tokens;
-  // A pointer to the replacement for this grpc_server_retry_throttle_data
-  // entry.  If non-nullptr, then this entry is stale and must not be used.
-  // We hold a reference to the replacement.
-  gpr_atm replacement;
-};
-
-static void get_replacement_throttle_data_if_needed(
-    grpc_server_retry_throttle_data** throttle_data) {
-  while (true) {
-    grpc_server_retry_throttle_data* new_throttle_data =
-        (grpc_server_retry_throttle_data*)gpr_atm_acq_load(
-            &(*throttle_data)->replacement);
-    if (new_throttle_data == nullptr) return;
-    *throttle_data = new_throttle_data;
-  }
-}
-
-bool grpc_server_retry_throttle_data_record_failure(
-    grpc_server_retry_throttle_data* throttle_data) {
-  if (throttle_data == nullptr) return true;
-  // First, check if we are stale and need to be replaced.
-  get_replacement_throttle_data_if_needed(&throttle_data);
-  // We decrement milli_tokens by 1000 (1 token) for each failure.
-  const int new_value = static_cast<int>(gpr_atm_no_barrier_clamped_add(
-      &throttle_data->milli_tokens, static_cast<gpr_atm>(-1000),
-      static_cast<gpr_atm>(0),
-      static_cast<gpr_atm>(throttle_data->max_milli_tokens)));
-  // Retries are allowed as long as the new value is above the threshold
-  // (max_milli_tokens / 2).
-  return new_value > throttle_data->max_milli_tokens / 2;
-}
-
-void grpc_server_retry_throttle_data_record_success(
-    grpc_server_retry_throttle_data* throttle_data) {
-  if (throttle_data == nullptr) return;
-  // First, check if we are stale and need to be replaced.
-  get_replacement_throttle_data_if_needed(&throttle_data);
-  // We increment milli_tokens by milli_token_ratio for each success.
-  gpr_atm_no_barrier_clamped_add(
-      &throttle_data->milli_tokens,
-      static_cast<gpr_atm>(throttle_data->milli_token_ratio),
-      static_cast<gpr_atm>(0),
-      static_cast<gpr_atm>(throttle_data->max_milli_tokens));
-}
-
-grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_ref(
-    grpc_server_retry_throttle_data* throttle_data) {
-  gpr_ref(&throttle_data->refs);
-  return throttle_data;
-}
-
-void grpc_server_retry_throttle_data_unref(
-    grpc_server_retry_throttle_data* throttle_data) {
-  if (gpr_unref(&throttle_data->refs)) {
-    grpc_server_retry_throttle_data* replacement =
-        (grpc_server_retry_throttle_data*)gpr_atm_acq_load(
-            &throttle_data->replacement);
-    if (replacement != nullptr) {
-      grpc_server_retry_throttle_data_unref(replacement);
-    }
-    gpr_free(throttle_data);
-  }
-}
-
-static grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_create(
-    int max_milli_tokens, int milli_token_ratio,
-    grpc_server_retry_throttle_data* old_throttle_data) {
-  grpc_server_retry_throttle_data* throttle_data =
-      static_cast<grpc_server_retry_throttle_data*>(
-          gpr_malloc(sizeof(*throttle_data)));
-  memset(throttle_data, 0, sizeof(*throttle_data));
-  gpr_ref_init(&throttle_data->refs, 1);
-  throttle_data->max_milli_tokens = max_milli_tokens;
-  throttle_data->milli_token_ratio = milli_token_ratio;
-  int initial_milli_tokens = max_milli_tokens;
+ServerRetryThrottleData::ServerRetryThrottleData(
+    intptr_t max_milli_tokens, intptr_t milli_token_ratio,
+    ServerRetryThrottleData* old_throttle_data)
+    : max_milli_tokens_(max_milli_tokens),
+      milli_token_ratio_(milli_token_ratio) {
+  intptr_t initial_milli_tokens = max_milli_tokens;
   // If there was a pre-existing entry for this server name, initialize
   // the token count by scaling proportionately to the old data.  This
   // ensures that if we're already throttling retries on the old scale,
   // we will start out doing the same thing on the new one.
   if (old_throttle_data != nullptr) {
     double token_fraction =
-        static_cast<int>(gpr_atm_acq_load(&old_throttle_data->milli_tokens)) /
-        static_cast<double>(old_throttle_data->max_milli_tokens);
-    initial_milli_tokens = static_cast<int>(token_fraction * max_milli_tokens);
+        static_cast<intptr_t>(
+            gpr_atm_acq_load(&old_throttle_data->milli_tokens_)) /
+        static_cast<double>(old_throttle_data->max_milli_tokens_);
+    initial_milli_tokens =
+        static_cast<intptr_t>(token_fraction * max_milli_tokens);
   }
-  gpr_atm_rel_store(&throttle_data->milli_tokens,
-                    (gpr_atm)initial_milli_tokens);
+  gpr_atm_rel_store(&milli_tokens_, static_cast<gpr_atm>(initial_milli_tokens));
   // If there was a pre-existing entry, mark it as stale and give it a
   // pointer to the new entry, which is its replacement.
   if (old_throttle_data != nullptr) {
-    grpc_server_retry_throttle_data_ref(throttle_data);
-    gpr_atm_rel_store(&old_throttle_data->replacement, (gpr_atm)throttle_data);
+    Ref().release();  // Ref held by pre-existing entry.
+    gpr_atm_rel_store(&old_throttle_data->replacement_,
+                      reinterpret_cast<gpr_atm>(this));
   }
-  return throttle_data;
+}
+
+ServerRetryThrottleData::~ServerRetryThrottleData() {
+  ServerRetryThrottleData* replacement =
+      reinterpret_cast<ServerRetryThrottleData*>(
+          gpr_atm_acq_load(&replacement_));
+  if (replacement != nullptr) {
+    replacement->Unref();
+  }
+}
+
+void ServerRetryThrottleData::GetReplacementThrottleDataIfNeeded(
+    ServerRetryThrottleData** throttle_data) {
+  while (true) {
+    ServerRetryThrottleData* new_throttle_data =
+        reinterpret_cast<ServerRetryThrottleData*>(
+            gpr_atm_acq_load(&(*throttle_data)->replacement_));
+    if (new_throttle_data == nullptr) return;
+    *throttle_data = new_throttle_data;
+  }
+}
+
+bool ServerRetryThrottleData::RecordFailure() {
+  // First, check if we are stale and need to be replaced.
+  ServerRetryThrottleData* throttle_data = this;
+  GetReplacementThrottleDataIfNeeded(&throttle_data);
+  // We decrement milli_tokens by 1000 (1 token) for each failure.
+  const intptr_t new_value =
+      static_cast<intptr_t>(gpr_atm_no_barrier_clamped_add(
+          &throttle_data->milli_tokens_, static_cast<gpr_atm>(-1000),
+          static_cast<gpr_atm>(0),
+          static_cast<gpr_atm>(throttle_data->max_milli_tokens_)));
+  // Retries are allowed as long as the new value is above the threshold
+  // (max_milli_tokens / 2).
+  return new_value > throttle_data->max_milli_tokens_ / 2;
+}
+
+void ServerRetryThrottleData::RecordSuccess() {
+  // First, check if we are stale and need to be replaced.
+  ServerRetryThrottleData* throttle_data = this;
+  GetReplacementThrottleDataIfNeeded(&throttle_data);
+  // We increment milli_tokens by milli_token_ratio for each success.
+  gpr_atm_no_barrier_clamped_add(
+      &throttle_data->milli_tokens_,
+      static_cast<gpr_atm>(throttle_data->milli_token_ratio_),
+      static_cast<gpr_atm>(0),
+      static_cast<gpr_atm>(throttle_data->max_milli_tokens_));
 }
 
 //
 // avl vtable for string -> server_retry_throttle_data map
 //
 
-static void* copy_server_name(void* key, void* unused) {
+namespace {
+
+void* copy_server_name(void* key, void* unused) {
   return gpr_strdup(static_cast<const char*>(key));
 }
 
-static long compare_server_name(void* key1, void* key2, void* unused) {
+long compare_server_name(void* key1, void* key2, void* unused) {
   return strcmp(static_cast<const char*>(key1), static_cast<const char*>(key2));
 }
 
-static void destroy_server_retry_throttle_data(void* value, void* unused) {
-  grpc_server_retry_throttle_data* throttle_data =
-      static_cast<grpc_server_retry_throttle_data*>(value);
-  grpc_server_retry_throttle_data_unref(throttle_data);
+void destroy_server_retry_throttle_data(void* value, void* unused) {
+  ServerRetryThrottleData* throttle_data =
+      static_cast<ServerRetryThrottleData*>(value);
+  throttle_data->Unref();
 }
 
-static void* copy_server_retry_throttle_data(void* value, void* unused) {
-  grpc_server_retry_throttle_data* throttle_data =
-      static_cast<grpc_server_retry_throttle_data*>(value);
-  return grpc_server_retry_throttle_data_ref(throttle_data);
+void* copy_server_retry_throttle_data(void* value, void* unused) {
+  ServerRetryThrottleData* throttle_data =
+      static_cast<ServerRetryThrottleData*>(value);
+  return throttle_data->Ref().release();
 }
 
-static void destroy_server_name(void* key, void* unused) { gpr_free(key); }
+void destroy_server_name(void* key, void* unused) { gpr_free(key); }
 
-static const grpc_avl_vtable avl_vtable = {
+const grpc_avl_vtable avl_vtable = {
     destroy_server_name, copy_server_name, compare_server_name,
     destroy_server_retry_throttle_data, copy_server_retry_throttle_data};
 
+}  // namespace
+
 //
-// server_retry_throttle_map
+// ServerRetryThrottleMap
 //
 
 static gpr_mu g_mu;
 static grpc_avl g_avl;
 
-void grpc_retry_throttle_map_init() {
+void ServerRetryThrottleMap::Init() {
   gpr_mu_init(&g_mu);
   g_avl = grpc_avl_create(&avl_vtable);
 }
 
-void grpc_retry_throttle_map_shutdown() {
+void ServerRetryThrottleMap::Shutdown() {
   gpr_mu_destroy(&g_mu);
   grpc_avl_unref(g_avl, nullptr);
 }
 
-grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server(
-    const char* server_name, int max_milli_tokens, int milli_token_ratio) {
+RefCountedPtr<ServerRetryThrottleData> ServerRetryThrottleMap::GetDataForServer(
+    const char* server_name, intptr_t max_milli_tokens,
+    intptr_t milli_token_ratio) {
+  RefCountedPtr<ServerRetryThrottleData> result;
   gpr_mu_lock(&g_mu);
-  grpc_server_retry_throttle_data* throttle_data =
-      static_cast<grpc_server_retry_throttle_data*>(
+  ServerRetryThrottleData* throttle_data =
+      static_cast<ServerRetryThrottleData*>(
           grpc_avl_get(g_avl, const_cast<char*>(server_name), nullptr));
-  if (throttle_data == nullptr) {
-    // Entry not found.  Create a new one.
-    throttle_data = grpc_server_retry_throttle_data_create(
-        max_milli_tokens, milli_token_ratio, nullptr);
-    g_avl = grpc_avl_add(g_avl, const_cast<char*>(server_name), throttle_data,
-                         nullptr);
+  if (throttle_data == nullptr ||
+      throttle_data->max_milli_tokens() != max_milli_tokens ||
+      throttle_data->milli_token_ratio() != milli_token_ratio) {
+    // Entry not found, or found with old parameters.  Create a new one.
+    result = MakeRefCounted<ServerRetryThrottleData>(
+        max_milli_tokens, milli_token_ratio, throttle_data);
+    g_avl = grpc_avl_add(g_avl, gpr_strdup(server_name),
+                         result->Ref().release(), nullptr);
   } else {
-    if (throttle_data->max_milli_tokens != max_milli_tokens ||
-        throttle_data->milli_token_ratio != milli_token_ratio) {
-      // Entry found but with old parameters.  Create a new one based on
-      // the original one.
-      throttle_data = grpc_server_retry_throttle_data_create(
-          max_milli_tokens, milli_token_ratio, throttle_data);
-      g_avl = grpc_avl_add(g_avl, const_cast<char*>(server_name), throttle_data,
-                           nullptr);
-    } else {
-      // Entry found.  Increase refcount.
-      grpc_server_retry_throttle_data_ref(throttle_data);
-    }
+    // Entry found.  Return a new ref to it.
+    result = throttle_data->Ref();
   }
   gpr_mu_unlock(&g_mu);
-  return throttle_data;
+  return result;
 }
+
+}  // namespace internal
+}  // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/retry_throttle.h b/src/core/ext/filters/client_channel/retry_throttle.h
index 0505fc2..2b6fa0a 100644
--- a/src/core/ext/filters/client_channel/retry_throttle.h
+++ b/src/core/ext/filters/client_channel/retry_throttle.h
@@ -21,32 +21,57 @@
 
 #include <grpc/support/port_platform.h>
 
-#include <stdbool.h>
+#include "src/core/lib/gprpp/ref_counted.h"
+
+namespace grpc_core {
+namespace internal {
 
 /// Tracks retry throttling data for an individual server name.
-typedef struct grpc_server_retry_throttle_data grpc_server_retry_throttle_data;
+class ServerRetryThrottleData : public RefCounted<ServerRetryThrottleData> {
+ public:
+  ServerRetryThrottleData(intptr_t max_milli_tokens, intptr_t milli_token_ratio,
+                          ServerRetryThrottleData* old_throttle_data);
 
-/// Records a failure.  Returns true if it's okay to send a retry.
-bool grpc_server_retry_throttle_data_record_failure(
-    grpc_server_retry_throttle_data* throttle_data);
-/// Records a success.
-void grpc_server_retry_throttle_data_record_success(
-    grpc_server_retry_throttle_data* throttle_data);
+  /// Records a failure.  Returns true if it's okay to send a retry.
+  bool RecordFailure();
 
-grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_ref(
-    grpc_server_retry_throttle_data* throttle_data);
-void grpc_server_retry_throttle_data_unref(
-    grpc_server_retry_throttle_data* throttle_data);
+  /// Records a success.
+  void RecordSuccess();
 
-/// Initializes global map of failure data for each server name.
-void grpc_retry_throttle_map_init();
-/// Shuts down global map of failure data for each server name.
-void grpc_retry_throttle_map_shutdown();
+  intptr_t max_milli_tokens() const { return max_milli_tokens_; }
+  intptr_t milli_token_ratio() const { return milli_token_ratio_; }
 
-/// Returns a reference to the failure data for \a server_name, creating
-/// a new entry if needed.
-/// Caller must eventually unref via \a grpc_server_retry_throttle_data_unref().
-grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server(
-    const char* server_name, int max_milli_tokens, int milli_token_ratio);
+ private:
+  ~ServerRetryThrottleData();
+
+  void GetReplacementThrottleDataIfNeeded(
+      ServerRetryThrottleData** throttle_data);
+
+  const intptr_t max_milli_tokens_;
+  const intptr_t milli_token_ratio_;
+  gpr_atm milli_tokens_;
+  // A pointer to the replacement for this ServerRetryThrottleData entry.
+  // If non-nullptr, then this entry is stale and must not be used.
+  // We hold a reference to the replacement.
+  gpr_atm replacement_ = 0;
+};
+
+/// Global map of server name to retry throttle data.
+class ServerRetryThrottleMap {
+ public:
+  /// Initializes global map of failure data for each server name.
+  static void Init();
+  /// Shuts down global map of failure data for each server name.
+  static void Shutdown();
+
+  /// Returns the failure data for \a server_name, creating a new entry if
+  /// needed.
+  static RefCountedPtr<ServerRetryThrottleData> GetDataForServer(
+      const char* server_name, intptr_t max_milli_tokens,
+      intptr_t milli_token_ratio);
+};
+
+}  // namespace internal
+}  // namespace grpc_core
 
 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_THROTTLE_H */
diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc
new file mode 100644
index 0000000..1f57ab5
--- /dev/null
+++ b/src/core/ext/filters/http/client_authority_filter.cc
@@ -0,0 +1,156 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/filters/http/client_authority_filter.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/surface/channel_stack_type.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+namespace {
+
+struct call_data {
+  grpc_linked_mdelem authority_storage;
+  grpc_call_combiner* call_combiner;
+};
+
+struct channel_data {
+  grpc_slice default_authority;
+};
+
+void authority_start_transport_stream_op_batch(
+    grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
+  channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+  call_data* calld = static_cast<call_data*>(elem->call_data);
+  // Handle send_initial_metadata.
+  auto* initial_metadata =
+      batch->payload->send_initial_metadata.send_initial_metadata;
+  // If the initial metadata doesn't already contain :authority, add it.
+  if (batch->send_initial_metadata &&
+      initial_metadata->idx.named.authority == nullptr) {
+    grpc_error* error = grpc_metadata_batch_add_head(
+        initial_metadata, &calld->authority_storage,
+        grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
+                                grpc_slice_ref(chand->default_authority)));
+    if (error != GRPC_ERROR_NONE) {
+      grpc_transport_stream_op_batch_finish_with_failure(batch, error,
+                                                         calld->call_combiner);
+      return;
+    }
+  }
+  // Pass control down the stack.
+  grpc_call_next_op(elem, batch);
+}
+
+/* Constructor for call_data */
+grpc_error* init_call_elem(grpc_call_element* elem,
+                           const grpc_call_element_args* args) {
+  call_data* calld = static_cast<call_data*>(elem->call_data);
+  calld->call_combiner = args->call_combiner;
+  return GRPC_ERROR_NONE;
+}
+
+/* Destructor for call_data */
+void destroy_call_elem(grpc_call_element* elem,
+                       const grpc_call_final_info* final_info,
+                       grpc_closure* ignored) {}
+
+/* Constructor for channel_data */
+grpc_error* init_channel_elem(grpc_channel_element* elem,
+                              grpc_channel_element_args* args) {
+  channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+  const grpc_arg* default_authority_arg =
+      grpc_channel_args_find(args->channel_args, GRPC_ARG_DEFAULT_AUTHORITY);
+  if (default_authority_arg == nullptr) {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "GRPC_ARG_DEFAULT_AUTHORITY channel arg. not found. Note that direct "
+        "channels must explicity specify a value for this argument.");
+  }
+  const char* default_authority_str =
+      grpc_channel_arg_get_string(default_authority_arg);
+  if (default_authority_str == nullptr) {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "GRPC_ARG_DEFAULT_AUTHORITY channel arg. must be a string");
+  }
+  chand->default_authority =
+      grpc_slice_from_copied_string(default_authority_str);
+  GPR_ASSERT(!args->is_last);
+  return GRPC_ERROR_NONE;
+}
+
+/* Destructor for channel data */
+void destroy_channel_elem(grpc_channel_element* elem) {
+  channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+  grpc_slice_unref(chand->default_authority);
+}
+}  // namespace
+
+const grpc_channel_filter grpc_client_authority_filter = {
+    authority_start_transport_stream_op_batch,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset_or_pollset_set,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_channel_next_get_info,
+    "authority"};
+
+static bool add_client_authority_filter(grpc_channel_stack_builder* builder,
+                                        void* arg) {
+  const grpc_channel_args* channel_args =
+      grpc_channel_stack_builder_get_channel_arguments(builder);
+  const grpc_arg* disable_client_authority_filter_arg = grpc_channel_args_find(
+      channel_args, GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER);
+  if (disable_client_authority_filter_arg != nullptr) {
+    const bool is_client_authority_filter_disabled =
+        grpc_channel_arg_get_bool(disable_client_authority_filter_arg, false);
+    if (is_client_authority_filter_disabled) {
+      return true;
+    }
+  }
+  return grpc_channel_stack_builder_prepend_filter(
+      builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
+}
+
+void grpc_client_authority_filter_init(void) {
+  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
+                                   add_client_authority_filter,
+                                   (void*)&grpc_client_authority_filter);
+  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
+                                   add_client_authority_filter,
+                                   (void*)&grpc_client_authority_filter);
+}
+
+void grpc_client_authority_filter_shutdown(void) {}
diff --git a/src/core/ext/filters/http/client_authority_filter.h b/src/core/ext/filters/http/client_authority_filter.h
new file mode 100644
index 0000000..5824e91
--- /dev/null
+++ b/src/core/ext/filters/http/client_authority_filter.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_FILTERS_HTTP_CLIENT_AUTHORITY_FILTER_H
+#define GRPC_CORE_EXT_FILTERS_HTTP_CLIENT_AUTHORITY_FILTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/impl/codegen/compression_types.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+
+/// Filter responsible for setting the authority header, if not already set. It
+/// uses the value of the GRPC_ARG_DEFAULT_AUTHORITY channel arg if the initial
+/// metadata doesn't already contain an authority value.
+
+extern const grpc_channel_filter grpc_client_authority_filter;
+
+#endif /* GRPC_CORE_EXT_FILTERS_HTTP_CLIENT_AUTHORITY_FILTER_H */
diff --git a/src/core/ext/transport/chttp2/client/authority.cc b/src/core/ext/transport/chttp2/client/authority.cc
new file mode 100644
index 0000000..bad3153
--- /dev/null
+++ b/src/core/ext/transport/chttp2/client/authority.cc
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/transport/chttp2/client/authority.h"
+
+grpc_channel_args* grpc_default_authority_add_if_not_present(
+    const grpc_channel_args* args) {
+  const bool has_default_authority =
+      grpc_channel_args_find(args, GRPC_ARG_DEFAULT_AUTHORITY) != nullptr;
+  grpc_arg new_args[1];
+  size_t num_new_args = 0;
+  grpc_core::UniquePtr<char> default_authority;
+  if (!has_default_authority) {
+    const grpc_arg* server_uri_arg =
+        grpc_channel_args_find(args, GRPC_ARG_SERVER_URI);
+    const char* server_uri_str = grpc_channel_arg_get_string(server_uri_arg);
+    GPR_ASSERT(server_uri_str != nullptr);
+    default_authority =
+        grpc_core::ResolverRegistry::GetDefaultAuthority(server_uri_str);
+    GPR_ASSERT(default_authority != nullptr);
+    new_args[num_new_args++] = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), default_authority.get());
+  }
+  return grpc_channel_args_copy_and_add(args, new_args, num_new_args);
+}
diff --git a/src/core/ext/transport/chttp2/client/authority.h b/src/core/ext/transport/chttp2/client/authority.h
new file mode 100644
index 0000000..642584e
--- /dev/null
+++ b/src/core/ext/transport/chttp2/client/authority.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/grpc.h>
+
+#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/client_channel/resolver_registry.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gprpp/memory.h"
+
+/// Returns a copy of \a args with the default authority channel arg set if it
+/// wasn't already present.
+grpc_channel_args* grpc_default_authority_add_if_not_present(
+    const grpc_channel_args* args);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H */
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc
index 6080036..e6c8c38 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc
@@ -27,6 +27,7 @@
 
 #include "src/core/ext/filters/client_channel/client_channel.h"
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
+#include "src/core/ext/transport/chttp2/client/authority.h"
 #include "src/core/ext/transport/chttp2/client/chttp2_connector.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/api_trace.h"
@@ -40,9 +41,13 @@
 
 static grpc_subchannel* client_channel_factory_create_subchannel(
     grpc_client_channel_factory* cc_factory, const grpc_subchannel_args* args) {
+  grpc_subchannel_args final_sc_args;
+  memcpy(&final_sc_args, args, sizeof(*args));
+  final_sc_args.args = grpc_default_authority_add_if_not_present(args->args);
   grpc_connector* connector = grpc_chttp2_connector_create();
-  grpc_subchannel* s = grpc_subchannel_create(connector, args);
+  grpc_subchannel* s = grpc_subchannel_create(connector, &final_sc_args);
   grpc_connector_unref(connector);
+  grpc_channel_args_destroy(const_cast<grpc_channel_args*>(final_sc_args.args));
   return s;
 }
 
@@ -56,8 +61,8 @@
   // Add channel arg containing the server URI.
   grpc_core::UniquePtr<char> canonical_target =
       grpc_core::ResolverRegistry::AddDefaultPrefixIfNeeded(target);
-  grpc_arg arg = grpc_channel_arg_string_create((char*)GRPC_ARG_SERVER_URI,
-                                                canonical_target.get());
+  grpc_arg arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_SERVER_URI), canonical_target.get());
   const char* to_remove[] = {GRPC_ARG_SERVER_URI};
   grpc_channel_args* new_args =
       grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
index a82009f..5ce73a9 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
@@ -71,9 +71,6 @@
   grpc_uri* server_uri =
       grpc_uri_parse(server_uri_str, true /* supress errors */);
   GPR_ASSERT(server_uri != nullptr);
-  const char* server_uri_path;
-  server_uri_path =
-      server_uri->path[0] == '/' ? server_uri->path + 1 : server_uri->path;
   const grpc_core::TargetAuthorityTable* target_authority_table =
       grpc_core::FindTargetAuthorityTableInArgs(args->args);
   grpc_core::UniquePtr<char> authority;
@@ -98,33 +95,49 @@
   // authority table was present or because the target was not present
   // in the table), fall back to using the original server URI.
   if (authority == nullptr) {
-    authority.reset(gpr_strdup(server_uri_path));
+    authority =
+        grpc_core::ResolverRegistry::GetDefaultAuthority(server_uri_str);
   }
+  grpc_arg args_to_add[2];
+  size_t num_args_to_add = 0;
+  if (grpc_channel_args_find(args->args, GRPC_ARG_DEFAULT_AUTHORITY) ==
+      nullptr) {
+    // If the channel args don't already contain GRPC_ARG_DEFAULT_AUTHORITY, add
+    // the arg, setting it to the value just obtained.
+    args_to_add[num_args_to_add++] = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), authority.get());
+  }
+  grpc_channel_args* args_with_authority =
+      grpc_channel_args_copy_and_add(args->args, args_to_add, num_args_to_add);
   grpc_uri_destroy(server_uri);
   grpc_channel_security_connector* subchannel_security_connector = nullptr;
   // Create the security connector using the credentials and target name.
   grpc_channel_args* new_args_from_connector = nullptr;
   const grpc_security_status security_status =
       grpc_channel_credentials_create_security_connector(
-          channel_credentials, authority.get(), args->args,
+          channel_credentials, authority.get(), args_with_authority,
           &subchannel_security_connector, &new_args_from_connector);
   if (security_status != GRPC_SECURITY_OK) {
     gpr_log(GPR_ERROR,
             "Failed to create secure subchannel for secure name '%s'",
             authority.get());
+    grpc_channel_args_destroy(args_with_authority);
     return nullptr;
   }
   grpc_arg new_security_connector_arg =
       grpc_security_connector_to_arg(&subchannel_security_connector->base);
 
   grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
-      new_args_from_connector != nullptr ? new_args_from_connector : args->args,
+      new_args_from_connector != nullptr ? new_args_from_connector
+                                         : args_with_authority,
       &new_security_connector_arg, 1);
+
   GRPC_SECURITY_CONNECTOR_UNREF(&subchannel_security_connector->base,
                                 "lb_channel_create");
   if (new_args_from_connector != nullptr) {
     grpc_channel_args_destroy(new_args_from_connector);
   }
+  grpc_channel_args_destroy(args_with_authority);
   grpc_subchannel_args* final_sc_args =
       static_cast<grpc_subchannel_args*>(gpr_malloc(sizeof(*final_sc_args)));
   memcpy(final_sc_args, args, sizeof(*args));
diff --git a/src/core/lib/iomgr/gevent_util.h b/src/core/lib/iomgr/gevent_util.h
new file mode 100644
index 0000000..de30543
--- /dev/null
+++ b/src/core/lib/iomgr/gevent_util.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_IOMGR_GEVENT_UTIL_H
+#define GRPC_CORE_LIB_IOMGR_GEVENT_UTIL_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/impl/codegen/slice.h>
+#include <grpc/status.h>
+#include "src/core/lib/iomgr/error.h"
+
+// These are only used by the gRPC Python extension for gevent
+// support.  They are easier to define here (rather than in Cython)
+// because Cython doesn't handle #defines well.
+
+grpc_error* grpc_socket_error(char* error) {
+  return grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(error),
+                            GRPC_ERROR_INT_GRPC_STATUS,
+                            GRPC_STATUS_UNAVAILABLE);
+}
+
+char* grpc_slice_buffer_start(grpc_slice_buffer* buffer, int i) {
+  return (char*)GRPC_SLICE_START_PTR(buffer->slices[i]);
+}
+
+int grpc_slice_buffer_length(grpc_slice_buffer* buffer, int i) {
+  return GRPC_SLICE_LENGTH(buffer->slices[i]);
+}
+
+#endif
diff --git a/src/core/lib/iomgr/iomgr_custom.h b/src/core/lib/iomgr/iomgr_custom.h
index ceb6c65..57cc2f9 100644
--- a/src/core/lib/iomgr/iomgr_custom.h
+++ b/src/core/lib/iomgr/iomgr_custom.h
@@ -37,7 +37,7 @@
   GPR_ASSERT(gpr_thd_currentid() == g_init_thread)
 #else
 #define GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD()
-#endif /* GRPC_UV_THREAD_CHECK */
+#endif /* GRPC_CUSTOM_IOMGR_THREAD_CHECK */
 
 void grpc_custom_iomgr_init(grpc_socket_vtable* socket,
                             grpc_custom_resolver_vtable* resolver,
diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h
index b507b94..d6a6c22 100644
--- a/src/core/lib/iomgr/lockfree_event.h
+++ b/src/core/lib/iomgr/lockfree_event.h
@@ -42,12 +42,23 @@
   void InitEvent();
   void DestroyEvent();
 
+  // Returns true if fd has been shutdown, false otherwise.
   bool IsShutdown() const {
     return (gpr_atm_no_barrier_load(&state_) & kShutdownBit) != 0;
   }
 
+  // Schedules \a closure when the event is received (see SetReady()) or the
+  // shutdown state has been set. Note that the event may have already been
+  // received, in which case the closure would be scheduled immediately.
+  // If the shutdown state has already been set, then \a closure is scheduled
+  // with the shutdown error.
   void NotifyOn(grpc_closure* closure);
+
+  // Sets the shutdown state. If a closure had been provided by NotifyOn and has
+  // not yet been scheduled, it will be scheduled with \a error.
   bool SetShutdown(grpc_error* error);
+
+  // Signals that the event has been received.
   void SetReady();
 
  private:
diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h
index c1dcc52..a397012 100644
--- a/src/core/lib/iomgr/port.h
+++ b/src/core/lib/iomgr/port.h
@@ -22,8 +22,10 @@
 #define GRPC_CORE_LIB_IOMGR_PORT_H
 
 #ifdef GRPC_UV
+#ifndef GRPC_CUSTOM_SOCKET
 #define GRPC_CUSTOM_SOCKET
 #endif
+#endif
 #if defined(GRPC_CUSTOM_SOCKET)
 // Do Nothing
 #elif defined(GPR_MANYLINUX1)
diff --git a/src/core/lib/iomgr/sockaddr_utils.cc b/src/core/lib/iomgr/sockaddr_utils.cc
index df25f77..1b66dce 100644
--- a/src/core/lib/iomgr/sockaddr_utils.cc
+++ b/src/core/lib/iomgr/sockaddr_utils.cc
@@ -204,6 +204,8 @@
 
   if (grpc_inet_pton(GRPC_AF_INET6, addr, &addr6->sin6_addr) == 1) {
     addr6->sin6_family = GRPC_AF_INET6;
+    addr6->sin6_flowinfo = 0;
+    addr6->sin6_scope_id = 0;
     out->len = sizeof(grpc_sockaddr_in6);
   } else if (grpc_inet_pton(GRPC_AF_INET, addr, &addr4->sin_addr) == 1) {
     addr4->sin_family = GRPC_AF_INET;
diff --git a/src/core/lib/iomgr/socket_utils_linux.cc b/src/core/lib/iomgr/socket_utils_linux.cc
index f506329..b0207578 100644
--- a/src/core/lib/iomgr/socket_utils_linux.cc
+++ b/src/core/lib/iomgr/socket_utils_linux.cc
@@ -34,7 +34,6 @@
                  int cloexec) {
   int flags = 0;
   GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t));
-  GPR_ASSERT(resolved_addr->len <= (socklen_t)-1);
   flags |= nonblock ? SOCK_NONBLOCK : 0;
   flags |= cloexec ? SOCK_CLOEXEC : 0;
   return accept4(sockfd, reinterpret_cast<grpc_sockaddr*>(resolved_addr->addr),
diff --git a/src/core/lib/iomgr/socket_utils_posix.cc b/src/core/lib/iomgr/socket_utils_posix.cc
index d5d00af..2a49583 100644
--- a/src/core/lib/iomgr/socket_utils_posix.cc
+++ b/src/core/lib/iomgr/socket_utils_posix.cc
@@ -35,7 +35,6 @@
                  int cloexec) {
   int fd, flags;
   GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t));
-  GPR_ASSERT(resolved_addr->len <= (socklen_t)-1);
   fd = accept(sockfd, (grpc_sockaddr*)resolved_addr->addr,
               (socklen_t*)&resolved_addr->len);
   if (fd >= 0) {
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
index 0734453..9f4e58c 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
+++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
@@ -170,7 +170,6 @@
   err = grpc_set_socket_no_sigpipe_if_possible(fd);
   if (err != GRPC_ERROR_NONE) goto error;
 
-  GPR_ASSERT(addr->len < ~(socklen_t)0);
   if (bind(fd, reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr)),
            addr->len) < 0) {
     err = GRPC_OS_ERROR(errno, "bind");
diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc
index 04716a2..9990dee 100644
--- a/src/core/lib/iomgr/udp_server.cc
+++ b/src/core/lib/iomgr/udp_server.cc
@@ -381,7 +381,6 @@
     }
   }
 
-  GPR_ASSERT(addr->len < ~(socklen_t)0);
   if (bind_socket(socket_factory, fd, addr) < 0) {
     char* addr_str;
     grpc_sockaddr_to_string(&addr_str, addr, 0);
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index 3967112..3551061 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -306,6 +306,7 @@
   char* target;
   char* expected_targets;
   bool is_lb_channel;
+  char* target_name_override;
 } grpc_fake_channel_security_connector;
 
 static void fake_channel_destroy(grpc_security_connector* sc) {
@@ -314,6 +315,7 @@
   grpc_call_credentials_unref(c->base.request_metadata_creds);
   gpr_free(c->target);
   gpr_free(c->expected_targets);
+  gpr_free(c->target_name_override);
   gpr_free(c);
 }
 
@@ -465,13 +467,36 @@
                                          grpc_error** error) {
   grpc_fake_channel_security_connector* c =
       reinterpret_cast<grpc_fake_channel_security_connector*>(sc);
-  if (c->is_lb_channel) {
-    // TODO(dgq): verify that the host (ie, authority header) matches that of
-    // the LB, as opposed to that of the backends.
-  } else {
-    // TODO(dgq): verify that the host (ie, authority header) matches that of
-    // the backend, not the LB's.
+  char* authority_hostname = nullptr;
+  char* authority_ignored_port = nullptr;
+  char* target_hostname = nullptr;
+  char* target_ignored_port = nullptr;
+  gpr_split_host_port(host, &authority_hostname, &authority_ignored_port);
+  gpr_split_host_port(c->target, &target_hostname, &target_ignored_port);
+  if (c->target_name_override != nullptr) {
+    char* fake_security_target_name_override_hostname = nullptr;
+    char* fake_security_target_name_override_ignored_port = nullptr;
+    gpr_split_host_port(c->target_name_override,
+                        &fake_security_target_name_override_hostname,
+                        &fake_security_target_name_override_ignored_port);
+    if (strcmp(authority_hostname,
+               fake_security_target_name_override_hostname) != 0) {
+      gpr_log(GPR_ERROR,
+              "Authority (host) '%s' != Fake Security Target override '%s'",
+              host, fake_security_target_name_override_hostname);
+      abort();
+    }
+    gpr_free(fake_security_target_name_override_hostname);
+    gpr_free(fake_security_target_name_override_ignored_port);
+  } else if (strcmp(authority_hostname, target_hostname) != 0) {
+    gpr_log(GPR_ERROR, "Authority (host) '%s' != Target '%s'",
+            authority_hostname, target_hostname);
+    abort();
   }
+  gpr_free(authority_hostname);
+  gpr_free(authority_ignored_port);
+  gpr_free(target_hostname);
+  gpr_free(target_ignored_port);
   return true;
 }
 
@@ -524,6 +549,12 @@
   const char* expected_targets = grpc_fake_transport_get_expected_targets(args);
   c->expected_targets = gpr_strdup(expected_targets);
   c->is_lb_channel = grpc_core::FindTargetAuthorityTableInArgs(args) != nullptr;
+  const grpc_arg* target_name_override_arg =
+      grpc_channel_args_find(args, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
+  if (target_name_override_arg != nullptr) {
+    c->target_name_override =
+        gpr_strdup(grpc_channel_arg_get_string(target_name_override_arg));
+  }
   return &c->base;
 }
 
@@ -1120,16 +1151,6 @@
                    GRPC_SLICE_START_PTR(default_pem_root_certs_);
 }
 
-void DefaultSslRootStore::Initialize() {
-  default_root_store_ = nullptr;
-  default_pem_root_certs_ = grpc_empty_slice();
-}
-
-void DefaultSslRootStore::Destroy() {
-  tsi_ssl_root_certs_store_destroy(default_root_store_);
-  grpc_slice_unref_internal(default_pem_root_certs_);
-}
-
 grpc_slice DefaultSslRootStore::ComputePemRootCerts() {
   grpc_slice result = grpc_empty_slice();
   // First try to load the roots from the environment.
diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h
index 5d3d1e0..c4cc19d 100644
--- a/src/core/lib/security/security_connector/security_connector.h
+++ b/src/core/lib/security/security_connector/security_connector.h
@@ -256,15 +256,6 @@
   // Gets the default PEM root certificate.
   static const char* GetPemRootCerts();
 
-  // Initializes the SSL root store's underlying data structure. It does not
-  // load default SSL root certificates. Should only be called by
-  // grpc_security_init().
-  static void Initialize();
-
-  // Destroys the default SSL root store. Should only be called by
-  // grpc_security_shutdown().
-  static void Destroy();
-
  protected:
   // Returns default PEM root certificates in nullptr terminated grpc_slice.
   // This function is protected instead of private, so that it can be tested.
diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc
index cecc15b..d740ebd 100644
--- a/src/core/lib/surface/channel.cc
+++ b/src/core/lib/surface/channel.cc
@@ -60,7 +60,6 @@
 struct grpc_channel {
   int is_client;
   grpc_compression_options compression_options;
-  grpc_mdelem default_authority;
 
   gpr_atm call_size_estimate;
 
@@ -117,40 +116,8 @@
 
   grpc_compression_options_init(&channel->compression_options);
   for (size_t i = 0; i < args->num_args; i++) {
-    if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
-      if (args->args[i].type != GRPC_ARG_STRING) {
-        gpr_log(GPR_ERROR, "%s ignored: it must be a string",
-                GRPC_ARG_DEFAULT_AUTHORITY);
-      } else {
-        if (!GRPC_MDISNULL(channel->default_authority)) {
-          /* setting this takes precedence over anything else */
-          GRPC_MDELEM_UNREF(channel->default_authority);
-        }
-        channel->default_authority = grpc_mdelem_from_slices(
-            GRPC_MDSTR_AUTHORITY,
-            grpc_slice_intern(
-                grpc_slice_from_static_string(args->args[i].value.string)));
-      }
-    } else if (0 ==
-               strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
-      if (args->args[i].type != GRPC_ARG_STRING) {
-        gpr_log(GPR_ERROR, "%s ignored: it must be a string",
-                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-      } else {
-        if (!GRPC_MDISNULL(channel->default_authority)) {
-          /* other ways of setting this (notably ssl) take precedence */
-          gpr_log(GPR_ERROR,
-                  "%s ignored: default host already set some other way",
-                  GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-        } else {
-          channel->default_authority = grpc_mdelem_from_slices(
-              GRPC_MDSTR_AUTHORITY,
-              grpc_slice_intern(
-                  grpc_slice_from_static_string(args->args[i].value.string)));
-        }
-      }
-    } else if (0 == strcmp(args->args[i].key,
-                           GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) {
+    if (0 ==
+        strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) {
       channel->compression_options.default_level.is_set = true;
       channel->compression_options.default_level.level =
           static_cast<grpc_compression_level>(grpc_channel_arg_get_integer(
@@ -189,6 +156,37 @@
   return channel;
 }
 
+static grpc_core::UniquePtr<char> get_default_authority(
+    const grpc_channel_args* input_args) {
+  bool has_default_authority = false;
+  char* ssl_override = nullptr;
+  grpc_core::UniquePtr<char> default_authority;
+  const size_t num_args = input_args != nullptr ? input_args->num_args : 0;
+  for (size_t i = 0; i < num_args; ++i) {
+    if (0 == strcmp(input_args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
+      has_default_authority = true;
+    } else if (0 == strcmp(input_args->args[i].key,
+                           GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
+      ssl_override = grpc_channel_arg_get_string(&input_args->args[i]);
+    }
+  }
+  if (!has_default_authority && ssl_override != nullptr) {
+    default_authority.reset(gpr_strdup(ssl_override));
+  }
+  return default_authority;
+}
+
+static grpc_channel_args* build_channel_args(
+    const grpc_channel_args* input_args, char* default_authority) {
+  grpc_arg new_args[1];
+  size_t num_new_args = 0;
+  if (default_authority != nullptr) {
+    new_args[num_new_args++] = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), default_authority);
+  }
+  return grpc_channel_args_copy_and_add(input_args, new_args, num_new_args);
+}
+
 char* grpc_channel_get_trace(grpc_channel* channel) {
   return channel->tracer->RenderTrace();
 }
@@ -202,7 +200,12 @@
                                   grpc_channel_stack_type channel_stack_type,
                                   grpc_transport* optional_transport) {
   grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
-  grpc_channel_stack_builder_set_channel_arguments(builder, input_args);
+  const grpc_core::UniquePtr<char> default_authority =
+      get_default_authority(input_args);
+  grpc_channel_args* args =
+      build_channel_args(input_args, default_authority.get());
+  grpc_channel_stack_builder_set_channel_arguments(builder, args);
+  grpc_channel_args_destroy(args);
   grpc_channel_stack_builder_set_target(builder, target);
   grpc_channel_stack_builder_set_transport(builder, optional_transport);
   if (!grpc_channel_init_create_stack(builder, channel_stack_type)) {
@@ -274,8 +277,6 @@
   send_metadata[num_metadata++] = path_mdelem;
   if (!GRPC_MDISNULL(authority_mdelem)) {
     send_metadata[num_metadata++] = authority_mdelem;
-  } else if (!GRPC_MDISNULL(channel->default_authority)) {
-    send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority);
   }
 
   grpc_call_create_args args;
@@ -406,7 +407,6 @@
     gpr_free(rc);
   }
   channel->tracer.reset();
-  GRPC_MDELEM_UNREF(channel->default_authority);
   gpr_mu_destroy(&channel->registered_call_mu);
   gpr_free(channel->target);
   gpr_free(channel);
diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc
index 52e0ee1..bd436d6 100644
--- a/src/core/lib/surface/init.cc
+++ b/src/core/lib/surface/init.cc
@@ -172,7 +172,6 @@
           }
         }
       }
-      grpc_security_shutdown();
       grpc_iomgr_shutdown();
       gpr_timers_global_destroy();
       grpc_tracer_shutdown();
diff --git a/src/core/lib/surface/init.h b/src/core/lib/surface/init.h
index d8282b4..9353208 100644
--- a/src/core/lib/surface/init.h
+++ b/src/core/lib/surface/init.h
@@ -22,7 +22,6 @@
 void grpc_register_security_filters(void);
 void grpc_security_pre_init(void);
 void grpc_security_init(void);
-void grpc_security_shutdown(void);
 int grpc_is_initialized(void);
 
 #endif /* GRPC_CORE_LIB_SURFACE_INIT_H */
diff --git a/src/core/lib/surface/init_secure.cc b/src/core/lib/surface/init_secure.cc
index 3e4f1a8..28c6f7b 100644
--- a/src/core/lib/surface/init_secure.cc
+++ b/src/core/lib/surface/init_secure.cc
@@ -67,17 +67,15 @@
 }
 
 void grpc_register_security_filters(void) {
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
+  // Register the auth client with a priority < INT_MAX to allow the authority
+  // filter -on which the auth filter depends- to be higher on the channel
+  // stack.
+  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX - 1,
                                    maybe_prepend_client_auth_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
+  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX - 1,
                                    maybe_prepend_client_auth_filter, nullptr);
   grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
                                    maybe_prepend_server_auth_filter, nullptr);
 }
 
-void grpc_security_init() {
-  grpc_security_register_handshaker_factories();
-  grpc_core::DefaultSslRootStore::Initialize();
-}
-
-void grpc_security_shutdown() { grpc_core::DefaultSslRootStore::Destroy(); }
+void grpc_security_init() { grpc_security_register_handshaker_factories(); }
diff --git a/src/core/lib/surface/init_unsecure.cc b/src/core/lib/surface/init_unsecure.cc
index 1c8d07b..2b3bc64 100644
--- a/src/core/lib/surface/init_unsecure.cc
+++ b/src/core/lib/surface/init_unsecure.cc
@@ -25,5 +25,3 @@
 void grpc_register_security_filters(void) {}
 
 void grpc_security_init(void) {}
-
-void grpc_security_shutdown(void) {}
diff --git a/src/core/plugin_registry/grpc_cronet_plugin_registry.cc b/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
index 84228cb..49b9c7d 100644
--- a/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
+++ b/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
@@ -20,50 +20,30 @@
 
 #include <grpc/grpc.h>
 
-void grpc_deadline_filter_init(void);
-void grpc_deadline_filter_shutdown(void);
-void grpc_client_channel_init(void);
-void grpc_client_channel_shutdown(void);
-void grpc_lb_policy_pick_first_init(void);
-void grpc_lb_policy_pick_first_shutdown(void);
-void grpc_max_age_filter_init(void);
-void grpc_max_age_filter_shutdown(void);
-void grpc_message_size_filter_init(void);
-void grpc_message_size_filter_shutdown(void);
-void grpc_resolver_dns_native_init(void);
-void grpc_resolver_dns_native_shutdown(void);
-void grpc_resolver_sockaddr_init(void);
-void grpc_resolver_sockaddr_shutdown(void);
-void grpc_server_load_reporting_plugin_init(void);
-void grpc_server_load_reporting_plugin_shutdown(void);
 void grpc_http_filters_init(void);
 void grpc_http_filters_shutdown(void);
 void grpc_chttp2_plugin_init(void);
 void grpc_chttp2_plugin_shutdown(void);
+void grpc_deadline_filter_init(void);
+void grpc_deadline_filter_shutdown(void);
+void grpc_client_channel_init(void);
+void grpc_client_channel_shutdown(void);
 void grpc_tsi_alts_init(void);
 void grpc_tsi_alts_shutdown(void);
+void grpc_server_load_reporting_plugin_init(void);
+void grpc_server_load_reporting_plugin_shutdown(void);
 
 void grpc_register_built_in_plugins(void) {
-  grpc_register_plugin(grpc_deadline_filter_init,
-                       grpc_deadline_filter_shutdown);
-  grpc_register_plugin(grpc_client_channel_init,
-                       grpc_client_channel_shutdown);
-  grpc_register_plugin(grpc_lb_policy_pick_first_init,
-                       grpc_lb_policy_pick_first_shutdown);
-  grpc_register_plugin(grpc_max_age_filter_init,
-                       grpc_max_age_filter_shutdown);
-  grpc_register_plugin(grpc_message_size_filter_init,
-                       grpc_message_size_filter_shutdown);
-  grpc_register_plugin(grpc_resolver_dns_native_init,
-                       grpc_resolver_dns_native_shutdown);
-  grpc_register_plugin(grpc_resolver_sockaddr_init,
-                       grpc_resolver_sockaddr_shutdown);
-  grpc_register_plugin(grpc_server_load_reporting_plugin_init,
-                       grpc_server_load_reporting_plugin_shutdown);
   grpc_register_plugin(grpc_http_filters_init,
                        grpc_http_filters_shutdown);
   grpc_register_plugin(grpc_chttp2_plugin_init,
                        grpc_chttp2_plugin_shutdown);
+  grpc_register_plugin(grpc_deadline_filter_init,
+                       grpc_deadline_filter_shutdown);
+  grpc_register_plugin(grpc_client_channel_init,
+                       grpc_client_channel_shutdown);
   grpc_register_plugin(grpc_tsi_alts_init,
                        grpc_tsi_alts_shutdown);
+  grpc_register_plugin(grpc_server_load_reporting_plugin_init,
+                       grpc_server_load_reporting_plugin_shutdown);
 }
diff --git a/src/core/plugin_registry/grpc_plugin_registry.cc b/src/core/plugin_registry/grpc_plugin_registry.cc
index 6f11e6b..e371310 100644
--- a/src/core/plugin_registry/grpc_plugin_registry.cc
+++ b/src/core/plugin_registry/grpc_plugin_registry.cc
@@ -52,6 +52,8 @@
 void grpc_max_age_filter_shutdown(void);
 void grpc_message_size_filter_init(void);
 void grpc_message_size_filter_shutdown(void);
+void grpc_client_authority_filter_init(void);
+void grpc_client_authority_filter_shutdown(void);
 void grpc_workaround_cronet_compression_filter_init(void);
 void grpc_workaround_cronet_compression_filter_shutdown(void);
 
@@ -88,6 +90,8 @@
                        grpc_max_age_filter_shutdown);
   grpc_register_plugin(grpc_message_size_filter_init,
                        grpc_message_size_filter_shutdown);
+  grpc_register_plugin(grpc_client_authority_filter_init,
+                       grpc_client_authority_filter_shutdown);
   grpc_register_plugin(grpc_workaround_cronet_compression_filter_init,
                        grpc_workaround_cronet_compression_filter_shutdown);
 }
diff --git a/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc b/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
index b08c5ce..283db5b 100644
--- a/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
+++ b/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
@@ -50,6 +50,8 @@
 void grpc_max_age_filter_shutdown(void);
 void grpc_message_size_filter_init(void);
 void grpc_message_size_filter_shutdown(void);
+void grpc_client_authority_filter_init(void);
+void grpc_client_authority_filter_shutdown(void);
 void grpc_workaround_cronet_compression_filter_init(void);
 void grpc_workaround_cronet_compression_filter_shutdown(void);
 
@@ -84,6 +86,8 @@
                        grpc_max_age_filter_shutdown);
   grpc_register_plugin(grpc_message_size_filter_init,
                        grpc_message_size_filter_shutdown);
+  grpc_register_plugin(grpc_client_authority_filter_init,
+                       grpc_client_authority_filter_shutdown);
   grpc_register_plugin(grpc_workaround_cronet_compression_filter_init,
                        grpc_workaround_cronet_compression_filter_shutdown);
 }
diff --git a/src/csharp/.editorconfig b/src/csharp/.editorconfig
index 7bc2bcc..fabce7f 100644
--- a/src/csharp/.editorconfig
+++ b/src/csharp/.editorconfig
@@ -1,5 +1,6 @@
 root = true
 [**]
+charset = utf-8  ; Implies no BOM.
 end_of_line = LF
 indent_style = space
 indent_size = 4
diff --git a/src/csharp/.gitignore b/src/csharp/.gitignore
index fc2875a..6fd7648 100644
--- a/src/csharp/.gitignore
+++ b/src/csharp/.gitignore
@@ -1,15 +1,17 @@
-*.xproj.user
 *.userprefs
-*.csproj.user
+*.user
 *.lock.json
+/*.suo
+/*.sdf
+/.vs/
+bin/
+obj/
+*.nupkg
 StyleCop.Cache
-test-results
-packages
-Grpc.v12.suo
-Grpc.sdf
+/packages/
+/protoc_plugins/
 
+test-results/
 TestResult.xml
 coverage_results.xml
 /TestResults
-.vs/
-*.nupkg
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
index 18d4597..b6d3938 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
@@ -46,4 +46,13 @@
 + (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm
                          forhost:(nonnull NSString *)host;
 
+/** Enable keepalive and configure keepalive parameters. A user should call this function once to
+ * enable keepalive for a particular host. gRPC client sends a ping after every \a interval ms to
+ * check if the transport is still alive. After waiting for \a timeout ms, if the client does not
+ * receive the ping ack, it closes the transport; all pending calls to this host will fail with
+ * error GRPC_STATUS_INTERNAL with error information "keepalive watchdog timeout". */
++ (void)setKeepaliveWithInterval:(int)interval
+                         timeout:(int)timeout
+                         forHost:(nonnull NSString *)host;
+
 @end
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
index 805e54b..217d0e9 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
@@ -57,4 +57,12 @@
   }
 }
 
++ (void)setKeepaliveWithInterval:(int)interval
+                         timeout:(int)timeout
+                         forHost:(nonnull NSString *)host {
+  GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
+  hostConfig.keepaliveInterval = interval;
+  hostConfig.keepaliveTimeout = timeout;
+}
+
 @end
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index ea658bc..cf70064 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -196,9 +196,6 @@
     _state = GRXWriterStateFinished;
   }
 
-  // If the call isn't retained anywhere else, it can be deallocated now.
-  _retainSelf = nil;
-
   // If there were still request messages coming, stop them.
   @synchronized(_requestWriter) {
     _requestWriter.state = GRXWriterStateFinished;
@@ -211,6 +208,9 @@
   }
 
   [GRPCConnectivityMonitor unregisterObserver:self];
+
+  // If the call isn't retained anywhere else, it can be deallocated now.
+  _retainSelf = nil;
 }
 
 - (void)cancelCall {
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h
index 0215db8..a1d2e5f 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.h
+++ b/src/objective-c/GRPCClient/private/GRPCHost.h
@@ -35,6 +35,8 @@
 @property(nonatomic, copy, nullable) NSString *userAgentPrefix;
 @property(nonatomic, nullable) struct grpc_channel_credentials *channelCreds;
 @property(nonatomic) grpc_compression_algorithm compressAlgorithm;
+@property(nonatomic) int keepaliveInterval;
+@property(nonatomic) int keepaliveTimeout;
 
 /** The following properties should only be modified for testing: */
 
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index 8568e33..152c3d3 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -192,7 +192,7 @@
   return YES;
 }
 
-- (NSDictionary *)channelArgs {
+- (NSDictionary *)channelArgsUsingCronet:(BOOL)useCronet {
   NSMutableDictionary *args = [NSMutableDictionary dictionary];
 
   // TODO(jcanizales): Add OS and device information (see
@@ -216,19 +216,29 @@
         [NSNumber numberWithInt:_compressAlgorithm];
   }
 
+  if (_keepaliveInterval != 0) {
+    args[@GRPC_ARG_KEEPALIVE_TIME_MS] = [NSNumber numberWithInt:_keepaliveInterval];
+    args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = [NSNumber numberWithInt:_keepaliveTimeout];
+  }
+
   id logConfig = [GRPCCall logConfig];
   if (logConfig != nil) {
     args[@GRPC_ARG_MOBILE_LOG_CONFIG] = logConfig;
   }
 
+  if (useCronet) {
+    args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1];
+  }
+
   return args;
 }
 
 - (GRPCChannel *)newChannel {
-  NSDictionary *args = [self channelArgs];
+  BOOL useCronet = NO;
 #ifdef GRPC_COMPILE_WITH_CRONET
-  BOOL useCronet = [GRPCCall isUsingCronet];
+  useCronet = [GRPCCall isUsingCronet];
 #endif
+  NSDictionary *args = [self channelArgsUsingCronet:useCronet];
   if (_secure) {
     GRPCChannel *channel;
     @synchronized(self) {
diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
index 33ccdb5..5d384d8 100644
--- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
+++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
@@ -82,8 +82,14 @@
                                                 grpc_channel_args *client_args,
                                                 stream_engine *cronetEngine) {
   fullstack_secure_fixture_data *ffd = (fullstack_secure_fixture_data *)f->fixture_data;
+  grpc_arg arg;
+  arg.key = const_cast<char*>(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER);
+  arg.type = GRPC_ARG_INTEGER;
+  arg.value.integer = 1;
+  client_args = grpc_channel_args_copy_and_add(client_args, &arg, 1);
   f->client = grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr,
                                                 client_args, NULL);
+  grpc_channel_args_destroy(client_args);
   GPR_ASSERT(f->client != NULL);
 }
 
@@ -147,12 +153,9 @@
 
 static grpc_end2end_test_config configs[] = {
     {"chttp2/simple_ssl_fullstack",
-     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-         FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
-     chttp2_create_fixture_secure_fullstack,
-     cronet_init_client_simple_ssl_secure_fullstack,
-     chttp2_init_server_simple_ssl_secure_fullstack,
-     chttp2_tear_down_secure_fullstack},
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, nullptr,
+     chttp2_create_fixture_secure_fullstack, cronet_init_client_simple_ssl_secure_fullstack,
+     chttp2_init_server_simple_ssl_secure_fullstack, chttp2_tear_down_secure_fullstack},
 };
 
 static char *roots_filename;
diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
index 28414b8..3da7d53 100644
--- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
+++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
@@ -126,6 +126,14 @@
          ((unsigned int)(unsigned char)(field[2]));
 }
 
+grpc_channel_args *add_disable_client_authority_filter_args(grpc_channel_args *args) {
+  grpc_arg arg;
+  arg.key = const_cast<char*>(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER);
+  arg.type = GRPC_ARG_INTEGER;
+  arg.value.integer = 1;
+  return grpc_channel_args_copy_and_add(args, &arg, 1);
+}
+
 - (void)testInternalError {
   grpc_call *c;
   grpc_slice request_payload_slice =
@@ -147,8 +155,10 @@
   gpr_join_host_port(&addr, "127.0.0.1", port);
   grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   stream_engine *cronetEngine = [Cronet getGlobalEngine];
+  grpc_channel_args *client_args = add_disable_client_authority_filter_args(NULL);
   grpc_channel *client =
-      grpc_cronet_secure_channel_create(cronetEngine, addr, NULL, NULL);
+      grpc_cronet_secure_channel_create(cronetEngine, addr, client_args, NULL);
+  grpc_channel_args_destroy(client_args);
 
   cq_verifier *cqv = cq_verifier_create(cq);
   grpc_op ops[6];
@@ -262,6 +272,8 @@
   arg.type = GRPC_ARG_INTEGER;
   arg.value.integer = useCoalescing ? 1 : 0;
   grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
+  args = add_disable_client_authority_filter_args(args);
+
   grpc_call *c;
   grpc_slice request_payload_slice =
       grpc_slice_from_copied_string("hello world");
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index dfa874a..bfc4755 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -486,4 +486,46 @@
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 
+#ifndef GRPC_COMPILE_WITH_CRONET
+- (void)testKeepalive {
+  XCTAssertNotNil(self.class.host);
+  __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Keepalive"];
+
+  [GRPCCall setKeepaliveWithInterval:1500 timeout:0 forHost:self.class.host];
+
+  NSArray *requests = @[@27182, @8];
+  NSArray *responses = @[@31415, @9];
+
+  GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
+
+  __block int index = 0;
+
+  id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
+                                               requestedResponseSize:responses[index]];
+  [requestsBuffer writeValue:request];
+
+  [_service fullDuplexCallWithRequestsWriter:requestsBuffer
+                                eventHandler:^(BOOL done,
+                                               RMTStreamingOutputCallResponse *response,
+                                               NSError *error) {
+    if (index == 0) {
+      XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+      XCTAssertTrue(response, @"Event handler called without an event.");
+      XCTAssertFalse(done);
+      index++;
+    } else {
+      // Keepalive should kick after 1s elapsed and fails the call.
+      XCTAssertNotNil(error);
+      XCTAssertEqual(error.code, GRPC_STATUS_INTERNAL);
+      XCTAssertEqualObjects(error.localizedDescription, @"keepalive watchdog timeout",
+                            @"Unexpected failure that is not keepalive watchdog timeout.");
+      XCTAssertTrue(done);
+      [expectation fulfill];
+    }
+  }];
+
+  [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
+}
+#endif
+
 @end
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index 6e17d9a..af1a34a 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -43,8 +43,10 @@
   target target_name do
     pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
     pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
+    pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
+    pod 'gRPC-Core/Cronet-Interface', :path => GRPC_LOCAL_SRC
     pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC
-    pod 'gRPC-Core/Cronet-Tests', :path => GRPC_LOCAL_SRC
+    pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC
   end
 end
 
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index 4054723..ed30888 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -57,9 +57,8 @@
 
 /* Frees and destroys an instance of wrapped_grpc_channel */
 PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel)
-  bool is_last_wrapper = false;
-  // In_persistent_list is used when the user don't close the channel.
-  // In this case, le in the list won't be freed.
+  // In_persistent_list is used when the user don't close the channel,
+  // In this case, channels not in the list should be freed.
   bool in_persistent_list = true;
   if (p->wrapper != NULL) {
     gpr_mu_lock(&p->wrapper->mu);
@@ -79,41 +78,18 @@
             free(p->wrapper->creds_hashstr);
             p->wrapper->creds_hashstr = NULL;
           }
+          free(p->wrapper->key);
         }
         gpr_mu_unlock(&global_persistent_list_mu);
       }
     }
     p->wrapper->ref_count -= 1;
-    if (p->wrapper->ref_count == 0) {
-      is_last_wrapper = true;
-    }
     gpr_mu_unlock(&p->wrapper->mu);
-    if (is_last_wrapper) {
-      if (in_persistent_list) {
-        // If ref_count==0 and the key still in the list, it means the user
-        // don't call channel->close().persistent list should free the
-        // allocation in such case, as well as related wrapped channel.
-        if (p->wrapper->wrapped != NULL) {
-          gpr_mu_lock(&p->wrapper->mu);
-          grpc_channel_destroy(p->wrapper->wrapped);
-          free(p->wrapper->target);
-          free(p->wrapper->args_hashstr);
-          if(p->wrapper->creds_hashstr != NULL){
-            free(p->wrapper->creds_hashstr);
-            p->wrapper->creds_hashstr = NULL;
-          }
-          p->wrapper->wrapped = NULL;
-          php_grpc_delete_persistent_list_entry(p->wrapper->key,
-                                                strlen(p->wrapper->key)
-                                                TSRMLS_CC);
-          gpr_mu_unlock(&p->wrapper->mu);
-        }
-      }
+    if (!in_persistent_list) {
       gpr_mu_destroy(&p->wrapper->mu);
-      free(p->wrapper->key);
       free(p->wrapper);
+      p->wrapper = NULL;
     }
-    p->wrapper = NULL;
   }
 PHP_GRPC_FREE_WRAPPED_FUNC_END()
 
@@ -330,7 +306,6 @@
 
   gpr_mu_init(&channel->wrapper->mu);
   smart_str_free(&buf);
-
   if (force_new || (creds != NULL && creds->has_call_creds)) {
     // If the ChannelCredentials object was composed with a CallCredentials
     // object, there is no way we can tell them apart. Do NOT persist
@@ -540,8 +515,18 @@
       grpc_channel_destroy(le->channel->wrapped);
       free(le->channel->target);
       free(le->channel->args_hashstr);
+      le->channel->wrapped = NULL;
+      le->channel->target = NULL;
+      le->channel->args_hashstr = NULL;
     }
+    free(le->channel->key);
+    le->channel->key = NULL;
     gpr_mu_unlock(&le->channel->mu);
+    gpr_mu_destroy(&le->channel->mu);
+    free(le->channel);
+    le->channel = NULL;
+    free(le);
+    le = NULL;
   }
 }
 
diff --git a/src/python/grpcio/grpc/_cython/.gitignore b/src/python/grpcio/grpc/_cython/.gitignore
index 306e3ad..b9936e9 100644
--- a/src/python/grpcio/grpc/_cython/.gitignore
+++ b/src/python/grpcio/grpc/_cython/.gitignore
@@ -1,4 +1,4 @@
-cygrpc.c
+cygrpc.cpp
 *.a
 *.so
 *.dll
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd
new file mode 100644
index 0000000..f35aeba
--- /dev/null
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd
@@ -0,0 +1,154 @@
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# distutils: language=c++
+
+from libc.stdint cimport uint32_t
+
+cdef extern from "grpc/impl/codegen/slice.h":
+  struct grpc_slice_buffer:
+    int count
+
+cdef extern from "src/core/lib/iomgr/error.h":
+  struct grpc_error:
+    pass
+
+cdef extern from "src/core/lib/iomgr/gevent_util.h":
+  grpc_error* grpc_socket_error(char* error) 
+  char* grpc_slice_buffer_start(grpc_slice_buffer* buffer, int i)
+  int grpc_slice_buffer_length(grpc_slice_buffer* buffer, int i)
+
+cdef extern from "src/core/lib/iomgr/sockaddr.h":
+  ctypedef struct grpc_sockaddr:
+    pass
+
+cdef extern from "src/core/lib/iomgr/resolve_address.h":
+  ctypedef struct grpc_resolved_addresses:
+    size_t naddrs
+    grpc_resolved_address* addrs
+
+  ctypedef struct grpc_resolved_address:
+    char[128] addr
+    size_t len
+
+cdef extern from "src/core/lib/iomgr/resolve_address_custom.h":
+  struct grpc_custom_resolver:
+    pass
+
+  struct grpc_custom_resolver_vtable:
+    grpc_error* (*resolve)(char* host, char* port, grpc_resolved_addresses** res);
+    void (*resolve_async)(grpc_custom_resolver* resolver, char* host, char* port);
+
+  void grpc_custom_resolve_callback(grpc_custom_resolver* resolver,
+                                    grpc_resolved_addresses* result,
+                                    grpc_error* error);
+
+cdef extern from "src/core/lib/iomgr/tcp_custom.h":
+  struct grpc_custom_socket:
+    void* impl
+    # We don't care about the rest of the fields
+  ctypedef void (*grpc_custom_connect_callback)(grpc_custom_socket* socket,
+                                             grpc_error* error)
+  ctypedef void (*grpc_custom_write_callback)(grpc_custom_socket* socket,
+                                           grpc_error* error)
+  ctypedef void (*grpc_custom_read_callback)(grpc_custom_socket* socket,
+                                          size_t nread, grpc_error* error)
+  ctypedef void (*grpc_custom_accept_callback)(grpc_custom_socket* socket,
+                                            grpc_custom_socket* client,
+                                            grpc_error* error)
+  ctypedef void (*grpc_custom_close_callback)(grpc_custom_socket* socket)
+
+  struct grpc_socket_vtable:
+      grpc_error* (*init)(grpc_custom_socket* socket, int domain);
+      void (*connect)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
+                      size_t len, grpc_custom_connect_callback cb);
+      void (*destroy)(grpc_custom_socket* socket);
+      void (*shutdown)(grpc_custom_socket* socket);
+      void (*close)(grpc_custom_socket* socket, grpc_custom_close_callback cb);
+      void (*write)(grpc_custom_socket* socket, grpc_slice_buffer* slices,
+                    grpc_custom_write_callback cb);
+      void (*read)(grpc_custom_socket* socket, char* buffer, size_t length,
+                   grpc_custom_read_callback cb);
+      grpc_error* (*getpeername)(grpc_custom_socket* socket,
+                                 const grpc_sockaddr* addr, int* len);
+      grpc_error* (*getsockname)(grpc_custom_socket* socket,
+                             const grpc_sockaddr* addr, int* len);
+      grpc_error* (*setsockopt)(grpc_custom_socket* socket, int level, int optname,
+                                const void* optval, uint32_t len);
+      grpc_error* (*bind)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
+                          size_t len, int flags);
+      grpc_error* (*listen)(grpc_custom_socket* socket);
+      void (*accept)(grpc_custom_socket* socket, grpc_custom_socket* client,
+                     grpc_custom_accept_callback cb);
+
+cdef extern from "src/core/lib/iomgr/timer_custom.h":
+  struct grpc_custom_timer:
+    void* timer
+    int timeout_ms
+     # We don't care about the rest of the fields
+
+  struct grpc_custom_timer_vtable:
+    void (*start)(grpc_custom_timer* t);
+    void (*stop)(grpc_custom_timer* t);
+
+  void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error);
+
+cdef extern from "src/core/lib/iomgr/pollset_custom.h":
+  struct grpc_custom_poller_vtable:
+    void (*init)()
+    void (*poll)(size_t timeout_ms)
+    void (*kick)()
+    void (*shutdown)()
+
+cdef extern from "src/core/lib/iomgr/iomgr_custom.h":
+  void grpc_custom_iomgr_init(grpc_socket_vtable* socket,
+                            grpc_custom_resolver_vtable* resolver,
+                            grpc_custom_timer_vtable* timer,
+                            grpc_custom_poller_vtable* poller);
+
+cdef extern from "src/core/lib/iomgr/sockaddr_utils.h":
+  int grpc_sockaddr_get_port(const grpc_resolved_address *addr);
+  int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr,
+                              int normalize);
+  void grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port);
+  int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr,
+                             int port)
+  const char* grpc_sockaddr_get_uri_scheme(const grpc_resolved_address* resolved_addr)
+
+
+cdef class TimerWrapper:
+
+  cdef grpc_custom_timer *c_timer
+  cdef object timer
+  cdef object event
+
+cdef class SocketWrapper:
+  cdef object sockopts
+  cdef object socket
+  cdef object closed
+  cdef grpc_custom_socket *c_socket
+  cdef char* c_buffer
+  cdef size_t len
+  cdef grpc_custom_socket *accepting_socket
+
+  cdef grpc_custom_connect_callback connect_cb
+  cdef grpc_custom_write_callback write_cb
+  cdef grpc_custom_read_callback read_cb
+  cdef grpc_custom_accept_callback accept_cb
+  cdef grpc_custom_close_callback close_cb
+
+
+cdef class ResolveWrapper:
+  cdef grpc_custom_resolver *c_resolver
+  cdef char* c_host
+  cdef char* c_port
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx
new file mode 100644
index 0000000..ba8c731
--- /dev/null
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx
@@ -0,0 +1,454 @@
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# distutils: language=c++
+
+cimport cpython
+from libc cimport string
+from libc.stdlib cimport malloc, free
+import errno
+gevent_g = None
+gevent_socket = None
+gevent_hub = None
+gevent_event = None
+g_event = None
+g_pool = None
+
+cdef grpc_error* grpc_error_none():
+  return <grpc_error*>0
+
+cdef grpc_error* socket_error(str syscall, str err):
+  error_str = "{} failed: {}".format(syscall, err)
+  error_bytes = str_to_bytes(error_str)
+  return grpc_socket_error(error_bytes)
+
+cdef resolved_addr_to_tuple(grpc_resolved_address* address):
+  cdef char* res_str
+  port = grpc_sockaddr_get_port(address)
+  str_len = grpc_sockaddr_to_string(&res_str, address, 0) 
+  byte_str = _decode(<bytes>res_str[:str_len])
+  if byte_str.endswith(':' + str(port)):
+    byte_str = byte_str[:(0 - len(str(port)) - 1)]
+  byte_str = byte_str.lstrip('[')
+  byte_str = byte_str.rstrip(']')
+  byte_str = '{}'.format(byte_str)
+  return byte_str, port
+
+cdef sockaddr_to_tuple(const grpc_sockaddr* address, size_t length):
+  cdef grpc_resolved_address c_addr
+  string.memcpy(<void*>c_addr.addr, <void*> address, length)
+  c_addr.len = length
+  return resolved_addr_to_tuple(&c_addr)
+
+cdef sockaddr_is_ipv4(const grpc_sockaddr* address, size_t length):
+  cdef grpc_resolved_address c_addr
+  string.memcpy(<void*>c_addr.addr, <void*> address, length)
+  c_addr.len = length
+  return grpc_sockaddr_get_uri_scheme(&c_addr) == b'ipv4'
+
+cdef grpc_resolved_addresses* tuples_to_resolvaddr(tups):
+  cdef grpc_resolved_addresses* addresses
+  tups_set = set((tup[4][0], tup[4][1]) for tup in tups)
+  addresses = <grpc_resolved_addresses*> malloc(sizeof(grpc_resolved_addresses))
+  addresses.naddrs = len(tups_set)
+  addresses.addrs = <grpc_resolved_address*> malloc(sizeof(grpc_resolved_address) * len(tups_set))
+  i = 0
+  for tup in set(tups_set):
+    hostname = str_to_bytes(tup[0])
+    grpc_string_to_sockaddr(&addresses.addrs[i], hostname, tup[1])
+    i += 1
+  return addresses
+
+def _spawn_greenlet(*args):
+  greenlet = g_pool.spawn(*args)
+
+###############################
+### socket implementation ###
+###############################
+
+cdef class SocketWrapper:
+  def __cinit__(self):
+    self.sockopts = []
+    self.socket = None
+    self.c_socket = NULL
+    self.c_buffer = NULL
+    self.len = 0
+
+cdef grpc_error* socket_init(grpc_custom_socket* socket, int domain) with gil:
+  sw = SocketWrapper()
+  sw.c_socket = socket
+  sw.sockopts = []
+  cpython.Py_INCREF(sw)
+  # Python doesn't support AF_UNSPEC sockets, so we defer creation until
+  # bind/connect when we know what type of socket we need
+  sw.socket = None
+  sw.closed = False
+  sw.accepting_socket = NULL
+  socket.impl = <void*>sw
+  return grpc_error_none()
+
+cdef socket_connect_async_cython(SocketWrapper socket_wrapper, addr_tuple):
+  try:
+    socket_wrapper.socket.connect(addr_tuple)
+    socket_wrapper.connect_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                              grpc_error_none())
+  except IOError as io_error:
+    socket_wrapper.connect_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                              socket_error("connect", str(io_error)))
+  g_event.set()
+
+def socket_connect_async(socket_wrapper, addr_tuple):
+  socket_connect_async_cython(socket_wrapper, addr_tuple)
+
+cdef void socket_connect(grpc_custom_socket* socket, const grpc_sockaddr* addr,
+                         size_t addr_len,
+                         grpc_custom_connect_callback cb) with gil:
+  py_socket = None
+  socket_wrapper = <SocketWrapper>socket.impl
+  socket_wrapper.connect_cb = cb
+  addr_tuple = sockaddr_to_tuple(addr, addr_len)
+  if sockaddr_is_ipv4(addr, addr_len):
+      py_socket = gevent_socket.socket(gevent_socket.AF_INET)
+  else:
+      py_socket = gevent_socket.socket(gevent_socket.AF_INET6)
+  applysockopts(py_socket)
+  socket_wrapper.socket = py_socket
+  _spawn_greenlet(socket_connect_async, socket_wrapper, addr_tuple)
+
+cdef void socket_destroy(grpc_custom_socket* socket) with gil:
+  cpython.Py_DECREF(<SocketWrapper>socket.impl)
+
+cdef void socket_shutdown(grpc_custom_socket* socket) with gil:
+  try:
+    (<SocketWrapper>socket.impl).socket.shutdown(gevent_socket.SHUT_RDWR)
+  except IOError as io_error:
+    if io_error.errno != errno.ENOTCONN:
+      raise io_error
+
+cdef void socket_close(grpc_custom_socket* socket,
+                       grpc_custom_close_callback cb) with gil:
+  socket_wrapper = (<SocketWrapper>socket.impl)
+  if socket_wrapper.socket is not None:
+    socket_wrapper.socket.close()
+    socket_wrapper.closed = True
+    socket_wrapper.close_cb = cb
+    # Delay the close callback until the accept() call has picked it up
+    if socket_wrapper.accepting_socket != NULL:
+      return
+  socket_wrapper.close_cb(socket)
+
+def socket_sendmsg(socket, write_bytes):
+  try:
+    return socket.sendmsg(write_bytes)
+  except AttributeError:
+    # sendmsg not available on all Pythons/Platforms
+    return socket.send(b''.join(write_bytes))
+
+cdef socket_write_async_cython(SocketWrapper socket_wrapper, write_bytes):
+  try:
+    while write_bytes:
+      sent_byte_count = socket_sendmsg(socket_wrapper.socket, write_bytes)
+      while sent_byte_count > 0:
+        if sent_byte_count < len(write_bytes[0]):
+          write_bytes[0] = write_bytes[0][sent_byte_count:]
+          sent_byte_count = 0
+        else:
+          sent_byte_count -= len(write_bytes[0])
+          write_bytes = write_bytes[1:]
+    socket_wrapper.write_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                            grpc_error_none())
+  except IOError as io_error:
+    socket_wrapper.write_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                            socket_error("send", str(io_error)))
+  g_event.set()
+
+def socket_write_async(socket_wrapper, write_bytes):
+  socket_write_async_cython(socket_wrapper, write_bytes)
+
+cdef void socket_write(grpc_custom_socket* socket, grpc_slice_buffer* buffer,
+                       grpc_custom_write_callback cb) with gil:
+  cdef char* start
+  sw = <SocketWrapper>socket.impl
+  sw.write_cb = cb
+  write_bytes = []
+  for i in range(buffer.count):
+    start = grpc_slice_buffer_start(buffer, i)
+    length = grpc_slice_buffer_length(buffer, i)
+    write_bytes.append(<bytes>start[:length])
+  _spawn_greenlet(socket_write_async, <SocketWrapper>socket.impl, write_bytes)
+
+cdef socket_read_async_cython(SocketWrapper socket_wrapper):
+  cdef char* buff_char_arr
+  try:
+    buff_str = socket_wrapper.socket.recv(socket_wrapper.len)
+    buff_char_arr = buff_str
+    string.memcpy(<void*>socket_wrapper.c_buffer, buff_char_arr, len(buff_str))
+    socket_wrapper.read_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                           len(buff_str), grpc_error_none())
+  except IOError as io_error:
+    socket_wrapper.read_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                           -1, socket_error("recv", str(io_error)))
+  g_event.set()
+
+def socket_read_async(socket_wrapper):
+  socket_read_async_cython(socket_wrapper)
+
+cdef void socket_read(grpc_custom_socket* socket, char* buffer,
+                      size_t length, grpc_custom_read_callback cb) with gil:
+  sw = <SocketWrapper>socket.impl
+  sw.read_cb = cb
+  sw.c_buffer = buffer
+  sw.len = length
+  _spawn_greenlet(socket_read_async, sw)
+
+cdef grpc_error* socket_getpeername(grpc_custom_socket* socket,
+                                    const grpc_sockaddr* addr,
+                                    int* length) with gil:
+  cdef char* src_buf
+  peer = (<SocketWrapper>socket.impl).socket.getpeername()
+
+  cdef grpc_resolved_address c_addr
+  hostname = str_to_bytes(peer[0])
+  grpc_string_to_sockaddr(&c_addr, hostname, peer[1])
+  string.memcpy(<void*>addr, <void*>c_addr.addr, c_addr.len)
+  length[0] = c_addr.len
+  return grpc_error_none()  
+
+cdef grpc_error* socket_getsockname(grpc_custom_socket* socket,
+                                    const grpc_sockaddr* addr,
+                                    int* length) with gil:
+  cdef char* src_buf
+  cdef grpc_resolved_address c_addr
+  if (<SocketWrapper>socket.impl).socket is None:
+    peer = ('0.0.0.0', 0)
+  else:
+    peer = (<SocketWrapper>socket.impl).socket.getsockname()
+  hostname = str_to_bytes(peer[0])
+  grpc_string_to_sockaddr(&c_addr, hostname, peer[1])
+  string.memcpy(<void*>addr, <void*>c_addr.addr, c_addr.len)
+  length[0] = c_addr.len
+  return grpc_error_none()
+
+cdef grpc_error* socket_setsockopt(grpc_custom_socket* socket, int level, int optname,
+                const void *optval, uint32_t optlen) with gil:
+  # No-op; we provide a default set of options
+  return grpc_error_none()
+
+def applysockopts(s):
+  s.setsockopt(gevent_socket.SOL_SOCKET, gevent_socket.SO_REUSEADDR, 1)
+  s.setsockopt(gevent_socket.IPPROTO_TCP, gevent_socket.TCP_NODELAY, True)
+
+cdef grpc_error* socket_bind(grpc_custom_socket* socket,
+                             const grpc_sockaddr* addr,
+                             size_t len, int flags) with gil:
+  addr_tuple = sockaddr_to_tuple(addr, len)
+  try:
+    try:
+      py_socket = gevent_socket.socket(gevent_socket.AF_INET)
+      applysockopts(py_socket)
+      py_socket.bind(addr_tuple)
+    except gevent_socket.gaierror as e:
+      py_socket = gevent_socket.socket(gevent_socket.AF_INET6)
+      applysockopts(py_socket)
+      py_socket.bind(addr_tuple)
+    (<SocketWrapper>socket.impl).socket = py_socket
+  except IOError as io_error:
+    return socket_error("bind", str(io_error))
+  else:
+    return grpc_error_none()
+
+cdef grpc_error* socket_listen(grpc_custom_socket* socket) with gil:
+  (<SocketWrapper>socket.impl).socket.listen(50)
+  return grpc_error_none()
+
+cdef void accept_callback_cython(SocketWrapper s):
+   try:
+     conn, address = s.socket.accept()
+     sw = SocketWrapper()
+     sw.closed = False
+     sw.c_socket = s.accepting_socket
+     sw.sockopts = []
+     sw.socket = conn
+     sw.c_socket.impl = <void*>sw
+     sw.accepting_socket = NULL
+     cpython.Py_INCREF(sw)
+     s.accepting_socket = NULL
+     s.accept_cb(<grpc_custom_socket*>s.c_socket, sw.c_socket, grpc_error_none())
+   except IOError as io_error:
+      #TODO actual error
+      s.accepting_socket = NULL
+      s.accept_cb(<grpc_custom_socket*>s.c_socket, s.accepting_socket,
+                  socket_error("accept", str(io_error)))
+      if s.closed:
+        s.close_cb(<grpc_custom_socket*>s.c_socket)
+   g_event.set()
+
+def socket_accept_async(s):
+  accept_callback_cython(s)
+
+cdef void socket_accept(grpc_custom_socket* socket, grpc_custom_socket* client,
+                        grpc_custom_accept_callback cb) with gil:
+  sw = <SocketWrapper>socket.impl
+  sw.accepting_socket = client
+  sw.accept_cb = cb
+  _spawn_greenlet(socket_accept_async, sw)
+
+#####################################
+######Resolver implementation #######
+#####################################
+
+cdef class ResolveWrapper:
+  def __cinit__(self):
+    self.c_resolver = NULL
+    self.c_host = NULL
+    self.c_port = NULL
+
+cdef socket_resolve_async_cython(ResolveWrapper resolve_wrapper):
+  try:
+    res = gevent_socket.getaddrinfo(resolve_wrapper.c_host, resolve_wrapper.c_port)
+    grpc_custom_resolve_callback(<grpc_custom_resolver*>resolve_wrapper.c_resolver,
+                                 tuples_to_resolvaddr(res), grpc_error_none())
+  except IOError as io_error:
+    grpc_custom_resolve_callback(<grpc_custom_resolver*>resolve_wrapper.c_resolver,
+                                 <grpc_resolved_addresses*>0,
+                                 socket_error("getaddrinfo", str(io_error)))
+  g_event.set()
+
+def socket_resolve_async_python(resolve_wrapper):
+  socket_resolve_async_cython(resolve_wrapper)
+
+cdef void socket_resolve_async(grpc_custom_resolver* r, char* host, char* port) with gil:
+  rw = ResolveWrapper()
+  rw.c_resolver = r
+  rw.c_host = host
+  rw.c_port = port
+  _spawn_greenlet(socket_resolve_async_python, rw)
+
+cdef grpc_error* socket_resolve(char* host, char* port,
+                                grpc_resolved_addresses** res) with gil:
+    try:
+      result = gevent_socket.getaddrinfo(host, port)
+      res[0] = tuples_to_resolvaddr(result)
+      return grpc_error_none()
+    except IOError as io_error:
+      return socket_error("getaddrinfo", str(io_error))
+
+###############################
+### timer implementation ######
+###############################
+
+cdef class TimerWrapper:
+  def __cinit__(self, deadline):
+    self.timer = gevent_hub.get_hub().loop.timer(deadline)
+    self.event = None
+
+  def start(self):
+    self.event = gevent_event.Event()
+    self.timer.start(self.on_finish)
+
+  def on_finish(self):
+    grpc_custom_timer_callback(self.c_timer, grpc_error_none())
+    self.timer.stop()
+    g_event.set()
+
+  def stop(self):
+    self.event.set()
+    self.timer.stop()
+
+cdef void timer_start(grpc_custom_timer* t) with gil:
+  timer = TimerWrapper(t.timeout_ms / 1000.0)
+  timer.c_timer = t
+  t.timer = <void*>timer
+  timer.start()
+
+cdef void timer_stop(grpc_custom_timer* t) with gil:
+  time_wrapper = <object>t.timer
+  time_wrapper.stop()
+
+###############################
+### pollset implementation ###
+###############################
+
+cdef void init_loop() with gil:
+  pass
+
+cdef void destroy_loop() with gil:
+  g_pool.join()
+
+cdef void kick_loop() with gil:
+  g_event.set()
+
+cdef void run_loop(size_t timeout_ms) with gil:
+    timeout = timeout_ms / 1000.0
+    if timeout_ms > 0:
+      g_event.wait(timeout)
+      g_event.clear()
+
+###############################
+### Initializer ###############
+###############################
+
+cdef grpc_socket_vtable gevent_socket_vtable
+cdef grpc_custom_resolver_vtable gevent_resolver_vtable
+cdef grpc_custom_timer_vtable gevent_timer_vtable
+cdef grpc_custom_poller_vtable gevent_pollset_vtable
+
+def init_grpc_gevent():
+  # Lazily import gevent
+  global gevent_socket
+  global gevent_g
+  global gevent_hub
+  global gevent_event
+  global g_event
+  global g_pool
+  import gevent
+  gevent_g = gevent
+  import gevent.socket
+  gevent_socket = gevent.socket
+  import gevent.hub
+  gevent_hub = gevent.hub
+  import gevent.event
+  gevent_event = gevent.event
+  import gevent.pool
+
+  g_event = gevent.event.Event()
+  g_pool = gevent.pool.Group()
+  gevent_resolver_vtable.resolve = socket_resolve
+  gevent_resolver_vtable.resolve_async = socket_resolve_async
+
+  gevent_socket_vtable.init = socket_init
+  gevent_socket_vtable.connect = socket_connect
+  gevent_socket_vtable.destroy = socket_destroy
+  gevent_socket_vtable.shutdown = socket_shutdown
+  gevent_socket_vtable.close = socket_close
+  gevent_socket_vtable.write = socket_write
+  gevent_socket_vtable.read = socket_read
+  gevent_socket_vtable.getpeername = socket_getpeername
+  gevent_socket_vtable.getsockname = socket_getsockname
+  gevent_socket_vtable.setsockopt = socket_setsockopt
+  gevent_socket_vtable.bind = socket_bind
+  gevent_socket_vtable.listen = socket_listen
+  gevent_socket_vtable.accept = socket_accept
+
+  gevent_timer_vtable.start = timer_start
+  gevent_timer_vtable.stop = timer_stop
+
+  gevent_pollset_vtable.init = init_loop
+  gevent_pollset_vtable.poll = run_loop
+  gevent_pollset_vtable.kick = kick_loop
+  gevent_pollset_vtable.shutdown = destroy_loop
+
+  grpc_custom_iomgr_init(&gevent_socket_vtable,
+                         &gevent_resolver_vtable,
+                         &gevent_timer_vtable,
+                         &gevent_pollset_vtable)
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pxd b/src/python/grpcio/grpc/_cython/cygrpc.pxd
index b6a794c..c8ace7c 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pxd
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pxd
@@ -11,6 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+# distutils: language=c++
 
 include "_cygrpc/grpc.pxi"
 
@@ -27,3 +28,5 @@
 include "_cygrpc/server.pxd.pxi"
 include "_cygrpc/tag.pxd.pxi"
 include "_cygrpc/time.pxd.pxi"
+
+include "_cygrpc/grpc_gevent.pxd"
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx
index 2ee2e6b..f5f08fc 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
@@ -11,6 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+# distutils: language=c++
 
 cimport cpython
 
@@ -35,6 +36,8 @@
 include "_cygrpc/tag.pyx.pxi"
 include "_cygrpc/time.pyx.pxi"
 
+include "_cygrpc/grpc_gevent.pyx"
+
 #
 # initialize gRPC
 #
diff --git a/src/python/grpcio/grpc/experimental/__init__.py b/src/python/grpcio/grpc/experimental/__init__.py
new file mode 100644
index 0000000..dcec322
--- /dev/null
+++ b/src/python/grpcio/grpc/experimental/__init__.py
@@ -0,0 +1,17 @@
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""gRPC's experimental APIs.
+
+These APIs are subject to be removed during any minor version release.
+"""
diff --git a/src/python/grpcio/grpc/experimental/gevent.py b/src/python/grpcio/grpc/experimental/gevent.py
new file mode 100644
index 0000000..159d612
--- /dev/null
+++ b/src/python/grpcio/grpc/experimental/gevent.py
@@ -0,0 +1,27 @@
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""gRPC's Python gEvent APIs."""
+
+from grpc._cython import cygrpc as _cygrpc
+
+
+def init_gevent():
+    """Patches gRPC's libraries to be compatible with gevent.
+
+    This must be called AFTER the python standard lib has been patched,
+    but BEFORE creating and gRPC objects.
+
+    In order for progress to be made, the application must drive the event loop.
+    """
+    _cygrpc.init_grpc_gevent()
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 9f4aaff..b1f9d20 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -299,6 +299,7 @@
     'src/core/tsi/transport_security_adapter.cc',
     'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
     'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+    'src/core/ext/transport/chttp2/client/authority.cc',
     'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
     'src/core/ext/filters/client_channel/backup_poller.cc',
     'src/core/ext/filters/client_channel/channel_connectivity.cc',
@@ -356,6 +357,7 @@
     'src/core/ext/census/grpc_context.cc',
     'src/core/ext/filters/max_age/max_age_filter.cc',
     'src/core/ext/filters/message_size/message_size_filter.cc',
+    'src/core/ext/filters/http/client_authority_filter.cc',
     'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
     'src/core/ext/filters/workarounds/workaround_utils.cc',
     'src/core/plugin_registry/grpc_plugin_registry.cc',
diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py
index 93f8457..42e01c1 100644
--- a/src/python/grpcio_tests/commands.py
+++ b/src/python/grpcio_tests/commands.py
@@ -108,6 +108,57 @@
         self.distribution.fetch_build_eggs(self.distribution.tests_require)
 
 
+class TestGevent(setuptools.Command):
+    """Command to run tests w/gevent."""
+
+    BANNED_TESTS = (
+        # These tests send a lot of RPCs and are really slow on gevent.  They will
+        # eventually succeed, but need to dig into performance issues.
+        'unit._cython._no_messages_server_completion_queue_per_call_test.Test.test_rpcs',
+        'unit._cython._no_messages_single_server_completion_queue_test.Test.test_rpcs',
+        # I have no idea why this doesn't work in gevent, but it shouldn't even be
+        # using the c-core
+        'testing._client_test.ClientTest.test_infinite_request_stream_real_time',
+        # TODO(https://github.com/grpc/grpc/issues/14789) enable this test
+        'unit._server_ssl_cert_config_test',
+        # TODO(https://github.com/grpc/grpc/issues/14901) enable this test
+        'protoc_plugin._python_plugin_test.PythonPluginTest',
+        # Beta API is unsupported for gevent
+        'protoc_plugin.beta_python_plugin_test',
+        'unit.beta._beta_features_test',
+    )
+    description = 'run tests with gevent.  Assumes grpc/gevent are installed'
+    user_options = []
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        # distutils requires this override.
+        pass
+
+    def run(self):
+        from gevent import monkey
+        monkey.patch_all()
+
+        import tests
+
+        import grpc.experimental.gevent
+        grpc.experimental.gevent.init_gevent()
+
+        import gevent
+
+        import tests
+        loader = tests.Loader()
+        loader.loadTestsFromNames(['tests'])
+        runner = tests.Runner()
+        runner.skip_tests(self.BANNED_TESTS)
+        result = gevent.spawn(runner.run, loader.suite)
+        result.join()
+        if not result.value.wasSuccessful():
+            sys.exit('Test failure')
+
+
 class RunInterop(test.test):
 
     description = 'run interop test client/server'
diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py
index 250df65..4e0f672 100644
--- a/src/python/grpcio_tests/setup.py
+++ b/src/python/grpcio_tests/setup.py
@@ -50,7 +50,8 @@
     'build_package_protos': grpc_tools.command.BuildPackageProtos,
     'build_py': commands.BuildPy,
     'run_interop': commands.RunInterop,
-    'test_lite': commands.TestLite
+    'test_lite': commands.TestLite,
+    'test_gevent': commands.TestGevent,
 }
 
 PACKAGE_DATA = {
diff --git a/src/python/grpcio_tests/tests/_runner.py b/src/python/grpcio_tests/tests/_runner.py
index 8e27dc6..eaaa027 100644
--- a/src/python/grpcio_tests/tests/_runner.py
+++ b/src/python/grpcio_tests/tests/_runner.py
@@ -117,6 +117,12 @@
 
 class Runner(object):
 
+    def __init__(self):
+        self._skipped_tests = []
+
+    def skip_tests(self, tests):
+        self._skipped_tests = tests
+
     def run(self, suite):
         """See setuptools' test_runner setup argument for information."""
         # only run test cases with id starting with given prefix
@@ -181,27 +187,31 @@
         # Run the tests
         result.startTestRun()
         for augmented_case in augmented_cases:
-            sys.stdout.write('Running       {}\n'.format(
-                augmented_case.case.id()))
-            sys.stdout.flush()
-            case_thread = threading.Thread(
-                target=augmented_case.case.run, args=(result,))
-            try:
-                with stdout_pipe, stderr_pipe:
-                    case_thread.start()
-                    while case_thread.is_alive():
-                        check_kill_self()
-                        time.sleep(0)
-                    case_thread.join()
-            except:
-                # re-raise the exception after forcing the with-block to end
-                raise
-            result.set_output(augmented_case.case, stdout_pipe.output(),
-                              stderr_pipe.output())
-            sys.stdout.write(result_out.getvalue())
-            sys.stdout.flush()
-            result_out.truncate(0)
-            check_kill_self()
+            for skipped_test in self._skipped_tests:
+                if skipped_test in augmented_case.case.id():
+                    break
+            else:
+                sys.stdout.write('Running       {}\n'.format(
+                    augmented_case.case.id()))
+                sys.stdout.flush()
+                case_thread = threading.Thread(
+                    target=augmented_case.case.run, args=(result,))
+                try:
+                    with stdout_pipe, stderr_pipe:
+                        case_thread.start()
+                        while case_thread.is_alive():
+                            check_kill_self()
+                            time.sleep(0)
+                        case_thread.join()
+                except:
+                    # re-raise the exception after forcing the with-block to end
+                    raise
+                result.set_output(augmented_case.case, stdout_pipe.output(),
+                                  stderr_pipe.output())
+                sys.stdout.write(result_out.getvalue())
+                sys.stdout.flush()
+                result_out.truncate(0)
+                check_kill_self()
         result.stopTestRun()
         stdout_pipe.close()
         stderr_pipe.close()
diff --git a/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py b/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py
index 8d464b2..ace15be 100644
--- a/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py
+++ b/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py
@@ -36,6 +36,9 @@
         self.stub = test_pb2_grpc.TestServiceStub(
             grpc.insecure_channel('localhost:{}'.format(port)))
 
+    def tearDown(self):
+        self.server.stop(None)
+
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py b/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py
index c891359..e27e551 100644
--- a/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py
+++ b/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py
@@ -45,6 +45,9 @@
                                         _SERVER_HOST_OVERRIDE,
                                     ),)))
 
+    def tearDown(self):
+        self.server.stop(None)
+
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py
index 6d85f43..00e60b4 100644
--- a/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py
+++ b/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py
@@ -237,6 +237,7 @@
         self.assertIsNotNone(service.servicer_methods)
         self.assertIsNotNone(service.server)
         self.assertIsNotNone(service.stub)
+        service.server.stop(None)
 
     def testIncompleteServicer(self):
         service = _CreateIncompleteService()
@@ -245,6 +246,7 @@
             service.stub.UnaryCall(request)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.UNIMPLEMENTED)
+        service.server.stop(None)
 
     def testUnaryCall(self):
         service = _CreateService()
@@ -253,6 +255,7 @@
         expected_response = service.servicer_methods.UnaryCall(
             request, 'not a real context!')
         self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testUnaryCallFuture(self):
         service = _CreateService()
@@ -264,6 +267,7 @@
         expected_response = service.servicer_methods.UnaryCall(
             request, 'not a real RpcContext!')
         self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testUnaryCallFutureExpired(self):
         service = _CreateService()
@@ -276,6 +280,7 @@
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
         self.assertIs(response_future.code(), grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
     def testUnaryCallFutureCancelled(self):
         service = _CreateService()
@@ -285,6 +290,7 @@
             response_future.cancel()
         self.assertTrue(response_future.cancelled())
         self.assertIs(response_future.code(), grpc.StatusCode.CANCELLED)
+        service.server.stop(None)
 
     def testUnaryCallFutureFailed(self):
         service = _CreateService()
@@ -293,6 +299,7 @@
             response_future = service.stub.UnaryCall.future(request)
             self.assertIsNotNone(response_future.exception())
         self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN)
+        service.server.stop(None)
 
     def testStreamingOutputCall(self):
         service = _CreateService()
@@ -303,6 +310,7 @@
         for expected_response, response in moves.zip_longest(
                 expected_responses, responses):
             self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testStreamingOutputCallExpired(self):
         service = _CreateService()
@@ -314,6 +322,7 @@
                 list(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
     def testStreamingOutputCallCancelled(self):
         service = _CreateService()
@@ -324,6 +333,7 @@
         with self.assertRaises(grpc.RpcError) as exception_context:
             next(responses)
         self.assertIs(responses.code(), grpc.StatusCode.CANCELLED)
+        service.server.stop(None)
 
     def testStreamingOutputCallFailed(self):
         service = _CreateService()
@@ -335,6 +345,7 @@
                 next(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.UNKNOWN)
+        service.server.stop(None)
 
     def testStreamingInputCall(self):
         service = _CreateService()
@@ -343,6 +354,7 @@
         expected_response = service.servicer_methods.StreamingInputCall(
             _streaming_input_request_iterator(), 'not a real RpcContext!')
         self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testStreamingInputCallFuture(self):
         service = _CreateService()
@@ -353,6 +365,7 @@
         expected_response = service.servicer_methods.StreamingInputCall(
             _streaming_input_request_iterator(), 'not a real RpcContext!')
         self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testStreamingInputCallFutureExpired(self):
         service = _CreateService()
@@ -367,6 +380,7 @@
                       grpc.StatusCode.DEADLINE_EXCEEDED)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
     def testStreamingInputCallFutureCancelled(self):
         service = _CreateService()
@@ -377,6 +391,7 @@
         self.assertTrue(response_future.cancelled())
         with self.assertRaises(grpc.FutureCancelledError):
             response_future.result()
+        service.server.stop(None)
 
     def testStreamingInputCallFutureFailed(self):
         service = _CreateService()
@@ -385,6 +400,7 @@
                 _streaming_input_request_iterator())
             self.assertIsNotNone(response_future.exception())
             self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN)
+        service.server.stop(None)
 
     def testFullDuplexCall(self):
         service = _CreateService()
@@ -394,6 +410,7 @@
         for expected_response, response in moves.zip_longest(
                 expected_responses, responses):
             self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testFullDuplexCallExpired(self):
         request_iterator = _full_duplex_request_iterator()
@@ -405,6 +422,7 @@
                 list(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
     def testFullDuplexCallCancelled(self):
         service = _CreateService()
@@ -416,6 +434,7 @@
             next(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.CANCELLED)
+        service.server.stop(None)
 
     def testFullDuplexCallFailed(self):
         request_iterator = _full_duplex_request_iterator()
@@ -426,6 +445,7 @@
                 next(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.UNKNOWN)
+        service.server.stop(None)
 
     def testHalfDuplexCall(self):
         service = _CreateService()
@@ -445,6 +465,7 @@
         for expected_response, response in moves.zip_longest(
                 expected_responses, responses):
             self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testHalfDuplexCallWedged(self):
         condition = threading.Condition()
@@ -478,6 +499,7 @@
                 next(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
 
 if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
index ab33775..e21ea00 100644
--- a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
+++ b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
@@ -271,6 +271,7 @@
             stub = services_module.TestServiceStub(channel)
             response = stub.Call(self._messages_pb2.Request())
             self.assertEqual(self._messages_pb2.Response(), response)
+            server.stop(None)
 
 
 def _create_test_case_class(split_proto, protoc_style):
diff --git a/src/ruby/end2end/client_memory_usage_client.rb b/src/ruby/end2end/client_memory_usage_client.rb
new file mode 100755
index 0000000..c6268b4
--- /dev/null
+++ b/src/ruby/end2end/client_memory_usage_client.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require_relative './end2end_common'
+require 'objspace'
+
+def main
+  server_port = ''
+  loop_count = 200
+
+  OptionParser.new do |opts|
+    opts.on('--client_control_port=P', String) do
+      STDERR.puts 'client_control_port ignored'
+    end
+    opts.on('--server_port=P', String) do |p|
+      server_port = p
+    end
+  end.parse!
+
+  loop_count.times do
+    stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", :this_channel_is_insecure)
+    stub.echo(Echo::EchoRequest.new(request: 'client/child'))
+
+    # Get memory usage of all objects
+    ObjectSpace.memsize_of_all
+  end
+
+  STDERR.puts "Succeeded in getting memory usage for #{loop_count} times"
+end
+
+main
diff --git a/src/ruby/end2end/client_memory_usage_driver.rb b/src/ruby/end2end/client_memory_usage_driver.rb
new file mode 100755
index 0000000..9e46d7e
--- /dev/null
+++ b/src/ruby/end2end/client_memory_usage_driver.rb
@@ -0,0 +1,36 @@
+#!/usr/bin/env ruby
+
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require_relative './end2end_common'
+
+def main
+  STDERR.puts 'start server'
+  server_runner = ServerRunner.new(EchoServerImpl)
+  server_port = server_runner.run
+  STDERR.puts 'start client'
+  _, client_pid = start_client('client_memory_usage_client.rb', server_port)
+
+  Process.wait(client_pid)
+
+  client_exit_code = $CHILD_STATUS
+  if client_exit_code != 0
+    raise "Getting memory usage was failed, exit code #{client_exit_code}"
+  end
+ensure
+  server_runner.stop
+end
+
+main
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 7f3ca2a..b6c0791 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -103,23 +103,11 @@
   xfree(p);
 }
 
-static size_t md_ary_datasize(const void* p) {
-  const grpc_metadata_array* const ary = (grpc_metadata_array*)p;
-  size_t i, datasize = sizeof(grpc_metadata_array);
-  for (i = 0; i < ary->count; ++i) {
-    const grpc_metadata* const md = &ary->metadata[i];
-    datasize += GRPC_SLICE_LENGTH(md->key);
-    datasize += GRPC_SLICE_LENGTH(md->value);
-  }
-  datasize += ary->capacity * sizeof(grpc_metadata);
-  return datasize;
-}
-
 static const rb_data_type_t grpc_rb_md_ary_data_type = {
     "grpc_metadata_array",
     {GRPC_RB_GC_NOT_MARKED,
      GRPC_RB_GC_DONT_FREE,
-     md_ary_datasize,
+     GRPC_RB_MEMSIZE_UNAVAILABLE,
      {NULL, NULL}},
     NULL,
     NULL,
diff --git a/src/ruby/spec/pb/package_with_underscore/checker_spec.rb b/src/ruby/spec/pb/package_with_underscore/checker_spec.rb
new file mode 100644
index 0000000..6155b3b
--- /dev/null
+++ b/src/ruby/spec/pb/package_with_underscore/checker_spec.rb
@@ -0,0 +1,54 @@
+# Copyright 2016 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'open3'
+require 'tmpdir'
+
+def debug_mode?
+  !ENV['CONFIG'].nil? && ENV['CONFIG'] == 'dbg'
+end
+
+describe 'Package with underscore protobuf code generation' do
+  it 'should have the same content as created by code generation' do
+    root_dir = File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..')
+    pb_dir = File.join(root_dir, 'src', 'ruby', 'spec', 'pb')
+
+    bins_sub_dir = debug_mode? ? 'dbg' : 'opt'
+    bins_dir = File.join(root_dir, 'bins', bins_sub_dir)
+
+    plugin = File.join(bins_dir, 'grpc_ruby_plugin')
+    protoc = File.join(bins_dir, 'protobuf', 'protoc')
+
+    got = nil
+
+    Dir.mktmpdir do |tmp_dir|
+      gen_out = File.join(tmp_dir, 'package_with_underscore', 'service_services_pb.rb')
+
+      pid = spawn(
+        protoc,
+        '-I.',
+        'package_with_underscore/service.proto',
+        "--grpc_out=#{tmp_dir}",
+        "--plugin=protoc-gen-grpc=#{plugin}",
+        chdir: pb_dir)
+      Process.waitpid2(pid)
+      File.open(gen_out) { |f| got = f.read }
+    end
+
+    correct_modularized_rpc = 'rpc :TestOne, '                \
+      'Grpc::Testing::PackageWithUnderscore::Data::Request, ' \
+      'Grpc::Testing::PackageWithUnderscore::Data::Response'
+    expect(got).to include(correct_modularized_rpc)
+  end
+end
diff --git a/src/ruby/spec/pb/package_with_underscore/data.proto b/src/ruby/spec/pb/package_with_underscore/data.proto
new file mode 100644
index 0000000..2706f1d
--- /dev/null
+++ b/src/ruby/spec/pb/package_with_underscore/data.proto
@@ -0,0 +1,23 @@
+// Copyright 2018 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package grpc.testing.package_with_underscore.data;
+
+message Request {
+}
+
+message Response {
+}
diff --git a/src/ruby/spec/pb/package_with_underscore/service.proto b/src/ruby/spec/pb/package_with_underscore/service.proto
new file mode 100644
index 0000000..814c789
--- /dev/null
+++ b/src/ruby/spec/pb/package_with_underscore/service.proto
@@ -0,0 +1,23 @@
+// Copyright 2018 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package grpc.testing.package_with_underscore.service;
+
+import "package_with_underscore/data.proto";
+
+service MyService {
+  rpc TestOne(data.Request) returns (data.Response) {}
+}
diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template
index 01fe569..8a1581a 100644
--- a/templates/CMakeLists.txt.template
+++ b/templates/CMakeLists.txt.template
@@ -298,11 +298,13 @@
   endif (gRPC_BUILD_TESTS)
   % else:
   ${cc_library(lib)}
+  % if not lib.build in ["tool"]:
   ${cc_install(lib)}
   % endif
   % endif
   % endif
   % endif
+  % endif
   % endfor
 
   % for tgt in targets:
@@ -323,7 +325,9 @@
   % else:
   ${get_platforms_condition_begin(tgt.platforms)}\
   ${cc_binary(tgt)}
+  % if not tgt.build in ["tool"]:
   ${cc_install(tgt)}
+  % endif
   ${get_platforms_condition_end(tgt.platforms)}\
   % endif
   % endif
diff --git a/templates/Makefile.template b/templates/Makefile.template
index c0ce2e5..354f2a2 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -416,7 +416,7 @@
   OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
   OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
   ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
-  PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.0.0 protobuf
+  PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf
   CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares
   else # HAS_PKG_CONFIG
 
@@ -844,7 +844,7 @@
   	@echo
   	@echo "DEPENDENCY ERROR"
   	@echo
-  	@echo "The target you are trying to run requires protobuf 3.0.0+"
+  	@echo "The target you are trying to run requires protobuf 3.5.0+"
   	@echo "Your system doesn't have it, and neither does the third_party directory."
   	@echo
   	@echo "Please consult INSTALL to get more information."
@@ -858,7 +858,7 @@
   	@echo
   	@echo "DEPENDENCY ERROR"
   	@echo
-  	@echo "The target you are trying to run requires protobuf-compiler 3.0.0+"
+  	@echo "The target you are trying to run requires protobuf-compiler 3.5.0+"
   	@echo "Your system doesn't have it, and neither does the third_party directory."
   	@echo
   	@echo "Please consult INSTALL to get more information."
@@ -1636,7 +1636,7 @@
   % endif
   % if lib.language == 'c++':
   ## If the lib was C++, we have to close the Makefile's if that tested
-  ## the presence of protobuf 3.0.0+
+  ## the presence of protobuf 3.5.0+
 
   endif
   % endif
@@ -1702,7 +1702,7 @@
 
   ifeq ($(NO_PROTOBUF),true)
 
-  # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+  # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
   $(BINDIR)/$(CONFIG)/${tgt.name}: protobuf_dep_error
 
diff --git a/templates/config.m4.template b/templates/config.m4.template
index 9877e4b..cc19d98 100644
--- a/templates/config.m4.template
+++ b/templates/config.m4.template
@@ -10,6 +10,7 @@
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
+    PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/address_sorting/include)
 
     LIBS="-lpthread $LIBS"
 
diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template
index 33a8a8b..af97d81 100644
--- a/templates/gRPC-Core.podspec.template
+++ b/templates/gRPC-Core.podspec.template
@@ -42,21 +42,21 @@
     out = grpc_lib_files(libs, ("grpc", "gpr"), ("headers",))
     return [file for file in out if not file.startswith("third_party/nanopb/")]
 
-  def grpc_cronet_private_files(libs):
-    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("headers", "src"))
-    excl = [
-        # We do not want dummy cronet API for ObjC
+  def grpc_cronet_files(libs):
+    out = grpc_lib_files(libs, ("grpc_cronet",), ("src", "headers"))
+    excl = grpc_private_files(libs)
+    excl += [
+        # We do not need cronet dedicated plugin registry
+        "src/core/plugin_registry/grpc_cronet_plugin_registry.cc",
+        # We do not need dummy cronet API for ObjC
         "src/core/ext/transport/cronet/transport/cronet_api_dummy.cc",
     ]
     return [file for file in out if not file in excl]
 
   def grpc_cronet_public_headers(libs):
-    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("public_headers",))
-    return out
-
-  def grpc_cronet_private_headers(libs):
-    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("headers",))
-    return out
+    out = grpc_lib_files(libs, ("grpc_cronet",), ("public_headers",))
+    excl = grpc_public_headers(libs)
+    return [file for file in out if not file in excl]
 
   def grpc_test_util_files(libs):
     out = grpc_lib_files(libs, ("grpc_test_util", "gpr_test_util"), ("src", "headers"))
@@ -169,6 +169,7 @@
       ss.dependency 'BoringSSL', '~> 10.0'
       ss.dependency 'nanopb', '~> 0.3'
 
+      # To save you from scrolling, this is the last part of the podspec.
       ss.source_files = ${ruby_multiline_list(grpc_private_files(libs), 22)}
 
       ss.private_header_files = ${ruby_multiline_list(grpc_private_headers(libs), 30)}
@@ -181,21 +182,19 @@
 
     s.subspec 'Cronet-Implementation' do |ss|
       ss.header_mappings_dir = '.'
-      ss.libraries = 'z'
+
+      ss.dependency "#{s.name}/Interface", version
+      ss.dependency "#{s.name}/Implementation", version
       ss.dependency "#{s.name}/Cronet-Interface", version
-      ss.dependency 'BoringSSL', '~> 10.0'
-      ss.dependency 'nanopb', '~> 0.3'
 
-      ss.source_files = ${ruby_multiline_list(grpc_cronet_private_files(libs), 22)}
-
-      ss.private_header_files = ${ruby_multiline_list(grpc_cronet_private_headers(libs), 30)}
+      ss.source_files = ${ruby_multiline_list(grpc_cronet_files(libs), 22)}
     end
 
-    s.subspec 'Cronet-Tests' do |ss|
+    s.subspec 'Tests' do |ss|
       ss.header_mappings_dir = '.'
 
-      ss.dependency "#{s.name}/Cronet-Interface", version
-      ss.dependency "#{s.name}/Cronet-Implementation", version
+      ss.dependency "#{s.name}/Interface", version
+      ss.dependency "#{s.name}/Implementation", version
 
       ss.source_files = ${ruby_multiline_list(grpc_test_util_files(libs), 22)},
                         ${ruby_multiline_list(end2end_tests_files(libs), 22)}
diff --git a/test/core/channel/minimal_stack_is_minimal_test.cc b/test/core/channel/minimal_stack_is_minimal_test.cc
index f02c818..e5953ac 100644
--- a/test/core/channel/minimal_stack_is_minimal_test.cc
+++ b/test/core/channel/minimal_stack_is_minimal_test.cc
@@ -66,35 +66,37 @@
   minimal_stack_arg.key = const_cast<char*>(GRPC_ARG_MINIMAL_STACK);
   minimal_stack_arg.value.integer = 1;
   grpc_channel_args minimal_stack_args = {1, &minimal_stack_arg};
-  errors += CHECK_STACK("unknown", &minimal_stack_args,
-                        GRPC_CLIENT_DIRECT_CHANNEL, "connected", NULL);
+  errors +=
+      CHECK_STACK("unknown", &minimal_stack_args, GRPC_CLIENT_DIRECT_CHANNEL,
+                  "authority", "connected", NULL);
   errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL,
-                        "connected", NULL);
+                        "authority", "connected", NULL);
   errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_SERVER_CHANNEL,
                         "server", "connected", NULL);
   errors +=
       CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_DIRECT_CHANNEL,
-                  "http-client", "connected", NULL);
+                  "authority", "http-client", "connected", NULL);
   errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL,
-                        "http-client", "connected", NULL);
+                        "authority", "http-client", "connected", NULL);
   errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_SERVER_CHANNEL,
                         "server", "http-server", "connected", NULL);
   errors += CHECK_STACK(nullptr, &minimal_stack_args, GRPC_CLIENT_CHANNEL,
                         "client-channel", NULL);
 
   // tests with a default stack
-  errors += CHECK_STACK("unknown", nullptr, GRPC_CLIENT_DIRECT_CHANNEL,
-                        "message_size", "deadline", "connected", NULL);
-  errors += CHECK_STACK("unknown", nullptr, GRPC_CLIENT_SUBCHANNEL,
+  errors +=
+      CHECK_STACK("unknown", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, "authority",
+                  "message_size", "deadline", "connected", NULL);
+  errors += CHECK_STACK("unknown", nullptr, GRPC_CLIENT_SUBCHANNEL, "authority",
                         "message_size", "connected", NULL);
   errors += CHECK_STACK("unknown", nullptr, GRPC_SERVER_CHANNEL, "server",
                         "message_size", "deadline", "connected", NULL);
   errors += CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_DIRECT_CHANNEL,
-                        "message_size", "deadline", "http-client",
+                        "authority", "message_size", "deadline", "http-client",
                         "message_compress", "connected", NULL);
-  errors +=
-      CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_SUBCHANNEL, "message_size",
-                  "http-client", "message_compress", "connected", NULL);
+  errors += CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_SUBCHANNEL, "authority",
+                        "message_size", "http-client", "message_compress",
+                        "connected", NULL);
   errors += CHECK_STACK("chttp2", nullptr, GRPC_SERVER_CHANNEL, "server",
                         "message_size", "deadline", "http-server",
                         "message_compress", "connected", NULL);
diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD
index 5148dc5..db98ffa 100644
--- a/test/core/client_channel/BUILD
+++ b/test/core/client_channel/BUILD
@@ -53,3 +53,18 @@
         "//test/core/util:grpc_test_util",
     ],
 )
+
+grpc_cc_test(
+    name = "retry_throttle_test",
+    srcs = ["retry_throttle_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/client_channel/retry_throttle_test.cc b/test/core/client_channel/retry_throttle_test.cc
new file mode 100644
index 0000000..c6d5d3e
--- /dev/null
+++ b/test/core/client_channel/retry_throttle_test.cc
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "src/core/ext/filters/client_channel/retry_throttle.h"
+
+#include <gtest/gtest.h>
+
+#include "test/core/util/test_config.h"
+
+namespace grpc_core {
+namespace internal {
+namespace {
+
+TEST(ServerRetryThrottleData, Basic) {
+  // Max token count is 4, so threshold for retrying is 2.
+  // Token count starts at 4.
+  // Each failure decrements by 1.  Each success increments by 1.6.
+  auto throttle_data =
+      MakeRefCounted<ServerRetryThrottleData>(4000, 1600, nullptr);
+  // Failure: token_count=3.  Above threshold.
+  EXPECT_TRUE(throttle_data->RecordFailure());
+  // Success: token_count=4.  Not incremented beyond max.
+  throttle_data->RecordSuccess();
+  // Failure: token_count=3.  Above threshold.
+  EXPECT_TRUE(throttle_data->RecordFailure());
+  // Failure: token_count=2.  At threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Failure: token_count=1.  Below threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Failure: token_count=0.  Below threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Failure: token_count=0.  Below threshold, so no retries.  Not
+  // decremented below min.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=1.6.
+  throttle_data->RecordSuccess();
+  // Success: token_count=3.2.
+  throttle_data->RecordSuccess();
+  // Failure: token_count=2.2.  Above threshold.
+  EXPECT_TRUE(throttle_data->RecordFailure());
+  // Failure: token_count=1.2.  Below threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=2.8.
+  throttle_data->RecordSuccess();
+  // Failure: token_count=1.8.  Below threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=3.4.
+  throttle_data->RecordSuccess();
+  // Failure: token_count=2.4.  Above threshold.
+  EXPECT_TRUE(throttle_data->RecordFailure());
+}
+
+TEST(ServerRetryThrottleData, Replacement) {
+  // Create old throttle data.
+  // Max token count is 4, so threshold for retrying is 2.
+  // Token count starts at 4.
+  // Each failure decrements by 1.  Each success increments by 1.
+  auto old_throttle_data =
+      MakeRefCounted<ServerRetryThrottleData>(4000, 1000, nullptr);
+  // Failure: token_count=3.  Above threshold.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Create new throttle data.
+  // Max token count is 10, so threshold for retrying is 5.
+  // Token count starts at 7.5 (ratio inherited from old_throttle_data).
+  // Each failure decrements by 1.  Each success increments by 3.
+  auto throttle_data = MakeRefCounted<ServerRetryThrottleData>(
+      10000, 3000, old_throttle_data.get());
+  // Failure via old_throttle_data: token_count=6.5.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure: token_count=5.5.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure via old_throttle_data: token_count=4.5.  Below threshold.
+  EXPECT_FALSE(old_throttle_data->RecordFailure());
+  // Failure: token_count=3.5.  Below threshold.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=6.5.
+  throttle_data->RecordSuccess();
+  // Failure via old_throttle_data: token_count=5.5.  Above threshold.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure: token_count=4.5.  Below threshold.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+}
+
+TEST(ServerRetryThrottleMap, Replacement) {
+  ServerRetryThrottleMap::Init();
+  const char kServerName[] = "server_name";
+  // Create old throttle data.
+  // Max token count is 4, so threshold for retrying is 2.
+  // Token count starts at 4.
+  // Each failure decrements by 1.  Each success increments by 1.
+  auto old_throttle_data =
+      ServerRetryThrottleMap::GetDataForServer(kServerName, 4000, 1000);
+  // Failure: token_count=3.  Above threshold.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Create new throttle data.
+  // Max token count is 10, so threshold for retrying is 5.
+  // Token count starts at 7.5 (ratio inherited from old_throttle_data).
+  // Each failure decrements by 1.  Each success increments by 3.
+  auto throttle_data =
+      ServerRetryThrottleMap::GetDataForServer(kServerName, 10000, 3000);
+  // Failure via old_throttle_data: token_count=6.5.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure: token_count=5.5.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure via old_throttle_data: token_count=4.5.  Below threshold.
+  EXPECT_FALSE(old_throttle_data->RecordFailure());
+  // Failure: token_count=3.5.  Below threshold.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=6.5.
+  throttle_data->RecordSuccess();
+  // Failure via old_throttle_data: token_count=5.5.  Above threshold.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure: token_count=4.5.  Below threshold.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Clean up.
+  ServerRetryThrottleMap::Shutdown();
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  grpc_test_init(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc
index 78ddcdb..297408c 100644
--- a/test/core/end2end/end2end_nosec_tests.cc
+++ b/test/core/end2end/end2end_nosec_tests.cc
@@ -38,6 +38,8 @@
 extern void bad_ping_pre_init(void);
 extern void binary_metadata(grpc_end2end_test_config config);
 extern void binary_metadata_pre_init(void);
+extern void call_host_override(grpc_end2end_test_config config);
+extern void call_host_override_pre_init(void);
 extern void cancel_after_accept(grpc_end2end_test_config config);
 extern void cancel_after_accept_pre_init(void);
 extern void cancel_after_client_done(grpc_end2end_test_config config);
@@ -187,6 +189,7 @@
   bad_hostname_pre_init();
   bad_ping_pre_init();
   binary_metadata_pre_init();
+  call_host_override_pre_init();
   cancel_after_accept_pre_init();
   cancel_after_client_done_pre_init();
   cancel_after_invoke_pre_init();
@@ -270,6 +273,7 @@
     bad_hostname(config);
     bad_ping(config);
     binary_metadata(config);
+    call_host_override(config);
     cancel_after_accept(config);
     cancel_after_client_done(config);
     cancel_after_invoke(config);
@@ -360,6 +364,10 @@
       binary_metadata(config);
       continue;
     }
+    if (0 == strcmp("call_host_override", argv[i])) {
+      call_host_override(config);
+      continue;
+    }
     if (0 == strcmp("cancel_after_accept", argv[i])) {
       cancel_after_accept(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc
index fb1e61b..9b3f655 100644
--- a/test/core/end2end/end2end_tests.cc
+++ b/test/core/end2end/end2end_tests.cc
@@ -40,6 +40,8 @@
 extern void binary_metadata_pre_init(void);
 extern void call_creds(grpc_end2end_test_config config);
 extern void call_creds_pre_init(void);
+extern void call_host_override(grpc_end2end_test_config config);
+extern void call_host_override_pre_init(void);
 extern void cancel_after_accept(grpc_end2end_test_config config);
 extern void cancel_after_accept_pre_init(void);
 extern void cancel_after_client_done(grpc_end2end_test_config config);
@@ -190,6 +192,7 @@
   bad_ping_pre_init();
   binary_metadata_pre_init();
   call_creds_pre_init();
+  call_host_override_pre_init();
   cancel_after_accept_pre_init();
   cancel_after_client_done_pre_init();
   cancel_after_invoke_pre_init();
@@ -274,6 +277,7 @@
     bad_ping(config);
     binary_metadata(config);
     call_creds(config);
+    call_host_override(config);
     cancel_after_accept(config);
     cancel_after_client_done(config);
     cancel_after_invoke(config);
@@ -368,6 +372,10 @@
       call_creds(config);
       continue;
     }
+    if (0 == strcmp("call_host_override", argv[i])) {
+      call_host_override(config);
+      continue;
+    }
     if (0 == strcmp("cancel_after_accept", argv[i])) {
       cancel_after_accept(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h
index b42d90b..a1ebded 100644
--- a/test/core/end2end/end2end_tests.h
+++ b/test/core/end2end/end2end_tests.h
@@ -52,6 +52,11 @@
   /* Which features are supported by this fixture. See feature flags above. */
   uint32_t feature_mask;
 
+  /* If the call host is setup by the fixture (for example, via the
+   * GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg), which value should the test
+   * expect to find in call_details.host */
+  const char* overridden_call_host;
+
   grpc_end2end_test_fixture (*create_fixture)(grpc_channel_args* client_args,
                                               grpc_channel_args* server_args);
   void (*init_client)(grpc_end2end_test_fixture* f,
diff --git a/test/core/end2end/fixtures/h2_census.cc b/test/core/end2end/fixtures/h2_census.cc
index b3b4171..29b1d6d 100644
--- a/test/core/end2end/fixtures/h2_census.cc
+++ b/test/core/end2end/fixtures/h2_census.cc
@@ -111,7 +111,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_compress.cc b/test/core/end2end/fixtures/h2_compress.cc
index 565c96c..4aaadf7 100644
--- a/test/core/end2end/fixtures/h2_compress.cc
+++ b/test/core/end2end/fixtures/h2_compress.cc
@@ -109,7 +109,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack_compression,
+     nullptr, chttp2_create_fixture_fullstack_compression,
      chttp2_init_client_fullstack_compression,
      chttp2_init_server_fullstack_compression,
      chttp2_tear_down_fullstack_compression},
diff --git a/test/core/end2end/fixtures/h2_fakesec.cc b/test/core/end2end/fixtures/h2_fakesec.cc
index bbf65fc..a653d7c 100644
--- a/test/core/end2end/fixtures/h2_fakesec.cc
+++ b/test/core/end2end/fixtures/h2_fakesec.cc
@@ -132,10 +132,9 @@
 static grpc_end2end_test_config configs[] = {
     {"chttp2/fake_secure_fullstack",
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-         FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_secure_fullstack,
+     nullptr, chttp2_create_fixture_secure_fullstack,
      chttp2_init_client_fake_secure_fullstack,
      chttp2_init_server_fake_secure_fullstack,
      chttp2_tear_down_secure_fullstack},
diff --git a/test/core/end2end/fixtures/h2_fd.cc b/test/core/end2end/fixtures/h2_fd.cc
index 9157ab0..52be0f7 100644
--- a/test/core/end2end/fixtures/h2_fd.cc
+++ b/test/core/end2end/fixtures/h2_fd.cc
@@ -96,7 +96,7 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fd", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fd", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
      chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
      chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
 };
diff --git a/test/core/end2end/fixtures/h2_full+pipe.cc b/test/core/end2end/fixtures/h2_full+pipe.cc
index ed173c1..c532964 100644
--- a/test/core/end2end/fixtures/h2_full+pipe.cc
+++ b/test/core/end2end/fixtures/h2_full+pipe.cc
@@ -96,7 +96,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_full+trace.cc b/test/core/end2end/fixtures/h2_full+trace.cc
index afb86ea..ba7a780 100644
--- a/test/core/end2end/fixtures/h2_full+trace.cc
+++ b/test/core/end2end/fixtures/h2_full+trace.cc
@@ -96,7 +96,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_full+workarounds.cc b/test/core/end2end/fixtures/h2_full+workarounds.cc
index bd9ddff..78da841 100644
--- a/test/core/end2end/fixtures/h2_full+workarounds.cc
+++ b/test/core/end2end/fixtures/h2_full+workarounds.cc
@@ -107,7 +107,7 @@
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER |
          FEATURE_MASK_SUPPORTS_WORKAROUNDS,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_full.cc b/test/core/end2end/fixtures/h2_full.cc
index ca61ec8..0c826b6 100644
--- a/test/core/end2end/fixtures/h2_full.cc
+++ b/test/core/end2end/fixtures/h2_full.cc
@@ -90,7 +90,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_http_proxy.cc b/test/core/end2end/fixtures/h2_http_proxy.cc
index 90d0627..0af8a29 100644
--- a/test/core/end2end/fixtures/h2_http_proxy.cc
+++ b/test/core/end2end/fixtures/h2_http_proxy.cc
@@ -113,7 +113,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_load_reporting.cc b/test/core/end2end/fixtures/h2_load_reporting.cc
index ec9eedb..18ea10a 100644
--- a/test/core/end2end/fixtures/h2_load_reporting.cc
+++ b/test/core/end2end/fixtures/h2_load_reporting.cc
@@ -98,8 +98,9 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_load_reporting, chttp2_init_client_load_reporting,
-     chttp2_init_server_load_reporting, chttp2_tear_down_load_reporting},
+     nullptr, chttp2_create_fixture_load_reporting,
+     chttp2_init_client_load_reporting, chttp2_init_server_load_reporting,
+     chttp2_tear_down_load_reporting},
 };
 
 int main(int argc, char** argv) {
diff --git a/test/core/end2end/fixtures/h2_oauth2.cc b/test/core/end2end/fixtures/h2_oauth2.cc
index 9453f2f..d44aafd 100644
--- a/test/core/end2end/fixtures/h2_oauth2.cc
+++ b/test/core/end2end/fixtures/h2_oauth2.cc
@@ -216,7 +216,7 @@
          FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_secure_fullstack,
+     "foo.test.google.fr", chttp2_create_fixture_secure_fullstack,
      chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack,
      chttp2_init_server_simple_ssl_secure_fullstack,
      chttp2_tear_down_secure_fullstack},
diff --git a/test/core/end2end/fixtures/h2_proxy.cc b/test/core/end2end/fixtures/h2_proxy.cc
index c97188f..a320000 100644
--- a/test/core/end2end/fixtures/h2_proxy.cc
+++ b/test/core/end2end/fixtures/h2_proxy.cc
@@ -117,7 +117,7 @@
          FEATURE_MASK_SUPPORTS_REQUEST_PROXYING |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.cc b/test/core/end2end/fixtures/h2_sockpair+trace.cc
index d539dda..cdefcf4 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.cc
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.cc
@@ -63,9 +63,14 @@
 
 static void client_setup_transport(void* ts, grpc_transport* transport) {
   sp_client_setup* cs = static_cast<sp_client_setup*>(ts);
-
-  cs->f->client = grpc_channel_create("socketpair-target", cs->client_args,
+  grpc_arg authority_arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+      const_cast<char*>("test-authority"));
+  grpc_channel_args* args =
+      grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1);
+  cs->f->client = grpc_channel_create("socketpair-target", args,
                                       GRPC_CLIENT_DIRECT_CHANNEL, transport);
+  grpc_channel_args_destroy(args);
 }
 
 static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
@@ -118,7 +123,7 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
      chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
      chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
 };
diff --git a/test/core/end2end/fixtures/h2_sockpair.cc b/test/core/end2end/fixtures/h2_sockpair.cc
index 75f6402..8966cb3 100644
--- a/test/core/end2end/fixtures/h2_sockpair.cc
+++ b/test/core/end2end/fixtures/h2_sockpair.cc
@@ -58,8 +58,14 @@
 static void client_setup_transport(void* ts, grpc_transport* transport) {
   sp_client_setup* cs = static_cast<sp_client_setup*>(ts);
 
-  cs->f->client = grpc_channel_create("socketpair-target", cs->client_args,
+  grpc_arg authority_arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+      const_cast<char*>("test-authority"));
+  grpc_channel_args* args =
+      grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1);
+  cs->f->client = grpc_channel_create("socketpair-target", args,
                                       GRPC_CLIENT_DIRECT_CHANNEL, transport);
+  grpc_channel_args_destroy(args);
 }
 
 static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
@@ -112,7 +118,7 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
      chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
      chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
 };
diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.cc b/test/core/end2end/fixtures/h2_sockpair_1byte.cc
index 9296319..ebf4162 100644
--- a/test/core/end2end/fixtures/h2_sockpair_1byte.cc
+++ b/test/core/end2end/fixtures/h2_sockpair_1byte.cc
@@ -58,8 +58,14 @@
 static void client_setup_transport(void* ts, grpc_transport* transport) {
   sp_client_setup* cs = static_cast<sp_client_setup*>(ts);
 
-  cs->f->client = grpc_channel_create("socketpair-target", cs->client_args,
+  grpc_arg authority_arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+      const_cast<char*>("test-authority"));
+  grpc_channel_args* args =
+      grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1);
+  cs->f->client = grpc_channel_create("socketpair-target", args,
                                       GRPC_CLIENT_DIRECT_CHANNEL, transport);
+  grpc_channel_args_destroy(args);
 }
 
 static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
@@ -124,9 +130,9 @@
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
     {"chttp2/socketpair_one_byte_at_a_time",
-     FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, chttp2_create_fixture_socketpair,
-     chttp2_init_client_socketpair, chttp2_init_server_socketpair,
-     chttp2_tear_down_socketpair},
+     FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
+     chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
+     chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
 };
 
 int main(int argc, char** argv) {
diff --git a/test/core/end2end/fixtures/h2_ssl.cc b/test/core/end2end/fixtures/h2_ssl.cc
index bbcc88e..999cd4c 100644
--- a/test/core/end2end/fixtures/h2_ssl.cc
+++ b/test/core/end2end/fixtures/h2_ssl.cc
@@ -109,10 +109,7 @@
   grpc_channel_args* new_client_args =
       grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);
   chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds);
-  {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_channel_args_destroy(new_client_args);
-  }
+  grpc_channel_args_destroy(new_client_args);
 }
 
 static int fail_server_auth_check(grpc_channel_args* server_args) {
@@ -149,7 +146,7 @@
          FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_secure_fullstack,
+     "foo.test.google.fr", chttp2_create_fixture_secure_fullstack,
      chttp2_init_client_simple_ssl_secure_fullstack,
      chttp2_init_server_simple_ssl_secure_fullstack,
      chttp2_tear_down_secure_fullstack},
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.cc b/test/core/end2end/fixtures/h2_ssl_proxy.cc
index 6b0b891..9ab50c6 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.cc
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.cc
@@ -187,7 +187,7 @@
          FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_secure_fullstack,
+     "foo.test.google.fr", chttp2_create_fixture_secure_fullstack,
      chttp2_init_client_simple_ssl_secure_fullstack,
      chttp2_init_server_simple_ssl_secure_fullstack,
      chttp2_tear_down_secure_fullstack},
diff --git a/test/core/end2end/fixtures/h2_uds.cc b/test/core/end2end/fixtures/h2_uds.cc
index 1b081f9..2c81c3d 100644
--- a/test/core/end2end/fixtures/h2_uds.cc
+++ b/test/core/end2end/fixtures/h2_uds.cc
@@ -95,7 +95,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/inproc.cc b/test/core/end2end/fixtures/inproc.cc
index d47de42..be6eda8 100644
--- a/test/core/end2end/fixtures/inproc.cc
+++ b/test/core/end2end/fixtures/inproc.cc
@@ -75,8 +75,9 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"inproc", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, inproc_create_fixture,
-     inproc_init_client, inproc_init_server, inproc_tear_down},
+    {"inproc", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
+     inproc_create_fixture, inproc_init_client, inproc_init_server,
+     inproc_tear_down},
 };
 
 int main(int argc, char** argv) {
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5406804084260864 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5406804084260864
new file mode 100644
index 0000000..121aac7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5406804084260864
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5471994809155584 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5471994809155584
new file mode 100644
index 0000000..e5d3d38
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5471994809155584
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-6609852341157888 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-6609852341157888
new file mode 100644
index 0000000..b7debab
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-6609852341157888
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer.cc b/test/core/end2end/fuzzers/client_fuzzer.cc
index 16acf8e..e21006b 100644
--- a/test/core/end2end/fuzzers/client_fuzzer.cc
+++ b/test/core/end2end/fuzzers/client_fuzzer.cc
@@ -20,6 +20,7 @@
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
 
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/iomgr/executor.h"
@@ -58,8 +59,14 @@
         grpc_create_chttp2_transport(nullptr, mock_endpoint, true);
     grpc_chttp2_transport_start_reading(transport, nullptr, nullptr);
 
+    grpc_arg authority_arg = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+        const_cast<char*>("test-authority"));
+    grpc_channel_args* args =
+        grpc_channel_args_copy_and_add(nullptr, &authority_arg, 1);
     grpc_channel* channel = grpc_channel_create(
-        "test-target", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, transport);
+        "test-target", args, GRPC_CLIENT_DIRECT_CHANNEL, transport);
+    grpc_channel_args_destroy(args);
     grpc_slice host = grpc_slice_from_static_string("localhost");
     grpc_call* call = grpc_channel_create_call(
         channel, nullptr, 0, cq, grpc_slice_from_static_string("/foo"), &host,
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 4e20b0b..c7b03625 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -108,6 +108,8 @@
         proxyable=False, cpu_cost=LOWCPU, exclude_iomgrs=['uv']),
     'default_host': default_test_options._replace(
         needs_fullstack=True, needs_dns=True, needs_names=True),
+    'call_host_override': default_test_options._replace(
+        needs_fullstack=True, needs_dns=True, needs_names=True),
     'disappearing_server': connectivity_test_options._replace(flaky=True,
                                                               needs_names=True),
     'empty_batch': default_test_options._replace(cpu_cost=LOWCPU),
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 8e723fd..37fd183 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -101,6 +101,8 @@
     'binary_metadata': test_options(),
     'resource_quota_server': test_options(proxyable=False),
     'call_creds': test_options(secure=True),
+    'call_host_override': test_options(needs_fullstack=True, needs_dns=True,
+                                       needs_names=True),
     'cancel_after_accept': test_options(),
     'cancel_after_client_done': test_options(),
     'cancel_after_invoke': test_options(),
diff --git a/test/core/end2end/h2_ssl_cert_test.cc b/test/core/end2end/h2_ssl_cert_test.cc
index 9e2082c..9ed6f23 100644
--- a/test/core/end2end/h2_ssl_cert_test.cc
+++ b/test/core/end2end/h2_ssl_cert_test.cc
@@ -57,8 +57,6 @@
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
-  f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
-
   return f;
 }
 
@@ -202,6 +200,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |       \
          FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | \
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL,        \
+     "foo.test.google.fr",                            \
      chttp2_create_fixture_secure_fullstack,          \
      CLIENT_INIT_NAME(cert_type),                     \
      SERVER_INIT_NAME(request_type),                  \
@@ -270,27 +269,13 @@
   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
 }
 
+// Shuts down the server.
+// Side effect - Also shuts down and drains the completion queue.
 static void shutdown_server(grpc_end2end_test_fixture* f) {
   if (!f->server) return;
-  /* Perform a completion queue next, so that any pending operations can be
-   * finished, and resources can be released. This is so that, shutdown does not
-   * hang. For example, the server might be stuck in the handshaking code, which
-   * keeps a ref to a listener. Unless, it is unref'd, shutdown won't be able
-   * to proceed.
-   *
-   * (If shutdown times out, it is probably because 100ms wasn't enough. In that
-   * case, the deadline can be increased. Or, we could simply have another
-   * thread for the server to poll the completion queue while the shutdown
-   * progresses.)
-   */
-  GPR_ASSERT(grpc_completion_queue_next(
-                 f->cq, grpc_timeout_milliseconds_to_deadline(100), nullptr)
-                 .type == GRPC_QUEUE_TIMEOUT);
-  grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
-                                         grpc_timeout_seconds_to_deadline(5),
-                                         nullptr)
-                 .type == GRPC_OP_COMPLETE);
+  grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
   grpc_server_destroy(f->server);
   f->server = nullptr;
 }
@@ -304,11 +289,7 @@
 static void end_test(grpc_end2end_test_fixture* f) {
   shutdown_client(f);
   shutdown_server(f);
-
-  grpc_completion_queue_shutdown(f->cq);
-  drain_cq(f->cq);
   grpc_completion_queue_destroy(f->cq);
-  grpc_completion_queue_destroy(f->shutdown_cq);
 }
 
 static void simple_request_body(grpc_end2end_test_fixture f,
diff --git a/test/core/end2end/tests/bad_ping.cc b/test/core/end2end/tests/bad_ping.cc
index 239c608..22481d1 100644
--- a/test/core/end2end/tests/bad_ping.cc
+++ b/test/core/end2end/tests/bad_ping.cc
@@ -108,11 +108,9 @@
   grpc_slice details;
   int was_cancelled = 2;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -207,8 +205,6 @@
   // the in-progress RPC should fail.
   GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -271,11 +267,9 @@
   grpc_slice details;
   int was_cancelled = 2;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -368,8 +362,6 @@
   // The rpc should be successful.
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/binary_metadata.cc b/test/core/end2end/tests/binary_metadata.cc
index e66b4da..cdf5b1e 100644
--- a/test/core/end2end/tests/binary_metadata.cc
+++ b/test/core/end2end/tests/binary_metadata.cc
@@ -136,11 +136,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -278,8 +276,6 @@
           "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
           "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
diff --git a/test/core/end2end/tests/call_creds.cc b/test/core/end2end/tests/call_creds.cc
index e9cbaa3..ead6ecb 100644
--- a/test/core/end2end/tests/call_creds.cc
+++ b/test/core/end2end/tests/call_creds.cc
@@ -156,11 +156,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
   creds = grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr);
   GPR_ASSERT(creds != nullptr);
@@ -292,8 +290,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
@@ -396,11 +392,9 @@
   f = begin_test(config, "test_request_with_server_rejecting_client_creds", 1);
   cqv = cq_verifier_create(f.cq);
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   creds = grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr);
diff --git a/test/core/end2end/tests/call_host_override.cc b/test/core/end2end/tests/call_host_override.cc
new file mode 100644
index 0000000..251dc6d
--- /dev/null
+++ b/test/core/end2end/tests/call_host_override.cc
@@ -0,0 +1,230 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "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/time.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/string.h"
+#include "test/core/end2end/cq_verifier.h"
+
+static void* tag(intptr_t t) { return (void*)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char* test_name,
+                                            grpc_channel_args* client_args,
+                                            grpc_channel_args* server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  grpc_arg fake_security_name_override = {
+      GRPC_ARG_STRING,
+      const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
+      {const_cast<char*>("foo.test.google.fr:1234")}};
+  grpc_channel_args* new_client_args = grpc_channel_args_copy_and_add(
+      client_args, &fake_security_name_override, 1);
+  config.init_client(&f, new_client_args);
+  grpc_channel_args_destroy(new_client_args);
+  config.init_server(&f, server_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_from_now(int n) {
+  return grpc_timeout_seconds_to_deadline(n);
+}
+
+static gpr_timespec five_seconds_from_now(void) {
+  return n_seconds_from_now(5);
+}
+
+static void drain_cq(grpc_completion_queue* cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
+  } 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->shutdown_cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
+                                         grpc_timeout_seconds_to_deadline(5),
+                                         nullptr)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = nullptr;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture* f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = nullptr;
+}
+
+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);
+  grpc_completion_queue_destroy(f->shutdown_cq);
+}
+
+static void test_invoke_simple_request(grpc_end2end_test_config config) {
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
+  grpc_call* c;
+  grpc_call* s;
+  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_slice details;
+  int was_cancelled = 2;
+  char* peer;
+
+  gpr_timespec deadline = five_seconds_from_now();
+  c = grpc_channel_create_call(
+      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
+      nullptr);
+  GPR_ASSERT(c);
+
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer);
+  gpr_free(peer);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
+                                nullptr);
+  GPR_ASSERT(error == GRPC_CALL_OK);
+
+  error =
+      grpc_server_request_call(f.server, &s, &call_details,
+                               &request_metadata_recv, f.cq, f.cq, tag(101));
+  GPR_ASSERT(error == GRPC_CALL_OK);
+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+  cq_verify(cqv);
+
+  peer = grpc_call_get_peer(s);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "server_peer=%s", peer);
+  gpr_free(peer);
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "client_peer=%s", peer);
+  gpr_free(peer);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
+                                nullptr);
+  GPR_ASSERT(error == GRPC_CALL_OK);
+
+  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 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
+                                config);
+  GPR_ASSERT(was_cancelled == 1);
+
+  grpc_slice_unref(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  grpc_call_unref(c);
+  grpc_call_unref(s);
+
+  cq_verifier_destroy(cqv);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+void call_host_override(grpc_end2end_test_config config) {
+  test_invoke_simple_request(config);
+}
+
+void call_host_override_pre_init(void) {}
diff --git a/test/core/end2end/tests/cancel_after_accept.cc b/test/core/end2end/tests/cancel_after_accept.cc
index e94ea51..788d374 100644
--- a/test/core/end2end/tests/cancel_after_accept.cc
+++ b/test/core/end2end/tests/cancel_after_accept.cc
@@ -146,11 +146,9 @@
   gpr_timespec deadline = use_service_config
                               ? gpr_inf_future(GPR_CLOCK_MONOTONIC)
                               : five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/cancel_after_client_done.cc b/test/core/end2end/tests/cancel_after_client_done.cc
index 31c3ea6..6e93783 100644
--- a/test/core/end2end/tests/cancel_after_client_done.cc
+++ b/test/core/end2end/tests/cancel_after_client_done.cc
@@ -119,11 +119,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/cancel_after_invoke.cc b/test/core/end2end/tests/cancel_after_invoke.cc
index 72f7242..78009eb 100644
--- a/test/core/end2end/tests/cancel_after_invoke.cc
+++ b/test/core/end2end/tests/cancel_after_invoke.cc
@@ -113,11 +113,9 @@
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/cancel_after_round_trip.cc b/test/core/end2end/tests/cancel_after_round_trip.cc
index 4890b30..061b273 100644
--- a/test/core/end2end/tests/cancel_after_round_trip.cc
+++ b/test/core/end2end/tests/cancel_after_round_trip.cc
@@ -148,11 +148,9 @@
   gpr_timespec deadline = use_service_config
                               ? gpr_inf_future(GPR_CLOCK_MONOTONIC)
                               : five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/cancel_before_invoke.cc b/test/core/end2end/tests/cancel_before_invoke.cc
index c7d3ed5..abb2dbc 100644
--- a/test/core/end2end/tests/cancel_before_invoke.cc
+++ b/test/core/end2end/tests/cancel_before_invoke.cc
@@ -109,11 +109,9 @@
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c, nullptr));
diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.cc b/test/core/end2end/tests/cancel_in_a_vacuum.cc
index 6be2d69..4672e64 100644
--- a/test/core/end2end/tests/cancel_in_a_vacuum.cc
+++ b/test/core/end2end/tests/cancel_in_a_vacuum.cc
@@ -97,11 +97,9 @@
   cq_verifier* v_client = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr));
diff --git a/test/core/end2end/tests/cancel_with_status.cc b/test/core/end2end/tests/cancel_with_status.cc
index 887da85..2fc9d2f 100644
--- a/test/core/end2end/tests/cancel_with_status.cc
+++ b/test/core/end2end/tests/cancel_with_status.cc
@@ -104,11 +104,9 @@
   gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/compressed_payload.cc b/test/core/end2end/tests/compressed_payload.cc
index 85cfe16..178d68c 100644
--- a/test/core/end2end/tests/compressed_payload.cc
+++ b/test/core/end2end/tests/compressed_payload.cc
@@ -137,11 +137,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -239,8 +237,6 @@
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details));
   gpr_free(expected_details);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
@@ -320,11 +316,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -529,8 +523,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/default_host.cc b/test/core/end2end/tests/default_host.cc
index 3191f76..22c3102 100644
--- a/test/core/end2end/tests/default_host.cc
+++ b/test/core/end2end/tests/default_host.cc
@@ -85,7 +85,9 @@
   grpc_completion_queue_destroy(f->shutdown_cq);
 }
 
-static void simple_request_body(grpc_end2end_test_fixture f) {
+static void test_invoke_simple_request(grpc_end2end_test_config config) {
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
   grpc_call* c;
   grpc_call* s;
   cq_verifier* cqv = cq_verifier_create(f.cq);
@@ -191,7 +193,14 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9));
+
+  if (config.overridden_call_host != nullptr) {
+    validate_host_override_string(config.overridden_call_host,
+                                  call_details.host, config);
+  } else {
+    GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9) ||
+               grpc_slice_buf_start_eq(call_details.host, "127.0.0.1", 9));
+  }
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -204,22 +213,12 @@
   grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
-}
 
-static void test_invoke_simple_request(grpc_end2end_test_config config) {
-  grpc_end2end_test_fixture f;
-
-  f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
-  simple_request_body(f);
   end_test(&f);
   config.tear_down_data(&f);
 }
 
 void default_host(grpc_end2end_test_config config) {
-  if ((config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) == 0)
-    return;
-  if ((config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) == 0)
-    return;
   test_invoke_simple_request(config);
 }
 
diff --git a/test/core/end2end/tests/disappearing_server.cc b/test/core/end2end/tests/disappearing_server.cc
index d5b6f8f..fdd780f 100644
--- a/test/core/end2end/tests/disappearing_server.cc
+++ b/test/core/end2end/tests/disappearing_server.cc
@@ -85,11 +85,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f->client, nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f->client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                               f->cq, grpc_slice_from_static_string("/foo"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -167,8 +165,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/empty_batch.cc b/test/core/end2end/tests/empty_batch.cc
index 1de4b8f..317bb7a 100644
--- a/test/core/end2end/tests/empty_batch.cc
+++ b/test/core/end2end/tests/empty_batch.cc
@@ -93,11 +93,9 @@
   grpc_op* op = nullptr;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   error = grpc_call_start_batch(c, op, 0, tag(1), nullptr);
diff --git a/test/core/end2end/tests/filter_call_init_fails.cc b/test/core/end2end/tests/filter_call_init_fails.cc
index 6f72a18..ab96879 100644
--- a/test/core/end2end/tests/filter_call_init_fails.cc
+++ b/test/core/end2end/tests/filter_call_init_fails.cc
@@ -117,11 +117,9 @@
   grpc_slice details;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -213,11 +211,9 @@
   grpc_call_error error;
   grpc_slice details;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -304,11 +300,9 @@
   grpc_call_error error;
   grpc_slice details;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -364,11 +358,9 @@
   grpc_slice_unref(details);
   details = grpc_empty_slice();
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(2),
diff --git a/test/core/end2end/tests/filter_causes_close.cc b/test/core/end2end/tests/filter_causes_close.cc
index bc4cb86..a7f4268 100644
--- a/test/core/end2end/tests/filter_causes_close.cc
+++ b/test/core/end2end/tests/filter_causes_close.cc
@@ -111,11 +111,9 @@
   grpc_slice details;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/filter_latency.cc b/test/core/end2end/tests/filter_latency.cc
index 51f54c9..a89db7b 100644
--- a/test/core/end2end/tests/filter_latency.cc
+++ b/test/core/end2end/tests/filter_latency.cc
@@ -125,10 +125,9 @@
   const gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr", config), deadline, nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc
index 32cd954..ba3cbfa 100644
--- a/test/core/end2end/tests/filter_status_code.cc
+++ b/test/core/end2end/tests/filter_status_code.cc
@@ -126,10 +126,9 @@
   gpr_mu_unlock(&g_mu);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr", config), deadline, nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
   gpr_mu_lock(&g_mu);
   g_client_call_stack = grpc_call_get_call_stack(c);
diff --git a/test/core/end2end/tests/graceful_server_shutdown.cc b/test/core/end2end/tests/graceful_server_shutdown.cc
index 3ef414f..42f2d1a 100644
--- a/test/core/end2end/tests/graceful_server_shutdown.cc
+++ b/test/core/end2end/tests/graceful_server_shutdown.cc
@@ -99,11 +99,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = n_seconds_from_now(10);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -183,8 +181,6 @@
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/high_initial_seqno.cc b/test/core/end2end/tests/high_initial_seqno.cc
index 8767437..18e6ee9 100644
--- a/test/core/end2end/tests/high_initial_seqno.cc
+++ b/test/core/end2end/tests/high_initial_seqno.cc
@@ -104,11 +104,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -181,8 +179,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/hpack_size.cc b/test/core/end2end/tests/hpack_size.cc
index b4973684..7c51294 100644
--- a/test/core/end2end/tests/hpack_size.cc
+++ b/test/core/end2end/tests/hpack_size.cc
@@ -257,11 +257,9 @@
       grpc_slice_from_static_string(dragons[index % GPR_ARRAY_SIZE(dragons)]);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -335,8 +333,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/idempotent_request.cc b/test/core/end2end/tests/idempotent_request.cc
index 56be2d6..80908d5 100644
--- a/test/core/end2end/tests/idempotent_request.cc
+++ b/test/core/end2end/tests/idempotent_request.cc
@@ -104,11 +104,9 @@
   char* peer;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -195,8 +193,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/invoke_large_request.cc b/test/core/end2end/tests/invoke_large_request.cc
index 1aab34c..39d90ab 100644
--- a/test/core/end2end/tests/invoke_large_request.cc
+++ b/test/core/end2end/tests/invoke_large_request.cc
@@ -131,11 +131,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = n_seconds_from_now(30);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -237,8 +235,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc
index c0771b8..1ee5285 100644
--- a/test/core/end2end/tests/keepalive_timeout.cc
+++ b/test/core/end2end/tests/keepalive_timeout.cc
@@ -130,11 +130,9 @@
   grpc_set_disable_ping_ack(true);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -200,8 +198,6 @@
   GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "keepalive watchdog timeout"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   gpr_free(details_str);
   gpr_free(method_str);
diff --git a/test/core/end2end/tests/large_metadata.cc b/test/core/end2end/tests/large_metadata.cc
index da0615b..c7f72a1 100644
--- a/test/core/end2end/tests/large_metadata.cc
+++ b/test/core/end2end/tests/large_metadata.cc
@@ -114,11 +114,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   meta.key = grpc_slice_from_static_string("key");
@@ -220,8 +218,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(contains_metadata_slices(&request_metadata_recv,
diff --git a/test/core/end2end/tests/load_reporting_hook.cc b/test/core/end2end/tests/load_reporting_hook.cc
index 9e79d02..4324e9d 100644
--- a/test/core/end2end/tests/load_reporting_hook.cc
+++ b/test/core/end2end/tests/load_reporting_hook.cc
@@ -138,11 +138,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string(method_name),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string(method_name),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/max_concurrent_streams.cc b/test/core/end2end/tests/max_concurrent_streams.cc
index 789b3d4..86a8d22 100644
--- a/test/core/end2end/tests/max_concurrent_streams.cc
+++ b/test/core/end2end/tests/max_concurrent_streams.cc
@@ -100,11 +100,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -177,8 +175,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -248,17 +244,13 @@
   /* start two requests - ensuring that the second is not accepted until
      the first completes */
   deadline = n_seconds_from_now(1000);
-  c1 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/alpha"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c1 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/alpha"),
+                                nullptr, deadline, nullptr);
   GPR_ASSERT(c1);
-  c2 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/beta"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c2 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/beta"),
+                                nullptr, deadline, nullptr);
   GPR_ASSERT(c2);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
@@ -494,17 +486,13 @@
 
   /* start two requests - ensuring that the second is not accepted until
      the first completes */
-  c1 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/alpha"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      n_seconds_from_now(3), nullptr);
+  c1 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/alpha"),
+                                nullptr, n_seconds_from_now(3), nullptr);
   GPR_ASSERT(c1);
-  c2 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/beta"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      n_seconds_from_now(1000), nullptr);
+  c2 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/beta"),
+                                nullptr, n_seconds_from_now(1000), nullptr);
   GPR_ASSERT(c2);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
@@ -694,17 +682,13 @@
   /* start two requests - ensuring that the second is not accepted until
      the first completes , and the second request will timeout in the
      concurrent_list */
-  c1 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/alpha"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      n_seconds_from_now(1000), nullptr);
+  c1 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/alpha"),
+                                nullptr, n_seconds_from_now(1000), nullptr);
   GPR_ASSERT(c1);
-  c2 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/beta"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      n_seconds_from_now(3), nullptr);
+  c2 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/beta"),
+                                nullptr, n_seconds_from_now(3), nullptr);
   GPR_ASSERT(c2);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
diff --git a/test/core/end2end/tests/max_connection_age.cc b/test/core/end2end/tests/max_connection_age.cc
index e494dad..fcb0aaf 100644
--- a/test/core/end2end/tests/max_connection_age.cc
+++ b/test/core/end2end/tests/max_connection_age.cc
@@ -109,11 +109,9 @@
   grpc_slice details;
   int was_cancelled = 2;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -208,8 +206,6 @@
      the in-progress RPC should fail. */
   GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -255,11 +251,9 @@
   grpc_slice details;
   int was_cancelled = 2;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -348,8 +342,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/max_connection_idle.cc b/test/core/end2end/tests/max_connection_idle.cc
index 2f212b9..faa1383 100644
--- a/test/core/end2end/tests/max_connection_idle.cc
+++ b/test/core/end2end/tests/max_connection_idle.cc
@@ -60,11 +60,9 @@
   char* peer;
 
   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
-  c = grpc_channel_create_call(
-      f->client, nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f->client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                               f->cq, grpc_slice_from_static_string("/foo"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -151,8 +149,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/max_message_length.cc b/test/core/end2end/tests/max_message_length.cc
index fa5b3b6..6ac941e 100644
--- a/test/core/end2end/tests/max_message_length.cc
+++ b/test/core/end2end/tests/max_message_length.cc
@@ -180,11 +180,10 @@
 
   cqv = cq_verifier_create(f.cq);
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, gpr_inf_future(GPR_CLOCK_REALTIME),
+                               nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -258,8 +257,6 @@
   cq_verify(cqv);
 
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
 done:
@@ -371,11 +368,10 @@
   }
   cqv = cq_verifier_create(f.cq);
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, gpr_inf_future(GPR_CLOCK_REALTIME),
+                               nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -456,9 +452,6 @@
   cq_verify(cqv);
 
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  GPR_ASSERT(0 ==
-             grpc_slice_str_cmp(call_details.host, "foo.test.google.fr:1234"));
-
   GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED);
   GPR_ASSERT(
       grpc_slice_str_cmp(
diff --git a/test/core/end2end/tests/negative_deadline.cc b/test/core/end2end/tests/negative_deadline.cc
index dce3a02..2b2ff12 100644
--- a/test/core/end2end/tests/negative_deadline.cc
+++ b/test/core/end2end/tests/negative_deadline.cc
@@ -101,11 +101,9 @@
   gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
 
   gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_REALTIME);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/network_status_change.cc b/test/core/end2end/tests/network_status_change.cc
index 83cb172..98a9558 100644
--- a/test/core/end2end/tests/network_status_change.cc
+++ b/test/core/end2end/tests/network_status_change.cc
@@ -110,11 +110,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -209,8 +207,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
 
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/no_logging.cc b/test/core/end2end/tests/no_logging.cc
index b357e3b..c815402 100644
--- a/test/core/end2end/tests/no_logging.cc
+++ b/test/core/end2end/tests/no_logging.cc
@@ -131,11 +131,9 @@
   char* peer;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -219,8 +217,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/payload.cc b/test/core/end2end/tests/payload.cc
index 340c76e..cb6eb47 100644
--- a/test/core/end2end/tests/payload.cc
+++ b/test/core/end2end/tests/payload.cc
@@ -129,11 +129,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = n_seconds_from_now(60);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -235,8 +233,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice));
   GPR_ASSERT(
diff --git a/test/core/end2end/tests/ping_pong_streaming.cc b/test/core/end2end/tests/ping_pong_streaming.cc
index 9ca8804..30ee0bf 100644
--- a/test/core/end2end/tests/ping_pong_streaming.cc
+++ b/test/core/end2end/tests/ping_pong_streaming.cc
@@ -112,11 +112,9 @@
       grpc_slice_from_copied_string("hello you");
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/proxy_auth.cc b/test/core/end2end/tests/proxy_auth.cc
index 5a2e0ef..3b12869 100644
--- a/test/core/end2end/tests/proxy_auth.cc
+++ b/test/core/end2end/tests/proxy_auth.cc
@@ -108,11 +108,9 @@
   char* peer;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -199,8 +197,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/registered_call.cc b/test/core/end2end/tests/registered_call.cc
index d4ca146..3e05fd1 100644
--- a/test/core/end2end/tests/registered_call.cc
+++ b/test/core/end2end/tests/registered_call.cc
@@ -177,8 +177,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -196,9 +194,7 @@
 static void test_invoke_simple_request(grpc_end2end_test_config config) {
   grpc_end2end_test_fixture f =
       begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
-  void* rc = grpc_channel_register_call(
-      f.client, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), nullptr);
+  void* rc = grpc_channel_register_call(f.client, "/foo", nullptr, nullptr);
 
   simple_request_body(config, f, rc);
   end_test(&f);
@@ -209,9 +205,7 @@
   int i;
   grpc_end2end_test_fixture f =
       begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr);
-  void* rc = grpc_channel_register_call(
-      f.client, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), nullptr);
+  void* rc = grpc_channel_register_call(f.client, "/foo", nullptr, nullptr);
 
   for (i = 0; i < 10; i++) {
     simple_request_body(config, f, rc);
diff --git a/test/core/end2end/tests/request_with_flags.cc b/test/core/end2end/tests/request_with_flags.cc
index c524824..f3baf37 100644
--- a/test/core/end2end/tests/request_with_flags.cc
+++ b/test/core/end2end/tests/request_with_flags.cc
@@ -108,11 +108,9 @@
   grpc_call_error expectation;
 
   gpr_timespec deadline = one_second_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/request_with_payload.cc b/test/core/end2end/tests/request_with_payload.cc
index 44398df..37d9481 100644
--- a/test/core/end2end/tests/request_with_payload.cc
+++ b/test/core/end2end/tests/request_with_payload.cc
@@ -107,11 +107,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -202,8 +200,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
 
diff --git a/test/core/end2end/tests/resource_quota_server.cc b/test/core/end2end/tests/resource_quota_server.cc
index 33d6b4e..df83caa 100644
--- a/test/core/end2end/tests/resource_quota_server.cc
+++ b/test/core/end2end/tests/resource_quota_server.cc
@@ -188,11 +188,10 @@
   }
 
   for (int i = 0; i < NUM_CALLS; i++) {
-    client_calls[i] = grpc_channel_create_call(
-        f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-        grpc_slice_from_static_string("/foo"),
-        get_host_override_slice("foo.test.google.fr", config),
-        n_seconds_from_now(60), nullptr);
+    client_calls[i] =
+        grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                 f.cq, grpc_slice_from_static_string("/foo"),
+                                 nullptr, n_seconds_from_now(60), nullptr);
 
     memset(ops, 0, sizeof(ops));
     op = ops;
diff --git a/test/core/end2end/tests/retry.cc b/test/core/end2end/tests/retry.cc
index 38ecc6f..243dedc 100644
--- a/test/core/end2end/tests/retry.cc
+++ b/test/core/end2end/tests/retry.cc
@@ -145,11 +145,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -293,8 +291,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 0);
 
diff --git a/test/core/end2end/tests/retry_cancellation.cc b/test/core/end2end/tests/retry_cancellation.cc
index 0504092..e764fe7 100644
--- a/test/core/end2end/tests/retry_cancellation.cc
+++ b/test/core/end2end/tests/retry_cancellation.cc
@@ -146,11 +146,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
diff --git a/test/core/end2end/tests/retry_disabled.cc b/test/core/end2end/tests/retry_disabled.cc
index cb30502..ed35354 100644
--- a/test/core/end2end/tests/retry_disabled.cc
+++ b/test/core/end2end/tests/retry_disabled.cc
@@ -149,11 +149,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -230,8 +228,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
index 3908f29..a033a0a 100644
--- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
+++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
@@ -152,11 +152,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -233,8 +231,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
index 409fac4..c1070e6 100644
--- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
+++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
@@ -157,11 +157,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -245,8 +243,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_non_retriable_status.cc b/test/core/end2end/tests/retry_non_retriable_status.cc
index 6d59db0..b8d0947 100644
--- a/test/core/end2end/tests/retry_non_retriable_status.cc
+++ b/test/core/end2end/tests/retry_non_retriable_status.cc
@@ -144,11 +144,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -225,8 +223,6 @@
   GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_recv_initial_metadata.cc b/test/core/end2end/tests/retry_recv_initial_metadata.cc
index 14215e4..839b870 100644
--- a/test/core/end2end/tests/retry_recv_initial_metadata.cc
+++ b/test/core/end2end/tests/retry_recv_initial_metadata.cc
@@ -145,11 +145,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -236,8 +234,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_recv_message.cc b/test/core/end2end/tests/retry_recv_message.cc
index 86171fd..5fdaad0 100644
--- a/test/core/end2end/tests/retry_recv_message.cc
+++ b/test/core/end2end/tests/retry_recv_message.cc
@@ -145,11 +145,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -229,8 +227,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_server_pushback_delay.cc b/test/core/end2end/tests/retry_server_pushback_delay.cc
index 1da9860..f6a9796 100644
--- a/test/core/end2end/tests/retry_server_pushback_delay.cc
+++ b/test/core/end2end/tests/retry_server_pushback_delay.cc
@@ -150,11 +150,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -286,8 +284,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 0);
 
diff --git a/test/core/end2end/tests/retry_server_pushback_disabled.cc b/test/core/end2end/tests/retry_server_pushback_disabled.cc
index 13d4f01..1c56476 100644
--- a/test/core/end2end/tests/retry_server_pushback_disabled.cc
+++ b/test/core/end2end/tests/retry_server_pushback_disabled.cc
@@ -151,11 +151,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -274,8 +272,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_streaming.cc b/test/core/end2end/tests/retry_streaming.cc
index e96e57e..d06d124 100644
--- a/test/core/end2end/tests/retry_streaming.cc
+++ b/test/core/end2end/tests/retry_streaming.cc
@@ -158,11 +158,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -383,8 +381,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_streaming_after_commit.cc b/test/core/end2end/tests/retry_streaming_after_commit.cc
index 43eee86..05025d0 100644
--- a/test/core/end2end/tests/retry_streaming_after_commit.cc
+++ b/test/core/end2end/tests/retry_streaming_after_commit.cc
@@ -151,11 +151,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -312,8 +310,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc b/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc
index 5c92f64..14460d2 100644
--- a/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc
+++ b/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc
@@ -152,11 +152,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -364,8 +362,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_throttled.cc b/test/core/end2end/tests/retry_throttled.cc
index 8cd0848..f5b28de 100644
--- a/test/core/end2end/tests/retry_throttled.cc
+++ b/test/core/end2end/tests/retry_throttled.cc
@@ -151,11 +151,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -232,8 +230,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_too_many_attempts.cc b/test/core/end2end/tests/retry_too_many_attempts.cc
index 5225c9b..2af3267 100644
--- a/test/core/end2end/tests/retry_too_many_attempts.cc
+++ b/test/core/end2end/tests/retry_too_many_attempts.cc
@@ -145,11 +145,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -267,8 +265,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/server_finishes_request.cc b/test/core/end2end/tests/server_finishes_request.cc
index 6fc06cf..c81b309 100644
--- a/test/core/end2end/tests/server_finishes_request.cc
+++ b/test/core/end2end/tests/server_finishes_request.cc
@@ -102,11 +102,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -175,8 +173,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/shutdown_finishes_calls.cc b/test/core/end2end/tests/shutdown_finishes_calls.cc
index 28728ef..5dd5bb2 100644
--- a/test/core/end2end/tests/shutdown_finishes_calls.cc
+++ b/test/core/end2end/tests/shutdown_finishes_calls.cc
@@ -92,11 +92,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -172,8 +170,6 @@
   GPR_ASSERT(status == GRPC_STATUS_INTERNAL ||
              status == GRPC_STATUS_UNAVAILABLE);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/simple_cacheable_request.cc b/test/core/end2end/tests/simple_cacheable_request.cc
index 4ae8398..be6d16e 100644
--- a/test/core/end2end/tests/simple_cacheable_request.cc
+++ b/test/core/end2end/tests/simple_cacheable_request.cc
@@ -132,11 +132,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -240,8 +238,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) {
     // Our simple proxy does not support cacheable requests
   } else {
diff --git a/test/core/end2end/tests/simple_delayed_request.cc b/test/core/end2end/tests/simple_delayed_request.cc
index f8a1ddf..8d11699 100644
--- a/test/core/end2end/tests/simple_delayed_request.cc
+++ b/test/core/end2end/tests/simple_delayed_request.cc
@@ -94,11 +94,9 @@
   config.init_server(f, server_args);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f->client, nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f->client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                               f->cq, grpc_slice_from_static_string("/foo"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -171,8 +169,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/simple_metadata.cc b/test/core/end2end/tests/simple_metadata.cc
index 1f39f89..3e476c2 100644
--- a/test/core/end2end/tests/simple_metadata.cc
+++ b/test/core/end2end/tests/simple_metadata.cc
@@ -130,11 +130,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -238,8 +236,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
diff --git a/test/core/end2end/tests/simple_request.cc b/test/core/end2end/tests/simple_request.cc
index 926e2c7..2d6ccad 100644
--- a/test/core/end2end/tests/simple_request.cc
+++ b/test/core/end2end/tests/simple_request.cc
@@ -111,11 +111,9 @@
   grpc_stats_collect(before);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -212,8 +210,6 @@
   GPR_ASSERT(nullptr != strstr(error_string, "grpc_message"));
   GPR_ASSERT(nullptr != strstr(error_string, "grpc_status"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/stream_compression_compressed_payload.cc b/test/core/end2end/tests/stream_compression_compressed_payload.cc
index e90d54f..839f091 100644
--- a/test/core/end2end/tests/stream_compression_compressed_payload.cc
+++ b/test/core/end2end/tests/stream_compression_compressed_payload.cc
@@ -137,11 +137,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -239,8 +237,6 @@
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details));
   gpr_free(expected_details);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
@@ -327,11 +323,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -529,8 +523,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/stream_compression_payload.cc b/test/core/end2end/tests/stream_compression_payload.cc
index 9eace97..4c08150 100644
--- a/test/core/end2end/tests/stream_compression_payload.cc
+++ b/test/core/end2end/tests/stream_compression_payload.cc
@@ -132,11 +132,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = n_seconds_from_now(60);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -238,8 +236,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice));
   GPR_ASSERT(
diff --git a/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc b/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
index 5b03329..f7af59f 100644
--- a/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
+++ b/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
@@ -120,11 +120,9 @@
       grpc_slice_from_copied_string("hello you");
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/streaming_error_response.cc b/test/core/end2end/tests/streaming_error_response.cc
index 7c7d778..4c357e0 100644
--- a/test/core/end2end/tests/streaming_error_response.cc
+++ b/test/core/end2end/tests/streaming_error_response.cc
@@ -116,11 +116,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -244,8 +242,6 @@
   GPR_ASSERT(status == GRPC_STATUS_FAILED_PRECONDITION);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/trailing_metadata.cc b/test/core/end2end/tests/trailing_metadata.cc
index 2406985..5cf6f2b 100644
--- a/test/core/end2end/tests/trailing_metadata.cc
+++ b/test/core/end2end/tests/trailing_metadata.cc
@@ -138,11 +138,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -247,8 +245,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
   GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1"));
diff --git a/test/core/end2end/tests/workaround_cronet_compression.cc b/test/core/end2end/tests/workaround_cronet_compression.cc
index 4d4c369..f44ddca 100644
--- a/test/core/end2end/tests/workaround_cronet_compression.cc
+++ b/test/core/end2end/tests/workaround_cronet_compression.cc
@@ -155,11 +155,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -338,8 +336,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/write_buffering.cc b/test/core/end2end/tests/write_buffering.cc
index 5d76d23..2f7ee9c 100644
--- a/test/core/end2end/tests/write_buffering.cc
+++ b/test/core/end2end/tests/write_buffering.cc
@@ -111,11 +111,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -255,8 +253,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123"));
diff --git a/test/core/end2end/tests/write_buffering_at_end.cc b/test/core/end2end/tests/write_buffering_at_end.cc
index bd046ef..886d491 100644
--- a/test/core/end2end/tests/write_buffering_at_end.cc
+++ b/test/core/end2end/tests/write_buffering_at_end.cc
@@ -108,11 +108,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -246,8 +244,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world"));
   GPR_ASSERT(request_payload_recv2 == nullptr);
diff --git a/test/core/surface/BUILD b/test/core/surface/BUILD
index e848dde..77df1cc 100644
--- a/test/core/surface/BUILD
+++ b/test/core/surface/BUILD
@@ -91,18 +91,6 @@
 )
 
 grpc_cc_test(
-    name = "grpc_invalid_channel_args_test",
-    srcs = ["invalid_channel_args_test.cc"],
-    language = "C++",
-    deps = [
-        "//:gpr",
-        "//:grpc",
-        "//test/core/util:gpr_test_util",
-        "//test/core/util:grpc_test_util",
-    ],
-)
-
-grpc_cc_test(
     name = "lame_client_test",
     srcs = ["lame_client_test.cc"],
     language = "C++",
diff --git a/test/core/surface/invalid_channel_args_test.cc b/test/core/surface/invalid_channel_args_test.cc
deleted file mode 100644
index 7c5f1f0..0000000
--- a/test/core/surface/invalid_channel_args_test.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <grpc/grpc.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include "test/core/util/test_config.h"
-
-static char* g_last_log_error_message = nullptr;
-static const char* g_file_name = "channel.cc";
-
-static int ends_with(const char* src, const char* suffix) {
-  size_t src_len = strlen(src);
-  size_t suffix_len = strlen(suffix);
-  if (src_len < suffix_len) {
-    return 0;
-  }
-  return strcmp(src + src_len - suffix_len, suffix) == 0;
-}
-
-static void log_error_sink(gpr_log_func_args* args) {
-  if (args->severity == GPR_LOG_SEVERITY_ERROR &&
-      ends_with(args->file, g_file_name)) {
-    g_last_log_error_message = gpr_strdup(args->message);
-  }
-}
-
-static void verify_last_error(const char* message) {
-  if (message == nullptr) {
-    GPR_ASSERT(g_last_log_error_message == nullptr);
-    return;
-  }
-  GPR_ASSERT(strcmp(message, g_last_log_error_message) == 0);
-  gpr_free(g_last_log_error_message);
-  g_last_log_error_message = nullptr;
-}
-
-static char* compose_error_string(const char* key, const char* message) {
-  char* ret;
-  gpr_asprintf(&ret, "%s%s", key, message);
-  return ret;
-}
-
-static void one_test(grpc_channel_args* args, char* expected_error_message) {
-  grpc_channel* chan =
-      grpc_insecure_channel_create("nonexistant:54321", args, nullptr);
-  verify_last_error(expected_error_message);
-  gpr_free(expected_error_message);
-  grpc_channel_destroy(chan);
-}
-
-static void test_no_error_message(void) { one_test(nullptr, nullptr); }
-
-static void test_default_authority_type(void) {
-  grpc_arg client_arg;
-  grpc_channel_args client_args;
-  char* expected_error_message;
-
-  client_arg.type = GRPC_ARG_INTEGER;
-  client_arg.key = const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY);
-  client_arg.value.integer = 0;
-
-  client_args.num_args = 1;
-  client_args.args = &client_arg;
-  expected_error_message = compose_error_string(
-      GRPC_ARG_DEFAULT_AUTHORITY, " ignored: it must be a string");
-  one_test(&client_args, expected_error_message);
-}
-
-static void test_ssl_name_override_type(void) {
-  grpc_arg client_arg;
-  grpc_channel_args client_args;
-  char* expected_error_message;
-
-  client_arg.type = GRPC_ARG_INTEGER;
-  client_arg.key = const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-  client_arg.value.integer = 0;
-
-  client_args.num_args = 1;
-  client_args.args = &client_arg;
-  expected_error_message = compose_error_string(
-      GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, " ignored: it must be a string");
-  one_test(&client_args, expected_error_message);
-}
-
-static void test_ssl_name_override_failed(void) {
-  grpc_arg client_arg[2];
-  grpc_channel_args client_args;
-  char* expected_error_message;
-
-  client_arg[0].type = GRPC_ARG_STRING;
-  client_arg[0].key = const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY);
-  client_arg[0].value.string = const_cast<char*>("default");
-  client_arg[1].type = GRPC_ARG_STRING;
-  client_arg[1].key = const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-  client_arg[1].value.string = const_cast<char*>("ssl");
-
-  client_args.num_args = 2;
-  client_args.args = client_arg;
-  expected_error_message =
-      compose_error_string(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
-                           " ignored: default host already set some other way");
-  one_test(&client_args, expected_error_message);
-}
-
-int main(int argc, char** argv) {
-  grpc_test_init(argc, argv);
-  grpc_init();
-  gpr_set_log_function(log_error_sink);
-
-  test_no_error_message();
-  test_default_authority_type();
-  test_ssl_name_override_type();
-  test_ssl_name_override_failed();
-
-  grpc_shutdown();
-
-  return 0;
-}
diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc
index bfdcd96..f4be064 100644
--- a/test/cpp/naming/resolver_component_test.cc
+++ b/test/cpp/naming/resolver_component_test.cc
@@ -65,11 +65,6 @@
               "List of expected backend or balancer addresses in the form "
               "'<ip0:port0>,<is_balancer0>;<ip1:port1>,<is_balancer1>;...'. "
               "'is_balancer' should be bool, i.e. true or false.");
-DEFINE_bool(allow_extra_addrs, false,
-            "Permit extra resolved addresses in the final list of "
-            "resolved addresses. This is useful in certain integration "
-            "test environments in which DNS responses are not fully "
-            "deterministic.");
 DEFINE_string(expected_chosen_service_config, "",
               "Expected service config json string that gets chosen (no "
               "whitespace). Empty for none.");
@@ -245,11 +240,9 @@
   GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
   grpc_lb_addresses* addresses =
       (grpc_lb_addresses*)channel_arg->value.pointer.p;
-  gpr_log(GPR_INFO,
-          "num addrs found: %" PRIdPTR ". expected %" PRIdPTR
-          ". Allow extra addresses:%d.",
-          addresses->num_addresses, args->expected_addrs.size(),
-          FLAGS_allow_extra_addrs);
+  gpr_log(GPR_INFO, "num addrs found: %" PRIdPTR ". expected %" PRIdPTR,
+          addresses->num_addresses, args->expected_addrs.size());
+  GPR_ASSERT(addresses->num_addresses == args->expected_addrs.size());
   std::vector<GrpcLBAddress> found_lb_addrs;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     grpc_lb_address addr = addresses->addresses[i];
@@ -261,20 +254,13 @@
     gpr_free(str);
   }
   if (args->expected_addrs.size() != found_lb_addrs.size()) {
-    // Permit extra resolved addresses if "--allow_extra_addrs" was set.
-    if (!(FLAGS_allow_extra_addrs &&
-          found_lb_addrs.size() > args->expected_addrs.size())) {
-      gpr_log(GPR_DEBUG,
-              "found lb addrs size is: %" PRIdPTR
-              ". expected addrs size is %" PRIdPTR ". --allow_extra_addrs=%d.",
-              found_lb_addrs.size(), args->expected_addrs.size(),
-              FLAGS_allow_extra_addrs);
-      abort();
-    }
+    gpr_log(GPR_DEBUG,
+            "found lb addrs size is: %" PRIdPTR
+            ". expected addrs size is %" PRIdPTR,
+            found_lb_addrs.size(), args->expected_addrs.size());
+    abort();
   }
-  for (size_t i = 0; i < args->expected_addrs.size(); i++) {
-    EXPECT_THAT(found_lb_addrs, ::testing::Contains(args->expected_addrs[i]));
-  }
+  EXPECT_THAT(args->expected_addrs, UnorderedElementsAreArray(found_lb_addrs));
   CheckServiceConfigResultLocked(channel_args, args);
   if (args->expected_service_config_string == "") {
     CheckLBPolicyResultLocked(channel_args, args);
diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.bat b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.bat
new file mode 100644
index 0000000..6f4d581
--- /dev/null
+++ b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.bat
@@ -0,0 +1,41 @@
+@rem Copyright 2016 gRPC authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem     http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+
+@rem enter this directory
+cd /d %~dp0\..\..\..
+
+@rem TODO(jtattermusch): Kokoro has pre-installed protoc.exe in C:\Program Files\ProtoC and that directory
+@rem is on PATH. To avoid picking up the older version protoc.exe, we change the path to something non-existent.
+set PATH=%PATH:ProtoC=DontPickupProtoC%
+
+@rem Download OpenSSL-Win32 originally installed from https://slproweb.com/products/Win32OpenSSL.html
+powershell -Command "(New-Object Net.WebClient).DownloadFile('https://storage.googleapis.com/grpc-testing.appspot.com/OpenSSL-Win32-1_1_0g.zip', 'OpenSSL-Win32.zip')"
+powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('OpenSSL-Win32.zip', '.');"
+
+@rem set absolute path to OpenSSL with forward slashes
+set OPENSSL_DIR=%cd:\=/%/OpenSSL-Win32
+
+@rem Build helloworld example using cmake
+@rem Use non-standard build directory to avoid too long filenames
+mkdir example_build
+cd example_build
+cmake -DOPENSSL_ROOT_DIR=%OPENSSL_DIR% ../examples/cpp/helloworld/cmake_externalproject || goto :error
+cmake --build . --config Release || goto :error
+cd ..
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b %errorlevel%
diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh
new file mode 100755
index 0000000..163527f
--- /dev/null
+++ b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex
+
+cd "$(dirname "$0")/../../.."
+
+echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list
+apt-get update
+apt-get install -t jessie-backports -y libssl-dev
+
+# To increase the confidence that gRPC installation works without depending on
+# too many submodules unnecessarily, just wipe out contents of most submodules
+# before starting the test.
+rm -r third_party/abseil-cpp/* || true
+rm -r third_party/benchmark/* || true
+rm -r third_party/bloaty/* || true
+rm -r third_party/boringssl/* || true
+rm -r third_party/boringssl-with-bazel/* || true
+rm -r third_party/gflags/* || true
+rm -r third_party/googletest/* || true
+
+# Build helloworld example using cmake superbuild
+cd examples/cpp/helloworld/cmake_externalproject
+mkdir -p cmake/build
+cd cmake/build
+cmake ../..
+make
+
diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_submodule.sh b/test/distrib/cpp/run_distrib_test_cmake_as_submodule.sh
new file mode 100755
index 0000000..defc63e
--- /dev/null
+++ b/test/distrib/cpp/run_distrib_test_cmake_as_submodule.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 2017 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -ex
+
+cd "$(dirname "$0")/../../.."
+
+# Build helloworld example using cmake, including grpc with "add_subdirectory"
+cd examples/cpp/helloworld
+mkdir -p cmake/build
+cd cmake/build
+cmake -DGRPC_AS_SUBMODULE=ON ../..
+make
diff --git a/test/distrib/ruby/run_distrib_test.sh b/test/distrib/ruby/run_distrib_test.sh
index 99fb873..cb2eb1f 100755
--- a/test/distrib/ruby/run_distrib_test.sh
+++ b/test/distrib/ruby/run_distrib_test.sh
@@ -35,3 +35,24 @@
 bundle install
 
 bundle exec ./distribtest.rb
+
+# Attempt to repro https://github.com/google/protobuf/issues/4210.
+# TODO: This sanity check only works for linux-based distrib tests and for
+# binary gRPC packages. It will need to be ran conditionally if this test script is
+# used for other types of distrib tests.
+INSTALLATION_DIR="$(gem env | grep '\- INSTALLATION DIRECTORY' | awk '{ print $4 }')"
+if [[ "$(find "$INSTALLATION_DIR" -name 'grpc_c.so' | wc -l)" == 0 ]]; then
+  echo "Sanity check failed. The gRPC package is not installed in $INSTALLATION_DIR."
+  exit 1
+fi
+LIBRUBY_DEPENDENCY_EXISTS="$(find "$INSTALLATION_DIR" -name 'grpc_c.so' -exec ldd {} \; | grep -c 'libruby')" || true
+if [[ "$LIBRUBY_DEPENDENCY_EXISTS" != 0 ]]; then
+  echo "A grpc_c.so file in this binary gRPC package is dynamically linked to libruby."
+fi
+DEPENDENCY_NOT_FOUND="$(find "$INSTALLATION_DIR" -name 'grpc_c.so' -exec ldd {} \; | grep -c 'not found')" || true
+if [[ "$DEPENDENCY_NOT_FOUND" != 0 ]]; then
+  echo "A grpc_c.so file in this binary gRPC package has an non-portable dependency."
+fi
+if [ "$LIBRUBY_DEPENDENCY_EXISTS" != 0 ] || [ "$DEPENDENCY_NOT_FOUND" != 0 ]; then
+  exit 1
+fi
diff --git a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
index 5ea5121..200c5c2 100644
--- a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
@@ -14,6 +14,6 @@
 
 FROM fedora:20
 
-RUN yum clean all && yum update -y && yum install -y ruby
+RUN yum clean all && yum update -y && yum install -y ruby findutils
 
 RUN gem install bundler
diff --git a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
index b903401..e1177fd 100644
--- a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
@@ -19,6 +19,6 @@
 # https://github.com/docker/docker/issues/10180
 RUN yum install -y yum-plugin-ovl
 
-RUN yum clean all && yum update -y && yum install -y ruby
+RUN yum clean all && yum update -y && yum install -y ruby findutils
 
 RUN gem install bundler
diff --git a/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
index 0d57370..848c5be 100644
--- a/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
@@ -14,6 +14,6 @@
 
 FROM fedora:22
 
-RUN yum clean all && yum update -y && yum install -y ruby
+RUN yum clean all && yum update -y && yum install -y ruby findutils
 
 RUN gem install bundler
diff --git a/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
index 318993b..47dd577 100644
--- a/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
@@ -14,6 +14,6 @@
 
 FROM fedora:23
 
-RUN yum clean all && yum update -y && yum install -y ruby
+RUN yum clean all && yum update -y && yum install -y ruby findutils
 
 RUN gem install bundler
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 85675e9..b5869a6 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -939,6 +939,8 @@
 src/core/ext/filters/deadline/deadline_filter.h \
 src/core/ext/filters/http/client/http_client_filter.cc \
 src/core/ext/filters/http/client/http_client_filter.h \
+src/core/ext/filters/http/client_authority_filter.cc \
+src/core/ext/filters/http/client_authority_filter.h \
 src/core/ext/filters/http/http_filters_plugin.cc \
 src/core/ext/filters/http/message_compress/message_compress_filter.cc \
 src/core/ext/filters/http/message_compress/message_compress_filter.h \
@@ -960,6 +962,8 @@
 src/core/ext/transport/chttp2/README.md \
 src/core/ext/transport/chttp2/alpn/alpn.cc \
 src/core/ext/transport/chttp2/alpn/alpn.h \
+src/core/ext/transport/chttp2/client/authority.cc \
+src/core/ext/transport/chttp2/client/authority.h \
 src/core/ext/transport/chttp2/client/chttp2_connector.cc \
 src/core/ext/transport/chttp2/client/chttp2_connector.h \
 src/core/ext/transport/chttp2/client/insecure/README.md \
diff --git a/tools/internal_ci/linux/grpc_sanity.cfg b/tools/internal_ci/linux/grpc_sanity.cfg
index e06a2f4..9f65918 100644
--- a/tools/internal_ci/linux/grpc_sanity.cfg
+++ b/tools/internal_ci/linux/grpc_sanity.cfg
@@ -26,5 +26,5 @@
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux sanity opt --inner_jobs 16 -j 1 --internal_ci"
+  value: "-f basictests linux sanity --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
 }
diff --git a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg b/tools/internal_ci/linux/pull_request/grpc_sanity.cfg
similarity index 89%
rename from tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
rename to tools/internal_ci/linux/pull_request/grpc_sanity.cfg
index 24e7984..0f83299 100644
--- a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_sanity.cfg
@@ -16,7 +16,7 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
-timeout_mins: 20
+timeout_mins: 40
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
@@ -26,5 +26,5 @@
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux sanity opt --inner_jobs 16 -j 1 --internal_ci"
+  value: "-f basictests linux sanity --inner_jobs 16 -j 1 --internal_ci"
 }
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
index aa45f7f..c45a627 100644
--- a/tools/interop_matrix/client_matrix.py
+++ b/tools/interop_matrix/client_matrix.py
@@ -117,7 +117,10 @@
             'v1.9.2': None
         },
         {
-            'v1.10.0': None
+            'v1.10.1': None
+        },
+        {
+            'v1.11.1': None
         },
     ],
     'java': [
@@ -154,6 +157,9 @@
         {
             'v1.10.1': None
         },
+        {
+            'v1.11.0': None
+        },
     ],
     'python': [
         {
diff --git a/tools/run_tests/artifacts/distribtest_targets.py b/tools/run_tests/artifacts/distribtest_targets.py
index 041faab..1b467ed 100644
--- a/tools/run_tests/artifacts/distribtest_targets.py
+++ b/tools/run_tests/artifacts/distribtest_targets.py
@@ -287,7 +287,10 @@
     return [
         CppDistribTest('linux', 'x64', 'jessie', 'routeguide'),
         CppDistribTest('linux', 'x64', 'jessie', 'cmake'),
+        CppDistribTest('linux', 'x64', 'jessie', 'cmake_as_externalproject'),
+        CppDistribTest('linux', 'x64', 'jessie', 'cmake_as_submodule'),
         CppDistribTest('windows', 'x86', testcase='cmake'),
+        CppDistribTest('windows', 'x86', testcase='cmake_as_externalproject'),
         CSharpDistribTest('linux', 'x64', 'wheezy'),
         CSharpDistribTest('linux', 'x64', 'jessie'),
         CSharpDistribTest('linux', 'x86', 'jessie'),
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index fd6c526..c7ea43f 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -993,23 +993,6 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
-    "name": "grpc_invalid_channel_args_test", 
-    "src": [
-      "test/core/surface/invalid_channel_args_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
     "name": "grpc_json_token_test", 
     "src": [
       "test/core/security/json_token_test.cc"
@@ -4248,6 +4231,23 @@
       "gpr", 
       "gpr_test_util", 
       "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "retry_throttle_test", 
+    "src": [
+      "test/core/client_channel/retry_throttle_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
       "grpc++", 
       "grpc++_test_util", 
       "grpc_test_util"
@@ -6705,6 +6705,7 @@
       "census", 
       "gpr", 
       "grpc_base", 
+      "grpc_client_authority_filter", 
       "grpc_deadline_filter", 
       "grpc_lb_policy_grpclb_secure", 
       "grpc_lb_policy_pick_first", 
@@ -6739,16 +6740,8 @@
     "deps": [
       "gpr", 
       "grpc_base", 
-      "grpc_base_headers", 
-      "grpc_deadline_filter", 
-      "grpc_lb_policy_pick_first", 
-      "grpc_max_age_filter", 
-      "grpc_message_size_filter", 
-      "grpc_resolver_dns_native", 
-      "grpc_resolver_sockaddr", 
       "grpc_server_load_reporting", 
       "grpc_transport_chttp2_client_secure", 
-      "grpc_transport_chttp2_server_secure", 
       "grpc_transport_cronet_client_secure"
     ], 
     "headers": [], 
@@ -6820,6 +6813,7 @@
       "census", 
       "gpr", 
       "grpc_base", 
+      "grpc_client_authority_filter", 
       "grpc_deadline_filter", 
       "grpc_lb_policy_grpclb", 
       "grpc_lb_policy_pick_first", 
@@ -8524,6 +8518,7 @@
       "test/core/end2end/tests/bad_ping.cc", 
       "test/core/end2end/tests/binary_metadata.cc", 
       "test/core/end2end/tests/call_creds.cc", 
+      "test/core/end2end/tests/call_host_override.cc", 
       "test/core/end2end/tests/cancel_after_accept.cc", 
       "test/core/end2end/tests/cancel_after_client_done.cc", 
       "test/core/end2end/tests/cancel_after_invoke.cc", 
@@ -8621,6 +8616,7 @@
       "test/core/end2end/tests/bad_hostname.cc", 
       "test/core/end2end/tests/bad_ping.cc", 
       "test/core/end2end/tests/binary_metadata.cc", 
+      "test/core/end2end/tests/call_host_override.cc", 
       "test/core/end2end/tests/cancel_after_accept.cc", 
       "test/core/end2end/tests/cancel_after_client_done.cc", 
       "test/core/end2end/tests/cancel_after_invoke.cc", 
@@ -9551,6 +9547,24 @@
   {
     "deps": [
       "gpr", 
+      "grpc_base"
+    ], 
+    "headers": [
+      "src/core/ext/filters/http/client_authority_filter.h"
+    ], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc_client_authority_filter", 
+    "src": [
+      "src/core/ext/filters/http/client_authority_filter.cc", 
+      "src/core/ext/filters/http/client_authority_filter.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
       "grpc_base", 
       "grpc_deadline_filter"
     ], 
@@ -10269,12 +10283,15 @@
       "grpc_transport_chttp2"
     ], 
     "headers": [
+      "src/core/ext/transport/chttp2/client/authority.h", 
       "src/core/ext/transport/chttp2/client/chttp2_connector.h"
     ], 
     "is_filegroup": true, 
     "language": "c", 
     "name": "grpc_transport_chttp2_client_connector", 
     "src": [
+      "src/core/ext/transport/chttp2/client/authority.cc", 
+      "src/core/ext/transport/chttp2/client/authority.h", 
       "src/core/ext/transport/chttp2/client/chttp2_connector.cc", 
       "src/core/ext/transport/chttp2/client/chttp2_connector.h"
     ], 
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index c2bbf8c..d8c1a12 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -1279,30 +1279,6 @@
     "ci_platforms": [
       "linux", 
       "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c", 
-    "name": "grpc_invalid_channel_args_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [], 
-    "benchmark": false, 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
       "posix"
     ], 
     "cpu_cost": 1.0, 
@@ -4666,6 +4642,30 @@
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
+    "name": "retry_throttle_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
     "name": "secure_auth_context_test", 
     "platforms": [
       "linux", 
@@ -6969,6 +6969,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -8675,6 +8698,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -10353,6 +10399,28 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fakesec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -13186,6 +13254,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -14872,6 +14963,25 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -16298,6 +16408,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -17958,6 +18091,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+workarounds_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -19669,6 +19825,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -21464,6 +21644,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -23175,6 +23378,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -24927,6 +25154,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -29848,6 +30099,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -31535,6 +31809,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -35305,6 +35603,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -36988,6 +37309,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -39821,6 +40165,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -41488,6 +41855,25 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -42891,6 +43277,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -44528,6 +44937,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+workarounds_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -46215,6 +46647,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -47987,6 +48443,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -49650,6 +50129,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -103987,6 +104490,75 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5406804084260864"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5471994809155584"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-6609852341157888"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-minimized-4688823906729984"
     ], 
     "ci_platforms": [
diff --git a/tools/run_tests/helper_scripts/build_python.sh b/tools/run_tests/helper_scripts/build_python.sh
index b809fe0..dac29b9 100755
--- a/tools/run_tests/helper_scripts/build_python.sh
+++ b/tools/run_tests/helper_scripts/build_python.sh
@@ -152,6 +152,12 @@
   cd "$PWD"
 }
 
+case "$VENV" in
+  *gevent*)
+  $VENV_PYTHON -m pip install gevent
+  ;;
+esac
+
 $VENV_PYTHON -m pip install --upgrade pip==9.0.1
 $VENV_PYTHON -m pip install setuptools
 $VENV_PYTHON -m pip install cython
diff --git a/tools/run_tests/helper_scripts/run_python.sh b/tools/run_tests/helper_scripts/run_python.sh
index bcfe3a6..2b7321e 100755
--- a/tools/run_tests/helper_scripts/run_python.sh
+++ b/tools/run_tests/helper_scripts/run_python.sh
@@ -22,7 +22,7 @@
 
 ROOT=$(pwd)
 
-$PYTHON "$ROOT/src/python/grpcio_tests/setup.py" test_lite
+$PYTHON "$ROOT/src/python/grpcio_tests/setup.py" "$2"
 
 mkdir -p "$ROOT/reports"
 rm -rf "$ROOT/reports/python-coverage"
diff --git a/tools/run_tests/helper_scripts/run_ruby.sh b/tools/run_tests/helper_scripts/run_ruby.sh
index 4e9c212..03eaeb0 100755
--- a/tools/run_tests/helper_scripts/run_ruby.sh
+++ b/tools/run_tests/helper_scripts/run_ruby.sh
@@ -18,4 +18,7 @@
 # change to grpc repo root
 cd "$(dirname "$0")/../../.."
 
+# build grpc_ruby_plugin
+make grpc_ruby_plugin -j8
+
 rake
diff --git a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
index 1955442..5784745 100755
--- a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
+++ b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
@@ -28,4 +28,5 @@
 ruby src/ruby/end2end/grpc_class_init_driver.rb || EXIT_CODE=1
 ruby src/ruby/end2end/multiple_killed_watching_threads_driver.rb || EXIT_CODE=1
 ruby src/ruby/end2end/load_grpc_with_gc_stress_driver.rb || EXIT_CODE=1
+ruby src/ruby/end2end/client_memory_usage_driver.rb || EXIT_CODE=1
 exit $EXIT_CODE
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index ba4ab3b..970b0d7 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -545,13 +545,13 @@
 
     def client_cmd(self, args):
         return [
-            'py27/bin/python', 'src/python/grpcio_tests/setup.py',
+            'py27_native/bin/python', 'src/python/grpcio_tests/setup.py',
             'run_interop', '--client', '--args="{}"'.format(' '.join(args))
         ]
 
     def client_cmd_http2interop(self, args):
         return [
-            'py27/bin/python',
+            'py27_native/bin/python',
             'src/python/grpcio_tests/tests/http2/negative_http2_client.py',
         ] + args
 
@@ -560,7 +560,7 @@
 
     def server_cmd(self, args):
         return [
-            'py27/bin/python', 'src/python/grpcio_tests/setup.py',
+            'py27_native/bin/python', 'src/python/grpcio_tests/setup.py',
             'run_interop', '--server', '--args="{}"'.format(' '.join(args))
         ]
 
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 85c7f5c..4146eec 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -204,19 +204,28 @@
 
 
 _PythonConfigVars = collections.namedtuple('_ConfigVars', [
-    'shell', 'builder', 'builder_prefix_arguments', 'venv_relative_python',
-    'toolchain', 'runner'
+    'shell',
+    'builder',
+    'builder_prefix_arguments',
+    'venv_relative_python',
+    'toolchain',
+    'runner',
+    'test_name',
+    'iomgr_platform',
 ])
 
 
 def _python_config_generator(name, major, minor, bits, config_vars):
+    name += '_' + config_vars.iomgr_platform
     return PythonConfig(
         name, config_vars.shell + config_vars.builder +
         config_vars.builder_prefix_arguments + [
             _python_pattern_function(major=major, minor=minor, bits=bits)
         ] + [name] + config_vars.venv_relative_python + config_vars.toolchain,
-        config_vars.shell + config_vars.runner +
-        [os.path.join(name, config_vars.venv_relative_python[0])])
+        config_vars.shell + config_vars.runner + [
+            os.path.join(name, config_vars.venv_relative_python[0]),
+            config_vars.test_name
+        ])
 
 
 def _pypy_config_generator(name, major, config_vars):
@@ -281,7 +290,7 @@
             self._docker_distro, self._make_options = self._compiler_options(
                 self.args.use_docker, self.args.compiler)
         if args.iomgr_platform == "uv":
-            cflags = '-DGRPC_UV -DGRPC_CUSTOM_IOMGR_THREAD_CHECK '
+            cflags = '-DGRPC_UV -DGRPC_CUSTOM_IOMGR_THREAD_CHECK -DGRPC_CUSTOM_SOCKET '
             try:
                 cflags += subprocess.check_output(
                     ['pkg-config', '--cflags', 'libuv']).strip() + ' '
@@ -770,12 +779,16 @@
             venv_relative_python = ['bin/python']
             toolchain = ['unix']
 
+        test_command = 'test_lite'
+        if args.iomgr_platform == 'gevent':
+            test_command = 'test_gevent'
         runner = [
             os.path.abspath('tools/run_tests/helper_scripts/run_python.sh')
         ]
-        config_vars = _PythonConfigVars(shell, builder,
-                                        builder_prefix_arguments,
-                                        venv_relative_python, toolchain, runner)
+
+        config_vars = _PythonConfigVars(
+            shell, builder, builder_prefix_arguments, venv_relative_python,
+            toolchain, runner, test_command, args.iomgr_platform)
         python27_config = _python_config_generator(
             name='py27',
             major='2',
@@ -1341,7 +1354,7 @@
 )
 argp.add_argument(
     '--iomgr_platform',
-    choices=['native', 'uv'],
+    choices=['native', 'uv', 'gevent'],
     default='native',
     help='Selects iomgr platform to build on')
 argp.add_argument(
diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py
index 1c99e79..85f91b0 100755
--- a/tools/run_tests/run_tests_matrix.py
+++ b/tools/run_tests/run_tests_matrix.py
@@ -114,7 +114,7 @@
 def _generate_jobs(languages,
                    configs,
                    platforms,
-                   iomgr_platform='native',
+                   iomgr_platforms=['native'],
                    arch=None,
                    compiler=None,
                    labels=[],
@@ -125,48 +125,60 @@
     result = []
     for language in languages:
         for platform in platforms:
-            for config in configs:
-                name = '%s_%s_%s_%s' % (language, platform, config,
-                                        iomgr_platform)
-                runtests_args = [
-                    '-l', language, '-c', config, '--iomgr_platform',
-                    iomgr_platform
-                ]
-                if arch or compiler:
-                    name += '_%s_%s' % (arch, compiler)
-                    runtests_args += ['--arch', arch, '--compiler', compiler]
-                if '--build_only' in extra_args:
-                    name += '_buildonly'
-                for extra_env in extra_envs:
-                    name += '_%s_%s' % (extra_env, extra_envs[extra_env])
+            for iomgr_platform in iomgr_platforms:
+                for config in configs:
+                    name = '%s_%s_%s_%s' % (language, platform, config,
+                                            iomgr_platform)
+                    runtests_args = [
+                        '-l', language, '-c', config, '--iomgr_platform',
+                        iomgr_platform
+                    ]
+                    if arch or compiler:
+                        name += '_%s_%s' % (arch, compiler)
+                        runtests_args += [
+                            '--arch', arch, '--compiler', compiler
+                        ]
+                    if '--build_only' in extra_args:
+                        name += '_buildonly'
+                    for extra_env in extra_envs:
+                        name += '_%s_%s' % (extra_env, extra_envs[extra_env])
 
-                runtests_args += extra_args
-                if platform == 'linux':
-                    job = _docker_jobspec(
-                        name=name,
-                        runtests_args=runtests_args,
-                        runtests_envs=extra_envs,
-                        inner_jobs=inner_jobs,
-                        timeout_seconds=timeout_seconds)
-                else:
-                    job = _workspace_jobspec(
-                        name=name,
-                        runtests_args=runtests_args,
-                        runtests_envs=extra_envs,
-                        inner_jobs=inner_jobs,
-                        timeout_seconds=timeout_seconds)
+                    runtests_args += extra_args
+                    if platform == 'linux':
+                        job = _docker_jobspec(
+                            name=name,
+                            runtests_args=runtests_args,
+                            runtests_envs=extra_envs,
+                            inner_jobs=inner_jobs,
+                            timeout_seconds=timeout_seconds)
+                    else:
+                        job = _workspace_jobspec(
+                            name=name,
+                            runtests_args=runtests_args,
+                            runtests_envs=extra_envs,
+                            inner_jobs=inner_jobs,
+                            timeout_seconds=timeout_seconds)
 
-                job.labels = [platform, config, language, iomgr_platform
-                             ] + labels
-                result.append(job)
+                    job.labels = [platform, config, language, iomgr_platform
+                                 ] + labels
+                    result.append(job)
     return result
 
 
 def _create_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS):
     test_jobs = []
+    # sanity tests
+    test_jobs += _generate_jobs(
+        languages=['sanity'],
+        configs=['dbg', 'opt'],
+        platforms=['linux'],
+        labels=['basictests'],
+        extra_args=extra_args,
+        inner_jobs=inner_jobs)
+
     # supported on linux only
     test_jobs += _generate_jobs(
-        languages=['sanity', 'php7'],
+        languages=['php7'],
         configs=['dbg', 'opt'],
         platforms=['linux'],
         labels=['basictests', 'multilang'],
@@ -184,13 +196,22 @@
         timeout_seconds=_CPP_RUNTESTS_TIMEOUT)
 
     test_jobs += _generate_jobs(
-        languages=['csharp', 'python'],
+        languages=['csharp'],
         configs=['dbg', 'opt'],
         platforms=['linux', 'macos', 'windows'],
         labels=['basictests', 'multilang'],
         extra_args=extra_args,
         inner_jobs=inner_jobs)
 
+    test_jobs += _generate_jobs(
+        languages=['python'],
+        configs=['opt'],
+        platforms=['linux', 'macos', 'windows'],
+        iomgr_platforms=['native', 'gevent'],
+        labels=['basictests', 'multilang'],
+        extra_args=extra_args,
+        inner_jobs=inner_jobs)
+
     # supported on linux and mac.
     test_jobs += _generate_jobs(
         languages=['c++'],
@@ -377,7 +398,7 @@
         languages=['c'],
         configs=['dbg'],
         platforms=['linux'],
-        iomgr_platform='uv',
+        iomgr_platforms=['uv'],
         labels=['portability', 'corelang'],
         extra_args=extra_args,
         inner_jobs=inner_jobs,