瀏覽代碼

log updates

Danny Reidenbach 5 年之前
父節點
當前提交
c67fb4631d
共有 100 個文件被更改,包括 4198 次插入1975 次删除
  1. 1 1
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 1 1
      .github/ISSUE_TEMPLATE/cleanup_request.md
  3. 1 1
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 1 1
      .github/ISSUE_TEMPLATE/question.md
  5. 1 1
      .github/pull_request_template.md
  6. 295 6
      BUILD
  7. 138 4
      BUILD.gn
  8. 247 44
      CMakeLists.txt
  9. 278 64
      Makefile
  10. 1 1
      Rakefile
  11. 18 7
      bazel/grpc_deps.bzl
  12. 307 20
      build_autogenerated.yaml
  13. 1 1
      build_config.rb
  14. 3 3
      build_handwritten.yaml
  15. 72 0
      config.m4
  16. 72 0
      config.w32
  17. 1 1
      doc/PROTOCOL-WEB.md
  18. 5 5
      doc/core/combiner-explainer.md
  19. 1 1
      doc/core/epoll-polling-engine.md
  20. 1 1
      doc/core/grpc-client-server-polling-engine-usage.md
  21. 1 1
      doc/core/grpc-cq.md
  22. 3 3
      doc/core/moving-to-c++.md
  23. 1 1
      doc/environment_variables.md
  24. 1 1
      doc/fork_support.md
  25. 2 1
      doc/g_stands_for.md
  26. 40 0
      doc/grpc_xds_features.md
  27. 1 0
      doc/health-checking.md
  28. 13 13
      doc/http2-interop-test-descriptions.md
  29. 1 1
      doc/internationalization.md
  30. 5 5
      doc/interop-test-descriptions.md
  31. 4 4
      doc/keepalive.md
  32. 2 2
      doc/python/server_reflection.md
  33. 2 2
      doc/python/sphinx/grpc.rst
  34. 7 18
      doc/python/sphinx/grpc_asyncio.rst
  35. 4 4
      doc/security_audit.md
  36. 1 1
      doc/unit_testing.md
  37. 2 2
      doc/versioning.md
  38. 36 8
      doc/xds-test-descriptions.md
  39. 2 2
      examples/cpp/README.md
  40. 1 1
      examples/cpp/helloworld/README.md
  41. 1 1
      examples/cpp/route_guide/README.md
  42. 1 1
      examples/csharp/Helloworld/README.md
  43. 2 2
      examples/csharp/HelloworldLegacyCsproj/README.md
  44. 1 1
      examples/csharp/RouteGuide/README.md
  45. 1 1
      examples/node/README.md
  46. 1 1
      examples/node/dynamic_codegen/route_guide/README.md
  47. 1 1
      examples/node/static_codegen/route_guide/README.md
  48. 1 1
      examples/objective-c/auth_sample/README.md
  49. 1 1
      examples/objective-c/helloworld/README.md
  50. 1 1
      examples/objective-c/route_guide/README.md
  51. 1 1
      examples/php/README.md
  52. 1 1
      examples/php/route_guide/README.md
  53. 1 1
      examples/python/README.md
  54. 1 1
      examples/python/helloworld/README.md
  55. 1 1
      examples/python/metadata/README.md
  56. 1 1
      examples/python/multiplex/README.md
  57. 1 1
      examples/python/route_guide/README.md
  58. 1 1
      examples/ruby/README.md
  59. 1 1
      examples/ruby/route_guide/README.md
  60. 150 9
      gRPC-C++.podspec
  61. 224 9
      gRPC-Core.podspec
  62. 1 1
      gRPC-ProtoRPC.podspec
  63. 1 1
      gRPC-RxLibrary.podspec
  64. 1 1
      gRPC.podspec
  65. 144 1
      grpc.gemspec
  66. 157 2
      grpc.gyp
  67. 10 7
      include/grpc/impl/codegen/grpc_types.h
  68. 0 25
      include/grpc/impl/codegen/port_platform.h
  69. 28 11
      include/grpcpp/health_check_service_interface.h
  70. 0 55
      include/grpcpp/health_check_service_interface_impl.h
  71. 333 212
      include/grpcpp/impl/codegen/client_callback_impl.h
  72. 14 4
      include/grpcpp/impl/codegen/server_context_impl.h
  73. 2 2
      include/grpcpp/opencensus.h
  74. 42 3
      include/grpcpp/resource_quota.h
  75. 2 3
      include/grpcpp/server_builder_impl.h
  76. 147 4
      package.xml
  77. 2 2
      requirements.bazel.txt
  78. 1 1
      requirements.txt
  79. 5 0
      setup.py
  80. 5 2
      src/abseil-cpp/preprocessed_builds.yaml.gen.py
  81. 3 2
      src/compiler/objective_c_plugin.cc
  82. 3 2
      src/compiler/python_generator.cc
  83. 12 9
      src/core/ext/filters/client_channel/backend_metric.cc
  84. 350 238
      src/core/ext/filters/client_channel/client_channel.cc
  85. 62 0
      src/core/ext/filters/client_channel/config_selector.cc
  86. 91 0
      src/core/ext/filters/client_channel/config_selector.h
  87. 2 0
      src/core/ext/filters/client_channel/health/health_check_client.cc
  88. 2 0
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  89. 33 28
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  90. 39 20
      src/core/ext/filters/client_channel/resolving_lb_policy.h
  91. 142 0
      src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
  92. 88 630
      src/core/ext/filters/client_channel/xds/xds_api.cc
  93. 3 0
      src/core/ext/filters/client_channel/xds/xds_api.h
  94. 2 1
      src/core/ext/filters/http/http_filters_plugin.cc
  95. 67 25
      src/core/ext/filters/http/message_compress/message_decompress_filter.cc
  96. 3 1
      src/core/ext/filters/http/message_compress/message_decompress_filter.h
  97. 41 65
      src/core/ext/filters/message_size/message_size_filter.cc
  98. 6 0
      src/core/ext/filters/message_size/message_size_filter.h
  99. 380 344
      src/core/ext/transport/chttp2/server/chttp2_server.cc
  100. 6 2
      src/core/ext/transport/chttp2/server/chttp2_server.h

+ 1 - 1
.github/ISSUE_TEMPLATE/bug_report.md

@@ -2,7 +2,7 @@
 name: Report a bug
 about: Create a report to help us improve
 labels: kind/bug, priority/P2
-assignees: veblush
+assignees: nicolasnoble 
 
 ---
 

+ 1 - 1
.github/ISSUE_TEMPLATE/cleanup_request.md

@@ -2,7 +2,7 @@
 name: Request a cleanup
 about: Suggest a cleanup in our repository
 labels: kind/internal cleanup, priority/P2
-assignees: veblush
+assignees: nicolasnoble 
 
 ---
 

+ 1 - 1
.github/ISSUE_TEMPLATE/feature_request.md

@@ -2,7 +2,7 @@
 name: Request a feature
 about: Suggest an idea for this project
 labels: kind/enhancement, priority/P2
-assignees: veblush
+assignees: nicolasnoble 
 
 ---
 

+ 1 - 1
.github/ISSUE_TEMPLATE/question.md

@@ -2,7 +2,7 @@
 name: Ask a question
 about: Ask a question
 labels: kind/question, priority/P3
-assignees: veblush
+assignees: nicolasnoble 
 
 ---
 

+ 1 - 1
.github/pull_request_template.md

@@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
 
 -->
 
-@veblush
+@nicolasnoble

+ 295 - 6
BUILD

@@ -75,11 +75,11 @@ config_setting(
 python_config_settings()
 
 # This should be updated along with build.yaml
-g_stands_for = "gradius"
+g_stands_for = "galore"
 
 core_version = "10.0.0"
 
-version = "1.30.0-dev"
+version = "1.31.0-dev"
 
 GPR_PUBLIC_HDRS = [
     "include/grpc/support/alloc.h",
@@ -124,6 +124,7 @@ GRPC_SECURE_PUBLIC_HDRS = [
 # TODO(ctiller): layer grpc atop grpc_unsecure, layer grpc++ atop grpc++_unsecure
 GRPCXX_SRCS = [
     "src/cpp/client/channel_cc.cc",
+    "src/cpp/client/client_callback.cc",
     "src/cpp/client/client_context.cc",
     "src/cpp/client/client_interceptor.cc",
     "src/cpp/client/create_channel.cc",
@@ -233,7 +234,6 @@ GRPCXX_PUBLIC_HDRS = [
     "include/grpcpp/generic/generic_stub_impl.h",
     "include/grpcpp/grpcpp.h",
     "include/grpcpp/health_check_service_interface.h",
-    "include/grpcpp/health_check_service_interface_impl.h",
     "include/grpcpp/impl/call.h",
     "include/grpcpp/impl/channel_argument_option.h",
     "include/grpcpp/impl/client_unary_call.h",
@@ -250,7 +250,6 @@ GRPCXX_PUBLIC_HDRS = [
     "include/grpcpp/impl/server_initializer_impl.h",
     "include/grpcpp/impl/service_type.h",
     "include/grpcpp/resource_quota.h",
-    "include/grpcpp/resource_quota_impl.h",
     "include/grpcpp/security/auth_context.h",
     "include/grpcpp/security/auth_metadata_processor.h",
     "include/grpcpp/security/auth_metadata_processor_impl.h",
@@ -1027,6 +1026,7 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc",
         "src/core/ext/filters/client_channel/global_subchannel_pool.cc",
         "src/core/ext/filters/client_channel/health/health_check_client.cc",
         "src/core/ext/filters/client_channel/http_connect_handshaker.cc",
@@ -1044,6 +1044,7 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/retry_throttle.cc",
         "src/core/ext/filters/client_channel/server_address.cc",
         "src/core/ext/filters/client_channel/service_config.cc",
+        "src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc",
         "src/core/ext/filters/client_channel/service_config_parser.cc",
         "src/core/ext/filters/client_channel/subchannel.cc",
         "src/core/ext/filters/client_channel/subchannel_pool_interface.cc",
@@ -1054,6 +1055,7 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/client_channel.h",
         "src/core/ext/filters/client_channel/client_channel_channelz.h",
         "src/core/ext/filters/client_channel/client_channel_factory.h",
+        "src/core/ext/filters/client_channel/config_selector.h",
         "src/core/ext/filters/client_channel/connector.h",
         "src/core/ext/filters/client_channel/global_subchannel_pool.h",
         "src/core/ext/filters/client_channel/health/health_check_client.h",
@@ -1184,6 +1186,7 @@ grpc_cc_library(
     language = "c++",
     deps = [
         "grpc_base",
+        "grpc_message_size_filter",
     ],
 )
 
@@ -1307,9 +1310,14 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/xds/xds_client.h",
         "src/core/ext/filters/client_channel/xds/xds_client_stats.h",
     ],
+    external_deps = [
+        "upb_lib",
+        "upb_textformat_lib",
+    ],
     language = "c++",
     deps = [
         "envoy_ads_upb",
+        "envoy_ads_upbdefs",
         "grpc_base",
         "grpc_client_channel",
     ],
@@ -1332,9 +1340,14 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/xds/xds_client.h",
         "src/core/ext/filters/client_channel/xds/xds_client_stats.h",
     ],
+    external_deps = [
+        "upb_lib",
+        "upb_textformat_lib",
+    ],
     language = "c++",
     deps = [
         "envoy_ads_upb",
+        "envoy_ads_upbdefs",
         "grpc_base",
         "grpc_client_channel",
         "grpc_secure",
@@ -2553,6 +2566,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
     deps = [
@@ -2565,6 +2579,97 @@ grpc_cc_library(
     ],
 )
 
+grpc_cc_library(
+    name = "envoy_ads_upbdefs",
+    srcs = [
+        "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor",
+        "upb_textformat_lib",
+    ],
+    language = "c++",
+    deps = [
+        ":envoy_ads_upb",
+        ":envoy_annotations_upbdefs",
+        ":envoy_core_upbdefs",
+        ":envoy_type_upbdefs",
+        ":google_api_upbdefs",
+        ":proto_gen_validate_upbdefs",
+        ":udpa_annotations_upbdefs",
+    ],
+)
+
 grpc_cc_library(
     name = "envoy_annotations_upb",
     srcs = [
@@ -2577,6 +2682,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
     deps = [
@@ -2584,6 +2690,28 @@ grpc_cc_library(
     ],
 )
 
+grpc_cc_library(
+    name = "envoy_annotations_upbdefs",
+    srcs = [
+        "src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor",
+        "upb_textformat_lib",
+    ],
+    language = "c++",
+    deps = [
+        ":envoy_annotations_upb",
+        ":google_api_upbdefs",
+    ],
+)
+
 grpc_cc_library(
     name = "envoy_core_upb",
     srcs = [
@@ -2612,6 +2740,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
     deps = [
@@ -2623,6 +2752,46 @@ grpc_cc_library(
     ],
 )
 
+grpc_cc_library(
+    name = "envoy_core_upbdefs",
+    srcs = [
+        "src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor",
+        "upb_textformat_lib",
+    ],
+    language = "c++",
+    deps = [
+        ":envoy_core_upb",
+        ":envoy_type_upbdefs",
+        ":google_api_upbdefs",
+        ":proto_gen_validate_upbdefs",
+    ],
+)
+
 grpc_cc_library(
     name = "envoy_type_upb",
     srcs = [
@@ -2647,6 +2816,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
     deps = [
@@ -2657,6 +2827,37 @@ grpc_cc_library(
     ],
 )
 
+grpc_cc_library(
+    name = "envoy_type_upbdefs",
+    srcs = [
+        "src/core/ext/upb-generated/envoy/type/http.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/percent.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/range.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/envoy/type/http.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/type/percent.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/type/range.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h",
+        "src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor",
+        "upb_textformat_lib",
+    ],
+    language = "c++",
+    deps = [
+        ":envoy_type_upb",
+        ":google_api_upbdefs",
+        ":proto_gen_validate_upbdefs",
+    ],
+)
+
 grpc_cc_library(
     name = "proto_gen_validate_upb",
     srcs = [
@@ -2669,6 +2870,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
     deps = [
@@ -2676,6 +2878,28 @@ grpc_cc_library(
     ],
 )
 
+grpc_cc_library(
+    name = "proto_gen_validate_upbdefs",
+    srcs = [
+        "src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c",
+        "src/core/ext/upb-generated/validate/validate.upbdefs.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h",
+        "src/core/ext/upb-generated/validate/validate.upbdefs.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor",
+        "upb_textformat_lib",
+    ],
+    language = "c++",
+    deps = [
+        ":google_api_upbdefs",
+        ":proto_gen_validate_upb",
+    ],
+)
+
 # Once upb code-gen issue is resolved, replace udpa_orca_upb with this.
 # grpc_upb_proto_library(
 #     name = "udpa_orca_upb",
@@ -2692,6 +2916,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
     deps = [
@@ -2713,6 +2938,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
     deps = [
@@ -2720,6 +2946,30 @@ grpc_cc_library(
     ],
 )
 
+grpc_cc_library(
+    name = "udpa_annotations_upbdefs",
+    srcs = [
+        "src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c",
+        "src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c",
+        "src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h",
+        "src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h",
+        "src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor",
+        "upb_textformat_lib",
+    ],
+    language = "c++",
+    deps = [
+        ":google_api_upbdefs",
+        ":udpa_annotations_upb",
+    ],
+)
+
 # Once upb code-gen issue is resolved, replace grpc_health_upb with this.
 # grpc_upb_proto_library(
 #     name = "grpc_health_upb",
@@ -2736,6 +2986,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
 )
@@ -2747,7 +2998,6 @@ grpc_cc_library(
         "src/core/ext/upb-generated/google/api/annotations.upb.c",
         "src/core/ext/upb-generated/google/api/http.upb.c",
         "src/core/ext/upb-generated/google/protobuf/any.upb.c",
-        "src/core/ext/upb-generated/google/protobuf/descriptor.upb.c",
         "src/core/ext/upb-generated/google/protobuf/duration.upb.c",
         "src/core/ext/upb-generated/google/protobuf/empty.upb.c",
         "src/core/ext/upb-generated/google/protobuf/struct.upb.c",
@@ -2759,7 +3009,6 @@ grpc_cc_library(
         "src/core/ext/upb-generated/google/api/annotations.upb.h",
         "src/core/ext/upb-generated/google/api/http.upb.h",
         "src/core/ext/upb-generated/google/protobuf/any.upb.h",
-        "src/core/ext/upb-generated/google/protobuf/descriptor.upb.h",
         "src/core/ext/upb-generated/google/protobuf/duration.upb.h",
         "src/core/ext/upb-generated/google/protobuf/empty.upb.h",
         "src/core/ext/upb-generated/google/protobuf/struct.upb.h",
@@ -2769,10 +3018,48 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
 )
 
+grpc_cc_library(
+    name = "google_api_upbdefs",
+    srcs = [
+        "src/core/ext/upb-generated/google/api/annotations.upbdefs.c",
+        "src/core/ext/upb-generated/google/api/http.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/any.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c",
+        "src/core/ext/upb-generated/google/rpc/status.upbdefs.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/google/api/annotations.upbdefs.h",
+        "src/core/ext/upb-generated/google/api/http.upbdefs.h",
+        "src/core/ext/upb-generated/google/protobuf/any.upbdefs.h",
+        "src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h",
+        "src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h",
+        "src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h",
+        "src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h",
+        "src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h",
+        "src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h",
+        "src/core/ext/upb-generated/google/rpc/status.upbdefs.h",
+    ],
+    external_deps = [
+        "upb_lib",
+        "upb_lib_descriptor",
+        "upb_textformat_lib",
+    ],
+    language = "c++",
+    deps = [
+        ":google_api_upb",
+    ],
+)
+
 # Once upb code-gen issue is resolved, replace grpc_lb_upb with this.
 # grpc_upb_proto_library(
 #     name = "grpc_lb_upb",
@@ -2789,6 +3076,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
     deps = [
@@ -2816,6 +3104,7 @@ grpc_cc_library(
     ],
     external_deps = [
         "upb_lib",
+        "upb_lib_descriptor",
     ],
     language = "c++",
 )

+ 138 - 4
BUILD.gn

@@ -211,6 +211,8 @@ config("grpc_config") {
         "src/core/ext/filters/client_channel/client_channel_factory.cc",
         "src/core/ext/filters/client_channel/client_channel_factory.h",
         "src/core/ext/filters/client_channel/client_channel_plugin.cc",
+        "src/core/ext/filters/client_channel/config_selector.cc",
+        "src/core/ext/filters/client_channel/config_selector.h",
         "src/core/ext/filters/client_channel/connector.h",
         "src/core/ext/filters/client_channel/global_subchannel_pool.cc",
         "src/core/ext/filters/client_channel/global_subchannel_pool.h",
@@ -293,6 +295,7 @@ config("grpc_config") {
         "src/core/ext/filters/client_channel/service_config.cc",
         "src/core/ext/filters/client_channel/service_config.h",
         "src/core/ext/filters/client_channel/service_config_call_data.h",
+        "src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc",
         "src/core/ext/filters/client_channel/service_config_parser.cc",
         "src/core/ext/filters/client_channel/service_config_parser.h",
         "src/core/ext/filters/client_channel/subchannel.cc",
@@ -396,130 +399,254 @@ config("grpc_config") {
         "src/core/ext/transport/inproc/inproc_transport.h",
         "src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c",
         "src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h",
+        "src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h",
         "src/core/ext/upb-generated/envoy/annotations/resource.upb.c",
         "src/core/ext/upb-generated/envoy/annotations/resource.upb.h",
+        "src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/cds.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cds.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/eds.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/eds.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/lds.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/lds.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/listener.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/listener.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/rds.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/rds.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/route.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/route.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h",
         "src/core/ext/upb-generated/envoy/api/v2/srds.upb.c",
         "src/core/ext/upb-generated/envoy/api/v2/srds.upb.h",
+        "src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h",
         "src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c",
         "src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h",
+        "src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h",
         "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c",
         "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h",
+        "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h",
         "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c",
         "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h",
+        "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h",
         "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c",
         "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h",
+        "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h",
         "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c",
         "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h",
+        "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h",
         "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c",
         "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h",
+        "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h",
         "src/core/ext/upb-generated/envoy/type/http.upb.c",
         "src/core/ext/upb-generated/envoy/type/http.upb.h",
+        "src/core/ext/upb-generated/envoy/type/http.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/http.upbdefs.h",
         "src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c",
         "src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h",
+        "src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h",
         "src/core/ext/upb-generated/envoy/type/matcher/string.upb.c",
         "src/core/ext/upb-generated/envoy/type/matcher/string.upb.h",
+        "src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h",
         "src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c",
         "src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h",
+        "src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h",
         "src/core/ext/upb-generated/envoy/type/percent.upb.c",
         "src/core/ext/upb-generated/envoy/type/percent.upb.h",
+        "src/core/ext/upb-generated/envoy/type/percent.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/percent.upbdefs.h",
         "src/core/ext/upb-generated/envoy/type/range.upb.c",
         "src/core/ext/upb-generated/envoy/type/range.upb.h",
+        "src/core/ext/upb-generated/envoy/type/range.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/range.upbdefs.h",
         "src/core/ext/upb-generated/envoy/type/semantic_version.upb.c",
         "src/core/ext/upb-generated/envoy/type/semantic_version.upb.h",
+        "src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h",
         "src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c",
         "src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h",
+        "src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c",
+        "src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h",
         "src/core/ext/upb-generated/gogoproto/gogo.upb.c",
         "src/core/ext/upb-generated/gogoproto/gogo.upb.h",
+        "src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c",
+        "src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h",
         "src/core/ext/upb-generated/google/api/annotations.upb.c",
         "src/core/ext/upb-generated/google/api/annotations.upb.h",
+        "src/core/ext/upb-generated/google/api/annotations.upbdefs.c",
+        "src/core/ext/upb-generated/google/api/annotations.upbdefs.h",
         "src/core/ext/upb-generated/google/api/http.upb.c",
         "src/core/ext/upb-generated/google/api/http.upb.h",
+        "src/core/ext/upb-generated/google/api/http.upbdefs.c",
+        "src/core/ext/upb-generated/google/api/http.upbdefs.h",
         "src/core/ext/upb-generated/google/protobuf/any.upb.c",
         "src/core/ext/upb-generated/google/protobuf/any.upb.h",
-        "src/core/ext/upb-generated/google/protobuf/descriptor.upb.c",
-        "src/core/ext/upb-generated/google/protobuf/descriptor.upb.h",
+        "src/core/ext/upb-generated/google/protobuf/any.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/any.upbdefs.h",
+        "src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h",
         "src/core/ext/upb-generated/google/protobuf/duration.upb.c",
         "src/core/ext/upb-generated/google/protobuf/duration.upb.h",
+        "src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h",
         "src/core/ext/upb-generated/google/protobuf/empty.upb.c",
         "src/core/ext/upb-generated/google/protobuf/empty.upb.h",
+        "src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h",
         "src/core/ext/upb-generated/google/protobuf/struct.upb.c",
         "src/core/ext/upb-generated/google/protobuf/struct.upb.h",
+        "src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h",
         "src/core/ext/upb-generated/google/protobuf/timestamp.upb.c",
         "src/core/ext/upb-generated/google/protobuf/timestamp.upb.h",
+        "src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h",
         "src/core/ext/upb-generated/google/protobuf/wrappers.upb.c",
         "src/core/ext/upb-generated/google/protobuf/wrappers.upb.h",
+        "src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c",
+        "src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h",
         "src/core/ext/upb-generated/google/rpc/status.upb.c",
         "src/core/ext/upb-generated/google/rpc/status.upb.h",
+        "src/core/ext/upb-generated/google/rpc/status.upbdefs.c",
+        "src/core/ext/upb-generated/google/rpc/status.upbdefs.h",
         "src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c",
         "src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h",
         "src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c",
@@ -532,14 +659,22 @@ config("grpc_config") {
         "src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h",
         "src/core/ext/upb-generated/udpa/annotations/migrate.upb.c",
         "src/core/ext/upb-generated/udpa/annotations/migrate.upb.h",
+        "src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c",
+        "src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h",
         "src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c",
         "src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h",
+        "src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c",
+        "src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h",
         "src/core/ext/upb-generated/udpa/annotations/status.upb.c",
         "src/core/ext/upb-generated/udpa/annotations/status.upb.h",
+        "src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c",
+        "src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h",
         "src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c",
         "src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h",
         "src/core/ext/upb-generated/validate/validate.upb.c",
         "src/core/ext/upb-generated/validate/validate.upb.h",
+        "src/core/ext/upb-generated/validate/validate.upbdefs.c",
+        "src/core/ext/upb-generated/validate/validate.upbdefs.h",
         "src/core/lib/avl/avl.cc",
         "src/core/lib/avl/avl.h",
         "src/core/lib/backoff/backoff.cc",
@@ -1100,7 +1235,6 @@ config("grpc_config") {
         "include/grpcpp/generic/generic_stub_impl.h",
         "include/grpcpp/grpcpp.h",
         "include/grpcpp/health_check_service_interface.h",
-        "include/grpcpp/health_check_service_interface_impl.h",
         "include/grpcpp/impl/call.h",
         "include/grpcpp/impl/channel_argument_option.h",
         "include/grpcpp/impl/client_unary_call.h",
@@ -1175,7 +1309,6 @@ config("grpc_config") {
         "include/grpcpp/impl/server_initializer_impl.h",
         "include/grpcpp/impl/service_type.h",
         "include/grpcpp/resource_quota.h",
-        "include/grpcpp/resource_quota_impl.h",
         "include/grpcpp/security/auth_context.h",
         "include/grpcpp/security/auth_metadata_processor.h",
         "include/grpcpp/security/auth_metadata_processor_impl.h",
@@ -1220,6 +1353,7 @@ config("grpc_config") {
         "include/grpcpp/support/time.h",
         "include/grpcpp/support/validate_service_config.h",
         "src/cpp/client/channel_cc.cc",
+        "src/cpp/client/client_callback.cc",
         "src/cpp/client/client_context.cc",
         "src/cpp/client/client_interceptor.cc",
         "src/cpp/client/create_channel.cc",

+ 247 - 44
CMakeLists.txt

@@ -25,12 +25,12 @@
 cmake_minimum_required(VERSION 3.5.1)
 
 set(PACKAGE_NAME          "grpc")
-set(PACKAGE_VERSION       "1.30.0-dev")
-set(gRPC_CORE_VERSION     "10.0.0")
-set(gRPC_CORE_SOVERSION   "10")
-set(gRPC_CPP_VERSION      "1.30.0-dev")
+set(PACKAGE_VERSION       "1.31.0-dev")
+set(gRPC_CORE_VERSION     "11.0.0")
+set(gRPC_CORE_SOVERSION   "11")
+set(gRPC_CPP_VERSION      "1.31.0-dev")
 set(gRPC_CPP_SOVERSION    "1")
-set(gRPC_CSHARP_VERSION   "2.30.0-dev")
+set(gRPC_CSHARP_VERSION   "2.31.0-dev")
 set(gRPC_CSHARP_SOVERSION "2")
 set(PACKAGE_STRING        "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 set(PACKAGE_TARNAME       "${PACKAGE_NAME}-${PACKAGE_VERSION}")
@@ -569,7 +569,6 @@ if(gRPC_BUILD_TESTS)
   add_dependencies(buildtests_c secure_endpoint_test)
   add_dependencies(buildtests_c security_connector_test)
   add_dependencies(buildtests_c sequential_connectivity_test)
-  add_dependencies(buildtests_c server_chttp2_test)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     add_dependencies(buildtests_c server_ssl_test)
   endif()
@@ -793,6 +792,7 @@ if(gRPC_BUILD_TESTS)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
     add_dependencies(buildtests_cxx server_builder_with_socket_mutator_test)
   endif()
+  add_dependencies(buildtests_cxx server_chttp2_test)
   add_dependencies(buildtests_cxx server_context_test_spouse_test)
   add_dependencies(buildtests_cxx server_early_return_test)
   add_dependencies(buildtests_cxx server_interceptors_end2end_test)
@@ -827,6 +827,7 @@ if(gRPC_BUILD_TESTS)
   endif()
   add_dependencies(buildtests_cxx timer_test)
   add_dependencies(buildtests_cxx tls_security_connector_test)
+  add_dependencies(buildtests_cxx too_many_pings_test)
   add_dependencies(buildtests_cxx unknown_frame_bad_client_test)
   add_dependencies(buildtests_cxx window_overflow_bad_client_test)
   if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@@ -1327,6 +1328,7 @@ add_library(grpc
   src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc
   src/core/ext/filters/client_channel/global_subchannel_pool.cc
   src/core/ext/filters/client_channel/health/health_check_client.cc
   src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -1374,6 +1376,7 @@ add_library(grpc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/server_address.cc
   src/core/ext/filters/client_channel/service_config.cc
+  src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
   src/core/ext/filters/client_channel/service_config_parser.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_pool_interface.cc
@@ -1430,78 +1433,144 @@ add_library(grpc
   src/core/ext/transport/inproc/inproc_plugin.cc
   src/core/ext/transport/inproc/inproc_transport.cc
   src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c
+  src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c
   src/core/ext/upb-generated/envoy/annotations/resource.upb.c
+  src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/lds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/listener.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/rds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/route.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/srds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c
   src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
+  src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c
   src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
+  src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c
   src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
+  src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c
   src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
+  src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c
   src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
+  src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c
   src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
+  src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c
   src/core/ext/upb-generated/envoy/type/http.upb.c
+  src/core/ext/upb-generated/envoy/type/http.upbdefs.c
   src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c
+  src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c
   src/core/ext/upb-generated/envoy/type/matcher/string.upb.c
+  src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c
   src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c
+  src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c
   src/core/ext/upb-generated/envoy/type/percent.upb.c
+  src/core/ext/upb-generated/envoy/type/percent.upbdefs.c
   src/core/ext/upb-generated/envoy/type/range.upb.c
+  src/core/ext/upb-generated/envoy/type/range.upbdefs.c
   src/core/ext/upb-generated/envoy/type/semantic_version.upb.c
+  src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c
   src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c
+  src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c
   src/core/ext/upb-generated/gogoproto/gogo.upb.c
+  src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c
   src/core/ext/upb-generated/google/api/annotations.upb.c
+  src/core/ext/upb-generated/google/api/annotations.upbdefs.c
   src/core/ext/upb-generated/google/api/http.upb.c
+  src/core/ext/upb-generated/google/api/http.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/any.upb.c
-  src/core/ext/upb-generated/google/protobuf/descriptor.upb.c
+  src/core/ext/upb-generated/google/protobuf/any.upbdefs.c
+  src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c
   src/core/ext/upb-generated/google/rpc/status.upb.c
+  src/core/ext/upb-generated/google/rpc/status.upbdefs.c
   src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c
   src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c
   src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c
   src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c
   src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
   src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
+  src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c
   src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
+  src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c
   src/core/ext/upb-generated/udpa/annotations/status.upb.c
+  src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c
   src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   src/core/ext/upb-generated/validate/validate.upb.c
+  src/core/ext/upb-generated/validate/validate.upbdefs.c
   src/core/lib/avl/avl.cc
   src/core/lib/backoff/backoff.cc
   src/core/lib/channel/channel_args.cc
@@ -1998,6 +2067,7 @@ add_library(grpc_unsecure
   src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc
   src/core/ext/filters/client_channel/global_subchannel_pool.cc
   src/core/ext/filters/client_channel/health/health_check_client.cc
   src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -2045,6 +2115,7 @@ add_library(grpc_unsecure
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/server_address.cc
   src/core/ext/filters/client_channel/service_config.cc
+  src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
   src/core/ext/filters/client_channel/service_config_parser.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_pool_interface.cc
@@ -2099,75 +2170,141 @@ add_library(grpc_unsecure
   src/core/ext/transport/inproc/inproc_plugin.cc
   src/core/ext/transport/inproc/inproc_transport.cc
   src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c
+  src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c
   src/core/ext/upb-generated/envoy/annotations/resource.upb.c
+  src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/lds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/listener.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/rds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/route.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c
   src/core/ext/upb-generated/envoy/api/v2/srds.upb.c
+  src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c
   src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
+  src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c
   src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
+  src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c
   src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
+  src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c
   src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
+  src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c
   src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
+  src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c
   src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
+  src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c
   src/core/ext/upb-generated/envoy/type/http.upb.c
+  src/core/ext/upb-generated/envoy/type/http.upbdefs.c
   src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c
+  src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c
   src/core/ext/upb-generated/envoy/type/matcher/string.upb.c
+  src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c
   src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c
+  src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c
   src/core/ext/upb-generated/envoy/type/percent.upb.c
+  src/core/ext/upb-generated/envoy/type/percent.upbdefs.c
   src/core/ext/upb-generated/envoy/type/range.upb.c
+  src/core/ext/upb-generated/envoy/type/range.upbdefs.c
   src/core/ext/upb-generated/envoy/type/semantic_version.upb.c
+  src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c
   src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c
+  src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c
   src/core/ext/upb-generated/gogoproto/gogo.upb.c
+  src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c
   src/core/ext/upb-generated/google/api/annotations.upb.c
+  src/core/ext/upb-generated/google/api/annotations.upbdefs.c
   src/core/ext/upb-generated/google/api/http.upb.c
+  src/core/ext/upb-generated/google/api/http.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/any.upb.c
-  src/core/ext/upb-generated/google/protobuf/descriptor.upb.c
+  src/core/ext/upb-generated/google/protobuf/any.upbdefs.c
+  src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c
   src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c
   src/core/ext/upb-generated/google/rpc/status.upb.c
+  src/core/ext/upb-generated/google/rpc/status.upbdefs.c
   src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c
   src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
   src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
+  src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c
   src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
+  src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c
   src/core/ext/upb-generated/udpa/annotations/status.upb.c
+  src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c
   src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   src/core/ext/upb-generated/validate/validate.upb.c
+  src/core/ext/upb-generated/validate/validate.upbdefs.c
   src/core/lib/avl/avl.cc
   src/core/lib/backoff/backoff.cc
   src/core/lib/channel/channel_args.cc
@@ -2481,6 +2618,7 @@ endif()
 
 add_library(grpc++
   src/cpp/client/channel_cc.cc
+  src/cpp/client/client_callback.cc
   src/cpp/client/client_context.cc
   src/cpp/client/client_interceptor.cc
   src/cpp/client/create_channel.cc
@@ -2661,7 +2799,6 @@ foreach(_hdr
   include/grpcpp/generic/generic_stub_impl.h
   include/grpcpp/grpcpp.h
   include/grpcpp/health_check_service_interface.h
-  include/grpcpp/health_check_service_interface_impl.h
   include/grpcpp/impl/call.h
   include/grpcpp/impl/channel_argument_option.h
   include/grpcpp/impl/client_unary_call.h
@@ -2736,7 +2873,6 @@ foreach(_hdr
   include/grpcpp/impl/server_initializer_impl.h
   include/grpcpp/impl/service_type.h
   include/grpcpp/resource_quota.h
-  include/grpcpp/resource_quota_impl.h
   include/grpcpp/security/auth_context.h
   include/grpcpp/security/auth_metadata_processor.h
   include/grpcpp/security/auth_metadata_processor_impl.h
@@ -3182,6 +3318,7 @@ endif()
 
 add_library(grpc++_unsecure
   src/cpp/client/channel_cc.cc
+  src/cpp/client/client_callback.cc
   src/cpp/client/client_context.cc
   src/cpp/client/client_interceptor.cc
   src/cpp/client/create_channel.cc
@@ -3355,7 +3492,6 @@ foreach(_hdr
   include/grpcpp/generic/generic_stub_impl.h
   include/grpcpp/grpcpp.h
   include/grpcpp/health_check_service_interface.h
-  include/grpcpp/health_check_service_interface_impl.h
   include/grpcpp/impl/call.h
   include/grpcpp/impl/channel_argument_option.h
   include/grpcpp/impl/client_unary_call.h
@@ -3430,7 +3566,6 @@ foreach(_hdr
   include/grpcpp/impl/server_initializer_impl.h
   include/grpcpp/impl/service_type.h
   include/grpcpp/resource_quota.h
-  include/grpcpp/resource_quota_impl.h
   include/grpcpp/security/auth_context.h
   include/grpcpp/security/auth_metadata_processor.h
   include/grpcpp/security/auth_metadata_processor_impl.h
@@ -3638,6 +3773,23 @@ add_library(upb
   third_party/upb/upb/port.c
   third_party/upb/upb/table.c
   third_party/upb/upb/upb.c
+  third_party/upb/upb/def.c
+  third_party/upb/upb/reflection.c
+  third_party/upb/upb/text_encode.c
+  src/core/ext/upb-generated/google/protobuf/any.upb.c
+  src/core/ext/upb-generated/google/protobuf/any.upbdefs.c
+  src/core/ext/upb-generated/google/protobuf/descriptor.upb.c
+  src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c
+  src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c
+  src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c
+  src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c
+  src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c
+  src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c
 )
 
 set_target_properties(upb PROPERTIES
@@ -6827,35 +6979,6 @@ target_link_libraries(sequential_connectivity_test
 )
 
 
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(server_chttp2_test
-  test/core/surface/server_chttp2_test.cc
-)
-
-target_include_directories(server_chttp2_test
-  PRIVATE
-    ${CMAKE_CURRENT_SOURCE_DIR}
-    ${CMAKE_CURRENT_SOURCE_DIR}/include
-    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-    ${_gRPC_SSL_INCLUDE_DIR}
-    ${_gRPC_UPB_GENERATED_DIR}
-    ${_gRPC_UPB_GRPC_GENERATED_DIR}
-    ${_gRPC_UPB_INCLUDE_DIR}
-    ${_gRPC_ZLIB_INCLUDE_DIR}
-)
-
-target_link_libraries(server_chttp2_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-  grpc
-  gpr
-  address_sorting
-  upb
-)
-
-
 endif()
 if(gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@@ -13001,6 +13124,44 @@ endif()
 endif()
 if(gRPC_BUILD_TESTS)
 
+add_executable(server_chttp2_test
+  test/core/surface/server_chttp2_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(server_chttp2_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(server_chttp2_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr
+  address_sorting
+  upb
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
 add_executable(server_context_test_spouse_test
   test/cpp/test/server_context_test_spouse_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -14128,6 +14289,48 @@ target_link_libraries(tls_security_connector_test
 )
 
 
+endif()
+if(gRPC_BUILD_TESTS)
+
+add_executable(too_many_pings_test
+  test/core/end2end/cq_verifier.cc
+  test/core/transport/chttp2/too_many_pings_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(too_many_pings_test
+  PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/include
+    ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+    ${_gRPC_SSL_INCLUDE_DIR}
+    ${_gRPC_UPB_GENERATED_DIR}
+    ${_gRPC_UPB_GRPC_GENERATED_DIR}
+    ${_gRPC_UPB_INCLUDE_DIR}
+    ${_gRPC_ZLIB_INCLUDE_DIR}
+    third_party/googletest/googletest/include
+    third_party/googletest/googletest
+    third_party/googletest/googlemock/include
+    third_party/googletest/googlemock
+    ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(too_many_pings_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc++_test_config
+  grpc
+  gpr
+  address_sorting
+  upb
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+
 endif()
 if(gRPC_BUILD_TESTS)
 
@@ -15081,7 +15284,7 @@ include(CMakePackageConfigHelpers)
 configure_file(cmake/gRPCConfig.cmake.in
   gRPCConfig.cmake @ONLY)
 write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/gRPCConfigVersion.cmake
-  VERSION ${PACKAGE_VERSION}
+  VERSION ${gRPC_CPP_VERSION}
   COMPATIBILITY AnyNewerVersion)
 install(FILES
     ${CMAKE_CURRENT_BINARY_DIR}/gRPCConfig.cmake
@@ -15148,7 +15351,7 @@ generate_pkgconfig(
 generate_pkgconfig(
   "gRPC++"
   "C++ wrapper for gRPC"
-  "${PACKAGE_VERSION}"
+  "${gRPC_CPP_VERSION}"
   "grpc"
   "-lgrpc++ -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
   ""
@@ -15158,7 +15361,7 @@ generate_pkgconfig(
 generate_pkgconfig(
   "gRPC++ unsecure"
   "C++ wrapper for gRPC without SSL"
-  "${PACKAGE_VERSION}"
+  "${gRPC_CPP_VERSION}"
   "grpc_unsecure"
   "-lgrpc++_unsecure -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
   ""

+ 278 - 64
Makefile

@@ -469,9 +469,9 @@ E = @echo
 Q = @
 endif
 
-CORE_VERSION = 10.0.0
-CPP_VERSION = 1.30.0-dev
-CSHARP_VERSION = 2.30.0-dev
+CORE_VERSION = 11.0.0
+CPP_VERSION = 1.31.0-dev
+CSHARP_VERSION = 2.31.0-dev
 
 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
 CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -519,7 +519,7 @@ SHARED_EXT_CORE = dll
 SHARED_EXT_CPP = dll
 SHARED_EXT_CSHARP = dll
 SHARED_PREFIX =
-SHARED_VERSION_CORE = -10
+SHARED_VERSION_CORE = -11
 SHARED_VERSION_CPP = -1
 SHARED_VERSION_CSHARP = -2
 else ifeq ($(SYSTEM),Darwin)
@@ -1112,7 +1112,6 @@ secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test
 secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test
 security_connector_test: $(BINDIR)/$(CONFIG)/security_connector_test
 sequential_connectivity_test: $(BINDIR)/$(CONFIG)/sequential_connectivity_test
-server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test
 server_ssl_test: $(BINDIR)/$(CONFIG)/server_ssl_test
 server_test: $(BINDIR)/$(CONFIG)/server_test
 slice_buffer_test: $(BINDIR)/$(CONFIG)/slice_buffer_test
@@ -1269,6 +1268,7 @@ secure_auth_context_test: $(BINDIR)/$(CONFIG)/secure_auth_context_test
 server_builder_plugin_test: $(BINDIR)/$(CONFIG)/server_builder_plugin_test
 server_builder_test: $(BINDIR)/$(CONFIG)/server_builder_test
 server_builder_with_socket_mutator_test: $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test
+server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test
 server_context_test_spouse_test: $(BINDIR)/$(CONFIG)/server_context_test_spouse_test
 server_early_return_test: $(BINDIR)/$(CONFIG)/server_early_return_test
 server_fuzzer: $(BINDIR)/$(CONFIG)/server_fuzzer
@@ -1297,6 +1297,7 @@ thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
 time_jump_test: $(BINDIR)/$(CONFIG)/time_jump_test
 timer_test: $(BINDIR)/$(CONFIG)/timer_test
 tls_security_connector_test: $(BINDIR)/$(CONFIG)/tls_security_connector_test
+too_many_pings_test: $(BINDIR)/$(CONFIG)/too_many_pings_test
 unknown_frame_bad_client_test: $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test
 uri_fuzzer_test: $(BINDIR)/$(CONFIG)/uri_fuzzer_test
 window_overflow_bad_client_test: $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test
@@ -1486,7 +1487,6 @@ buildtests_c: privatelibs_c \
   $(BINDIR)/$(CONFIG)/secure_endpoint_test \
   $(BINDIR)/$(CONFIG)/security_connector_test \
   $(BINDIR)/$(CONFIG)/sequential_connectivity_test \
-  $(BINDIR)/$(CONFIG)/server_chttp2_test \
   $(BINDIR)/$(CONFIG)/server_ssl_test \
   $(BINDIR)/$(CONFIG)/server_test \
   $(BINDIR)/$(CONFIG)/slice_buffer_test \
@@ -1630,6 +1630,7 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/server_builder_plugin_test \
   $(BINDIR)/$(CONFIG)/server_builder_test \
   $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test \
+  $(BINDIR)/$(CONFIG)/server_chttp2_test \
   $(BINDIR)/$(CONFIG)/server_context_test_spouse_test \
   $(BINDIR)/$(CONFIG)/server_early_return_test \
   $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test \
@@ -1656,6 +1657,7 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/time_jump_test \
   $(BINDIR)/$(CONFIG)/timer_test \
   $(BINDIR)/$(CONFIG)/tls_security_connector_test \
+  $(BINDIR)/$(CONFIG)/too_many_pings_test \
   $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \
   $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test \
   $(BINDIR)/$(CONFIG)/work_serializer_test \
@@ -1786,6 +1788,7 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/server_builder_plugin_test \
   $(BINDIR)/$(CONFIG)/server_builder_test \
   $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test \
+  $(BINDIR)/$(CONFIG)/server_chttp2_test \
   $(BINDIR)/$(CONFIG)/server_context_test_spouse_test \
   $(BINDIR)/$(CONFIG)/server_early_return_test \
   $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test \
@@ -1812,6 +1815,7 @@ buildtests_cxx: privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/time_jump_test \
   $(BINDIR)/$(CONFIG)/timer_test \
   $(BINDIR)/$(CONFIG)/tls_security_connector_test \
+  $(BINDIR)/$(CONFIG)/too_many_pings_test \
   $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test \
   $(BINDIR)/$(CONFIG)/window_overflow_bad_client_test \
   $(BINDIR)/$(CONFIG)/work_serializer_test \
@@ -2040,8 +2044,6 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/secure_endpoint_test || ( echo test secure_endpoint_test failed ; exit 1 )
 	$(E) "[RUN]     Testing security_connector_test"
 	$(Q) $(BINDIR)/$(CONFIG)/security_connector_test || ( echo test security_connector_test failed ; exit 1 )
-	$(E) "[RUN]     Testing server_chttp2_test"
-	$(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_ssl_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_ssl_test || ( echo test server_ssl_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_test"
@@ -2296,6 +2298,8 @@ test_cxx: buildtests_cxx
 	$(Q) $(BINDIR)/$(CONFIG)/server_builder_test || ( echo test server_builder_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_builder_with_socket_mutator_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test || ( echo test server_builder_with_socket_mutator_test failed ; exit 1 )
+	$(E) "[RUN]     Testing server_chttp2_test"
+	$(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_context_test_spouse_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_context_test_spouse_test || ( echo test server_context_test_spouse_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_early_return_test"
@@ -2344,6 +2348,8 @@ test_cxx: buildtests_cxx
 	$(Q) $(BINDIR)/$(CONFIG)/timer_test || ( echo test timer_test failed ; exit 1 )
 	$(E) "[RUN]     Testing tls_security_connector_test"
 	$(Q) $(BINDIR)/$(CONFIG)/tls_security_connector_test || ( echo test tls_security_connector_test failed ; exit 1 )
+	$(E) "[RUN]     Testing too_many_pings_test"
+	$(Q) $(BINDIR)/$(CONFIG)/too_many_pings_test || ( echo test too_many_pings_test failed ; exit 1 )
 	$(E) "[RUN]     Testing unknown_frame_bad_client_test"
 	$(Q) $(BINDIR)/$(CONFIG)/unknown_frame_bad_client_test || ( echo test unknown_frame_bad_client_test failed ; exit 1 )
 	$(E) "[RUN]     Testing window_overflow_bad_client_test"
@@ -3037,7 +3043,7 @@ install-shared_c: shared_c strip-shared_c install-pkg-config_c
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libaddress_sorting.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libaddress_sorting.so.10
+	$(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libaddress_sorting.so.11
 	$(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libaddress_sorting.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3046,7 +3052,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgpr.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.10
+	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.11
 	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3055,7 +3061,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.10
+	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.11
 	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3064,7 +3070,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_csharp_ext.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_csharp_ext.so.10
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_csharp_ext.so.11
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_csharp_ext.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3073,7 +3079,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_unsecure.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.10
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.11
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3082,7 +3088,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libupb.a
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libupb.so.10
+	$(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libupb.so.11
 	$(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libupb.so
 endif
 ifneq ($(SYSTEM),MINGW32)
@@ -3243,8 +3249,8 @@ $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE):
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libaddress_sorting.so.10 -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so.10
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libaddress_sorting.so.11 -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+	$(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so.11
 	$(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -3605,8 +3611,8 @@ $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OB
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.10 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.10
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.11 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.11
 	$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -3625,6 +3631,7 @@ LIBGRPC_SRC = \
     src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc \
     src/core/ext/filters/client_channel/global_subchannel_pool.cc \
     src/core/ext/filters/client_channel/health/health_check_client.cc \
     src/core/ext/filters/client_channel/http_connect_handshaker.cc \
@@ -3672,6 +3679,7 @@ LIBGRPC_SRC = \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
     src/core/ext/filters/client_channel/service_config.cc \
+    src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
     src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
@@ -3728,78 +3736,144 @@ LIBGRPC_SRC = \
     src/core/ext/transport/inproc/inproc_plugin.cc \
     src/core/ext/transport/inproc/inproc_transport.cc \
     src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \
+    src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c \
     src/core/ext/upb-generated/envoy/annotations/resource.upb.c \
+    src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/eds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/lds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/rds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/srds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c \
+    src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c \
+    src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c \
+    src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c \
+    src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c \
     src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c \
+    src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c \
     src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c \
+    src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/http.upb.c \
+    src/core/ext/upb-generated/envoy/type/http.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c \
+    src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/matcher/string.upb.c \
+    src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c \
+    src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/percent.upb.c \
+    src/core/ext/upb-generated/envoy/type/percent.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/range.upb.c \
+    src/core/ext/upb-generated/envoy/type/range.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/semantic_version.upb.c \
+    src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c \
+    src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c \
     src/core/ext/upb-generated/gogoproto/gogo.upb.c \
+    src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c \
     src/core/ext/upb-generated/google/api/annotations.upb.c \
+    src/core/ext/upb-generated/google/api/annotations.upbdefs.c \
     src/core/ext/upb-generated/google/api/http.upb.c \
+    src/core/ext/upb-generated/google/api/http.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/any.upb.c \
-    src/core/ext/upb-generated/google/protobuf/descriptor.upb.c \
+    src/core/ext/upb-generated/google/protobuf/any.upbdefs.c \
+    src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/duration.upb.c \
+    src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/empty.upb.c \
+    src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/struct.upb.c \
+    src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/timestamp.upb.c \
+    src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/wrappers.upb.c \
+    src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c \
     src/core/ext/upb-generated/google/rpc/status.upb.c \
+    src/core/ext/upb-generated/google/rpc/status.upbdefs.c \
     src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
     src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c \
     src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c \
     src/core/ext/upb-generated/udpa/annotations/status.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c \
     src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
+    src/core/ext/upb-generated/validate/validate.upbdefs.c \
     src/core/lib/avl/avl.cc \
     src/core/lib/backoff/backoff.cc \
     src/core/lib/channel/channel_args.cc \
@@ -4087,8 +4161,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.10 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
-	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.10
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.11 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
+	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.11
 	$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -4144,8 +4218,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE):
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgrpc -lgpr -laddress_sorting -lupb
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.10 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgrpc -lgpr -laddress_sorting -lupb
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so.10
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.11 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgrpc -lgpr -laddress_sorting -lupb
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so.11
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -4270,6 +4344,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc \
     src/core/ext/filters/client_channel/global_subchannel_pool.cc \
     src/core/ext/filters/client_channel/health/health_check_client.cc \
     src/core/ext/filters/client_channel/http_connect_handshaker.cc \
@@ -4317,6 +4392,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
     src/core/ext/filters/client_channel/service_config.cc \
+    src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
     src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
@@ -4371,75 +4447,141 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/transport/inproc/inproc_plugin.cc \
     src/core/ext/transport/inproc/inproc_transport.cc \
     src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \
+    src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c \
     src/core/ext/upb-generated/envoy/annotations/resource.upb.c \
+    src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/eds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/lds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/rds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/srds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c \
+    src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c \
+    src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c \
+    src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c \
+    src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c \
     src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c \
+    src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c \
     src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c \
+    src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/http.upb.c \
+    src/core/ext/upb-generated/envoy/type/http.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c \
+    src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/matcher/string.upb.c \
+    src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c \
+    src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/percent.upb.c \
+    src/core/ext/upb-generated/envoy/type/percent.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/range.upb.c \
+    src/core/ext/upb-generated/envoy/type/range.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/semantic_version.upb.c \
+    src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c \
+    src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c \
     src/core/ext/upb-generated/gogoproto/gogo.upb.c \
+    src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c \
     src/core/ext/upb-generated/google/api/annotations.upb.c \
+    src/core/ext/upb-generated/google/api/annotations.upbdefs.c \
     src/core/ext/upb-generated/google/api/http.upb.c \
+    src/core/ext/upb-generated/google/api/http.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/any.upb.c \
-    src/core/ext/upb-generated/google/protobuf/descriptor.upb.c \
+    src/core/ext/upb-generated/google/protobuf/any.upbdefs.c \
+    src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/duration.upb.c \
+    src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/empty.upb.c \
+    src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/struct.upb.c \
+    src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/timestamp.upb.c \
+    src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/wrappers.upb.c \
+    src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c \
     src/core/ext/upb-generated/google/rpc/status.upb.c \
+    src/core/ext/upb-generated/google/rpc/status.upbdefs.c \
     src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
     src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c \
     src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c \
     src/core/ext/upb-generated/udpa/annotations/status.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c \
     src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
+    src/core/ext/upb-generated/validate/validate.upbdefs.c \
     src/core/lib/avl/avl.cc \
     src/core/lib/backoff/backoff.cc \
     src/core/lib/channel/channel_args.cc \
@@ -4645,8 +4787,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.10 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.10
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.11 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.11
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -4712,6 +4854,7 @@ $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/helpers.o: $(GENDIR)/src/proto/grpc
 
 LIBGRPC++_SRC = \
     src/cpp/client/channel_cc.cc \
+    src/cpp/client/client_callback.cc \
     src/cpp/client/client_context.cc \
     src/cpp/client/client_interceptor.cc \
     src/cpp/client/create_channel.cc \
@@ -4853,7 +4996,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpcpp/generic/generic_stub_impl.h \
     include/grpcpp/grpcpp.h \
     include/grpcpp/health_check_service_interface.h \
-    include/grpcpp/health_check_service_interface_impl.h \
     include/grpcpp/impl/call.h \
     include/grpcpp/impl/channel_argument_option.h \
     include/grpcpp/impl/client_unary_call.h \
@@ -4928,7 +5070,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpcpp/impl/server_initializer_impl.h \
     include/grpcpp/impl/service_type.h \
     include/grpcpp/resource_quota.h \
-    include/grpcpp/resource_quota_impl.h \
     include/grpcpp/security/auth_context.h \
     include/grpcpp/security/auth_metadata_processor.h \
     include/grpcpp/security/auth_metadata_processor_impl.h \
@@ -5418,6 +5559,7 @@ endif
 
 LIBGRPC++_UNSECURE_SRC = \
     src/cpp/client/channel_cc.cc \
+    src/cpp/client/client_callback.cc \
     src/cpp/client/client_context.cc \
     src/cpp/client/client_interceptor.cc \
     src/cpp/client/create_channel.cc \
@@ -5552,7 +5694,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpcpp/generic/generic_stub_impl.h \
     include/grpcpp/grpcpp.h \
     include/grpcpp/health_check_service_interface.h \
-    include/grpcpp/health_check_service_interface_impl.h \
     include/grpcpp/impl/call.h \
     include/grpcpp/impl/channel_argument_option.h \
     include/grpcpp/impl/client_unary_call.h \
@@ -5627,7 +5768,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpcpp/impl/server_initializer_impl.h \
     include/grpcpp/impl/service_type.h \
     include/grpcpp/resource_quota.h \
-    include/grpcpp/resource_quota_impl.h \
     include/grpcpp/security/auth_context.h \
     include/grpcpp/security/auth_metadata_processor.h \
     include/grpcpp/security/auth_metadata_processor_impl.h \
@@ -6237,6 +6377,23 @@ LIBUPB_SRC = \
     third_party/upb/upb/port.c \
     third_party/upb/upb/table.c \
     third_party/upb/upb/upb.c \
+    third_party/upb/upb/def.c \
+    third_party/upb/upb/reflection.c \
+    third_party/upb/upb/text_encode.c \
+    src/core/ext/upb-generated/google/protobuf/any.upb.c \
+    src/core/ext/upb-generated/google/protobuf/any.upbdefs.c \
+    src/core/ext/upb-generated/google/protobuf/descriptor.upb.c \
+    src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c \
+    src/core/ext/upb-generated/google/protobuf/duration.upb.c \
+    src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c \
+    src/core/ext/upb-generated/google/protobuf/empty.upb.c \
+    src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c \
+    src/core/ext/upb-generated/google/protobuf/struct.upb.c \
+    src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c \
+    src/core/ext/upb-generated/google/protobuf/timestamp.upb.c \
+    src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c \
+    src/core/ext/upb-generated/google/protobuf/wrappers.upb.c \
+    src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c \
 
 PUBLIC_HEADERS_C += \
 
@@ -6266,8 +6423,8 @@ $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBUPB_OB
 ifeq ($(SYSTEM),Darwin)
 	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libupb.so.10 -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
-	$(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so.10
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libupb.so.11 -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+	$(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so.11
 	$(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so
 endif
 endif
@@ -10049,38 +10206,6 @@ endif
 endif
 
 
-SERVER_CHTTP2_TEST_SRC = \
-    test/core/surface/server_chttp2_test.cc \
-
-SERVER_CHTTP2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CHTTP2_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/server_chttp2_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/server_chttp2_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/surface/server_chttp2_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-deps_server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(SERVER_CHTTP2_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 SERVER_SSL_TEST_SRC = \
     test/core/handshake/server_ssl.cc \
     test/core/handshake/server_ssl_common.cc \
@@ -17216,6 +17341,49 @@ endif
 $(OBJDIR)/$(CONFIG)/test/cpp/server/server_builder_with_socket_mutator_test.o: $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/simple_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/simple_messages.grpc.pb.cc
 
 
+SERVER_CHTTP2_TEST_SRC = \
+    test/core/surface/server_chttp2_test.cc \
+
+SERVER_CHTTP2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CHTTP2_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/server_chttp2_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)/server_chttp2_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/server_chttp2_test: $(PROTOBUF_DEP) $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_chttp2_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/surface/server_chttp2_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
+
+deps_server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(SERVER_CHTTP2_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 SERVER_CONTEXT_TEST_SPOUSE_TEST_SRC = \
     test/cpp/test/server_context_test_spouse_test.cc \
 
@@ -18532,6 +18700,52 @@ endif
 endif
 
 
+TOO_MANY_PINGS_TEST_SRC = \
+    test/core/end2end/cq_verifier.cc \
+    test/core/transport/chttp2/too_many_pings_test.cc \
+
+TOO_MANY_PINGS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TOO_MANY_PINGS_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/too_many_pings_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)/too_many_pings_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/too_many_pings_test: $(PROTOBUF_DEP) $(TOO_MANY_PINGS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(TOO_MANY_PINGS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/too_many_pings_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/end2end/cq_verifier.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
+
+$(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/too_many_pings_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
+
+deps_too_many_pings_test: $(TOO_MANY_PINGS_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(TOO_MANY_PINGS_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 UNKNOWN_FRAME_BAD_CLIENT_TEST_SRC = \
     test/core/bad_client/bad_client.cc \
     test/core/bad_client/tests/unknown_frame.cc \

+ 1 - 1
Rakefile

@@ -142,7 +142,7 @@ task 'gem:native' do
 
         gem update --system --no-document && \
         bundle && \
-        rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem \
+        rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem pkg/#{spec.full_name}.gem \
           RUBY_CC_VERSION=2.7.0:2.6.0:2.5.0:2.4.0:2.3.0 \
           V=#{verbose} \
           GRPC_CONFIG=#{grpc_config}

+ 18 - 7
bazel/grpc_deps.bzl

@@ -11,6 +11,16 @@ def grpc_deps():
         actual = "@upb//:upb",
     )
 
+    native.bind(
+        name = "upb_lib_descriptor",
+        actual = "@upb//:descriptor_upb_proto",
+    )
+
+    native.bind(
+        name = "upb_textformat_lib",
+        actual = "@upb//:textformat",
+    )
+
     native.bind(
         name = "absl",
         actual = "@com_google_absl//absl",
@@ -63,7 +73,7 @@ def grpc_deps():
 
     native.bind(
         name = "gtest",
-        actual = "@com_github_google_googletest//:gtest",
+        actual = "@com_google_googletest//:gtest",
     )
 
     native.bind(
@@ -162,9 +172,9 @@ def grpc_deps():
             ],
         )
 
-    if "com_github_google_googletest" not in native.existing_rules():
+    if "com_google_googletest" not in native.existing_rules():
         http_archive(
-            name = "com_github_google_googletest",
+            name = "com_google_googletest",
             sha256 = "443d383db648ebb8e391382c0ab63263b7091d03197f304390baac10f178a468",
             strip_prefix = "googletest-c9ccac7cb7345901884aabf5d1a786cfa6e2f397",
             urls = [
@@ -263,14 +273,15 @@ def grpc_deps():
                 "https://github.com/census-instrumentation/opencensus-cpp/archive/c9a4da319bc669a772928ffc55af4a61be1a1176.tar.gz",
             ],
         )
+
     if "upb" not in native.existing_rules():
         http_archive(
             name = "upb",
-            sha256 = "e9c136e56b98c8eb48ad1c9f8df4a6348e99f9f336ee6199c4259a312c2e3598",
-            strip_prefix = "upb-d8f3d6f9d415b31f3ce56d46791706c38fa311bc",
+            sha256 = "79f7de61203c4ee5e4fcb2f17c5f3338119d6eb94aca8bce05332d2c1cfee108",
+            strip_prefix = "upb-92e63da73328d01b417cf26c2de7b0a27a0f83af",
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/upb/archive/d8f3d6f9d415b31f3ce56d46791706c38fa311bc.tar.gz",
-                "https://github.com/protocolbuffers/upb/archive/d8f3d6f9d415b31f3ce56d46791706c38fa311bc.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/upb/archive/92e63da73328d01b417cf26c2de7b0a27a0f83af.tar.gz",
+                "https://github.com/protocolbuffers/upb/archive/92e63da73328d01b417cf26c2de7b0a27a0f83af.tar.gz",
             ],
         )
 

+ 307 - 20
build_autogenerated.yaml

@@ -377,6 +377,7 @@ libs:
   - src/core/ext/filters/client_channel/client_channel.h
   - src/core/ext/filters/client_channel/client_channel_channelz.h
   - src/core/ext/filters/client_channel/client_channel_factory.h
+  - src/core/ext/filters/client_channel/config_selector.h
   - src/core/ext/filters/client_channel/connector.h
   - src/core/ext/filters/client_channel/global_subchannel_pool.h
   - src/core/ext/filters/client_channel/health/health_check_client.h
@@ -459,78 +460,144 @@ libs:
   - src/core/ext/transport/chttp2/transport/varint.h
   - src/core/ext/transport/inproc/inproc_transport.h
   - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h
+  - src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h
   - src/core/ext/upb-generated/envoy/annotations/resource.upb.h
+  - src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/eds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/lds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/listener.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/rds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/route.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/srds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h
   - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h
+  - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h
   - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h
+  - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h
   - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h
+  - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h
   - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h
+  - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h
   - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h
+  - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h
   - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h
+  - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/http.upb.h
+  - src/core/ext/upb-generated/envoy/type/http.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h
+  - src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/matcher/string.upb.h
+  - src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h
+  - src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/percent.upb.h
+  - src/core/ext/upb-generated/envoy/type/percent.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/range.upb.h
+  - src/core/ext/upb-generated/envoy/type/range.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/semantic_version.upb.h
+  - src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h
+  - src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h
   - src/core/ext/upb-generated/gogoproto/gogo.upb.h
+  - src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h
   - src/core/ext/upb-generated/google/api/annotations.upb.h
+  - src/core/ext/upb-generated/google/api/annotations.upbdefs.h
   - src/core/ext/upb-generated/google/api/http.upb.h
+  - src/core/ext/upb-generated/google/api/http.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/any.upb.h
-  - src/core/ext/upb-generated/google/protobuf/descriptor.upb.h
+  - src/core/ext/upb-generated/google/protobuf/any.upbdefs.h
+  - src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/duration.upb.h
+  - src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/empty.upb.h
+  - src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/struct.upb.h
+  - src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/timestamp.upb.h
+  - src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/wrappers.upb.h
+  - src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h
   - src/core/ext/upb-generated/google/rpc/status.upb.h
+  - src/core/ext/upb-generated/google/rpc/status.upbdefs.h
   - src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h
   - src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h
   - src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h
   - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.h
+  - src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h
+  - src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h
   - src/core/ext/upb-generated/udpa/annotations/status.upb.h
+  - src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h
   - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
   - src/core/ext/upb-generated/validate/validate.upb.h
+  - src/core/ext/upb-generated/validate/validate.upbdefs.h
   - src/core/lib/avl/avl.h
   - src/core/lib/backoff/backoff.h
   - src/core/lib/channel/channel_args.h
@@ -746,6 +813,7 @@ libs:
   - src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc
   - src/core/ext/filters/client_channel/global_subchannel_pool.cc
   - src/core/ext/filters/client_channel/health/health_check_client.cc
   - src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -793,6 +861,7 @@ libs:
   - src/core/ext/filters/client_channel/retry_throttle.cc
   - src/core/ext/filters/client_channel/server_address.cc
   - src/core/ext/filters/client_channel/service_config.cc
+  - src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
   - src/core/ext/filters/client_channel/service_config_parser.cc
   - src/core/ext/filters/client_channel/subchannel.cc
   - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
@@ -849,78 +918,144 @@ libs:
   - src/core/ext/transport/inproc/inproc_plugin.cc
   - src/core/ext/transport/inproc/inproc_transport.cc
   - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c
+  - src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c
   - src/core/ext/upb-generated/envoy/annotations/resource.upb.c
+  - src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/lds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/listener.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/rds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/route.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/srds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c
   - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
+  - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c
   - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
+  - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c
   - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
+  - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c
   - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
+  - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c
   - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
+  - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c
   - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
+  - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/http.upb.c
+  - src/core/ext/upb-generated/envoy/type/http.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c
+  - src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/matcher/string.upb.c
+  - src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c
+  - src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/percent.upb.c
+  - src/core/ext/upb-generated/envoy/type/percent.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/range.upb.c
+  - src/core/ext/upb-generated/envoy/type/range.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/semantic_version.upb.c
+  - src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c
+  - src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c
   - src/core/ext/upb-generated/gogoproto/gogo.upb.c
+  - src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c
   - src/core/ext/upb-generated/google/api/annotations.upb.c
+  - src/core/ext/upb-generated/google/api/annotations.upbdefs.c
   - src/core/ext/upb-generated/google/api/http.upb.c
+  - src/core/ext/upb-generated/google/api/http.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/any.upb.c
-  - src/core/ext/upb-generated/google/protobuf/descriptor.upb.c
+  - src/core/ext/upb-generated/google/protobuf/any.upbdefs.c
+  - src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  - src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  - src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  - src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  - src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  - src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c
   - src/core/ext/upb-generated/google/rpc/status.upb.c
+  - src/core/ext/upb-generated/google/rpc/status.upbdefs.c
   - src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c
   - src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c
   - src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c
   - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
+  - src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
+  - src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c
   - src/core/ext/upb-generated/udpa/annotations/status.upb.c
+  - src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c
   - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   - src/core/ext/upb-generated/validate/validate.upb.c
+  - src/core/ext/upb-generated/validate/validate.upbdefs.c
   - src/core/lib/avl/avl.cc
   - src/core/lib/backoff/backoff.cc
   - src/core/lib/channel/channel_args.cc
@@ -1300,6 +1435,7 @@ libs:
   - src/core/ext/filters/client_channel/client_channel.h
   - src/core/ext/filters/client_channel/client_channel_channelz.h
   - src/core/ext/filters/client_channel/client_channel_factory.h
+  - src/core/ext/filters/client_channel/config_selector.h
   - src/core/ext/filters/client_channel/connector.h
   - src/core/ext/filters/client_channel/global_subchannel_pool.h
   - src/core/ext/filters/client_channel/health/health_check_client.h
@@ -1382,75 +1518,141 @@ libs:
   - src/core/ext/transport/chttp2/transport/varint.h
   - src/core/ext/transport/inproc/inproc_transport.h
   - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h
+  - src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h
   - src/core/ext/upb-generated/envoy/annotations/resource.upb.h
+  - src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/eds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/lds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/listener.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/rds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/route.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h
   - src/core/ext/upb-generated/envoy/api/v2/srds.upb.h
+  - src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h
   - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h
+  - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h
   - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h
+  - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h
   - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h
+  - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h
   - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h
+  - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h
   - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h
+  - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h
   - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h
+  - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/http.upb.h
+  - src/core/ext/upb-generated/envoy/type/http.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h
+  - src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/matcher/string.upb.h
+  - src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h
+  - src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/percent.upb.h
+  - src/core/ext/upb-generated/envoy/type/percent.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/range.upb.h
+  - src/core/ext/upb-generated/envoy/type/range.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/semantic_version.upb.h
+  - src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h
   - src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h
+  - src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h
   - src/core/ext/upb-generated/gogoproto/gogo.upb.h
+  - src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h
   - src/core/ext/upb-generated/google/api/annotations.upb.h
+  - src/core/ext/upb-generated/google/api/annotations.upbdefs.h
   - src/core/ext/upb-generated/google/api/http.upb.h
+  - src/core/ext/upb-generated/google/api/http.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/any.upb.h
-  - src/core/ext/upb-generated/google/protobuf/descriptor.upb.h
+  - src/core/ext/upb-generated/google/protobuf/any.upbdefs.h
+  - src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/duration.upb.h
+  - src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/empty.upb.h
+  - src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/struct.upb.h
+  - src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/timestamp.upb.h
+  - src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h
   - src/core/ext/upb-generated/google/protobuf/wrappers.upb.h
+  - src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h
   - src/core/ext/upb-generated/google/rpc/status.upb.h
+  - src/core/ext/upb-generated/google/rpc/status.upbdefs.h
   - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.h
+  - src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h
+  - src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h
   - src/core/ext/upb-generated/udpa/annotations/status.upb.h
+  - src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h
   - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h
   - src/core/ext/upb-generated/validate/validate.upb.h
+  - src/core/ext/upb-generated/validate/validate.upbdefs.h
   - src/core/lib/avl/avl.h
   - src/core/lib/backoff/backoff.h
   - src/core/lib/channel/channel_args.h
@@ -1605,6 +1807,7 @@ libs:
   - src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc
   - src/core/ext/filters/client_channel/global_subchannel_pool.cc
   - src/core/ext/filters/client_channel/health/health_check_client.cc
   - src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -1652,6 +1855,7 @@ libs:
   - src/core/ext/filters/client_channel/retry_throttle.cc
   - src/core/ext/filters/client_channel/server_address.cc
   - src/core/ext/filters/client_channel/service_config.cc
+  - src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
   - src/core/ext/filters/client_channel/service_config_parser.cc
   - src/core/ext/filters/client_channel/subchannel.cc
   - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
@@ -1706,75 +1910,141 @@ libs:
   - src/core/ext/transport/inproc/inproc_plugin.cc
   - src/core/ext/transport/inproc/inproc_transport.cc
   - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c
+  - src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c
   - src/core/ext/upb-generated/envoy/annotations/resource.upb.c
+  - src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/eds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/lds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/listener.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/rds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/route.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c
   - src/core/ext/upb-generated/envoy/api/v2/srds.upb.c
+  - src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c
   - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c
+  - src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c
   - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c
+  - src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c
   - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c
+  - src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c
   - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c
+  - src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c
   - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c
+  - src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c
   - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c
+  - src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/http.upb.c
+  - src/core/ext/upb-generated/envoy/type/http.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c
+  - src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/matcher/string.upb.c
+  - src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c
+  - src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/percent.upb.c
+  - src/core/ext/upb-generated/envoy/type/percent.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/range.upb.c
+  - src/core/ext/upb-generated/envoy/type/range.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/semantic_version.upb.c
+  - src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c
   - src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c
+  - src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c
   - src/core/ext/upb-generated/gogoproto/gogo.upb.c
+  - src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c
   - src/core/ext/upb-generated/google/api/annotations.upb.c
+  - src/core/ext/upb-generated/google/api/annotations.upbdefs.c
   - src/core/ext/upb-generated/google/api/http.upb.c
+  - src/core/ext/upb-generated/google/api/http.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/any.upb.c
-  - src/core/ext/upb-generated/google/protobuf/descriptor.upb.c
+  - src/core/ext/upb-generated/google/protobuf/any.upbdefs.c
+  - src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/duration.upb.c
+  - src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/empty.upb.c
+  - src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/struct.upb.c
+  - src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c
+  - src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c
   - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c
+  - src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c
   - src/core/ext/upb-generated/google/rpc/status.upb.c
+  - src/core/ext/upb-generated/google/rpc/status.upbdefs.c
   - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c
   - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
   - src/core/ext/upb-generated/udpa/annotations/migrate.upb.c
+  - src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c
   - src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c
+  - src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c
   - src/core/ext/upb-generated/udpa/annotations/status.upb.c
+  - src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c
   - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c
   - src/core/ext/upb-generated/validate/validate.upb.c
+  - src/core/ext/upb-generated/validate/validate.upbdefs.c
   - src/core/lib/avl/avl.cc
   - src/core/lib/backoff/backoff.cc
   - src/core/lib/channel/channel_args.cc
@@ -2070,7 +2340,6 @@ libs:
   - include/grpcpp/generic/generic_stub_impl.h
   - include/grpcpp/grpcpp.h
   - include/grpcpp/health_check_service_interface.h
-  - include/grpcpp/health_check_service_interface_impl.h
   - include/grpcpp/impl/call.h
   - include/grpcpp/impl/channel_argument_option.h
   - include/grpcpp/impl/client_unary_call.h
@@ -2145,7 +2414,6 @@ libs:
   - include/grpcpp/impl/server_initializer_impl.h
   - include/grpcpp/impl/service_type.h
   - include/grpcpp/resource_quota.h
-  - include/grpcpp/resource_quota_impl.h
   - include/grpcpp/security/auth_context.h
   - include/grpcpp/security/auth_metadata_processor.h
   - include/grpcpp/security/auth_metadata_processor_impl.h
@@ -2203,6 +2471,7 @@ libs:
   - src/cpp/thread_manager/thread_manager.h
   src:
   - src/cpp/client/channel_cc.cc
+  - src/cpp/client/client_callback.cc
   - src/cpp/client/client_context.cc
   - src/cpp/client/client_interceptor.cc
   - src/cpp/client/create_channel.cc
@@ -2463,7 +2732,6 @@ libs:
   - include/grpcpp/generic/generic_stub_impl.h
   - include/grpcpp/grpcpp.h
   - include/grpcpp/health_check_service_interface.h
-  - include/grpcpp/health_check_service_interface_impl.h
   - include/grpcpp/impl/call.h
   - include/grpcpp/impl/channel_argument_option.h
   - include/grpcpp/impl/client_unary_call.h
@@ -2538,7 +2806,6 @@ libs:
   - include/grpcpp/impl/server_initializer_impl.h
   - include/grpcpp/impl/service_type.h
   - include/grpcpp/resource_quota.h
-  - include/grpcpp/resource_quota_impl.h
   - include/grpcpp/security/auth_context.h
   - include/grpcpp/security/auth_metadata_processor.h
   - include/grpcpp/security/auth_metadata_processor_impl.h
@@ -2592,6 +2859,7 @@ libs:
   - src/cpp/thread_manager/thread_manager.h
   src:
   - src/cpp/client/channel_cc.cc
+  - src/cpp/client/client_callback.cc
   - src/cpp/client/client_context.cc
   - src/cpp/client/client_interceptor.cc
   - src/cpp/client/create_channel.cc
@@ -4134,18 +4402,6 @@ targets:
   - gpr
   - address_sorting
   - upb
-- name: server_chttp2_test
-  build: test
-  language: c
-  headers: []
-  src:
-  - test/core/surface/server_chttp2_test.cc
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr
-  - address_sorting
-  - upb
 - name: server_ssl_test
   build: test
   language: c
@@ -6930,6 +7186,19 @@ targets:
   - linux
   - posix
   - mac
+- name: server_chttp2_test
+  gtest: true
+  build: test
+  language: c++
+  headers: []
+  src:
+  - test/core/surface/server_chttp2_test.cc
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr
+  - address_sorting
+  - upb
 - name: server_context_test_spouse_test
   gtest: true
   build: test
@@ -7395,6 +7664,24 @@ targets:
   - gpr
   - address_sorting
   - upb
+- name: too_many_pings_test
+  gtest: true
+  build: test
+  language: c++
+  headers:
+  - test/core/end2end/cq_verifier.h
+  src:
+  - test/core/end2end/cq_verifier.cc
+  - test/core/transport/chttp2/too_many_pings_test.cc
+  deps:
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc++_test_config
+  - grpc
+  - gpr
+  - address_sorting
+  - upb
 - name: unknown_frame_bad_client_test
   gtest: true
   build: test

+ 1 - 1
build_config.rb

@@ -13,5 +13,5 @@
 # limitations under the License.
 
 module GrpcBuildConfig
-  CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-10.dll'
+  CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-11.dll'
 end

+ 3 - 3
build_handwritten.yaml

@@ -12,10 +12,10 @@ settings:
   '#08': Use "-preN" suffixes to identify pre-release versions
   '#09': Per-language overrides are possible with (eg) ruby_version tag here
   '#10': See the expand_version.py for all the quirks here
-  core_version: 10.0.0
+  core_version: 11.0.0
   csharp_major_version: 2
-  g_stands_for: gradius
-  version: 1.30.0-dev
+  g_stands_for: galore
+  version: 1.31.0-dev
 targets:
 - name: check_epollexclusive
   build: tool

+ 72 - 0
config.m4

@@ -45,6 +45,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc \
     src/core/ext/filters/client_channel/global_subchannel_pool.cc \
     src/core/ext/filters/client_channel/health/health_check_client.cc \
     src/core/ext/filters/client_channel/http_connect_handshaker.cc \
@@ -92,6 +93,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/server_address.cc \
     src/core/ext/filters/client_channel/service_config.cc \
+    src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
     src/core/ext/filters/client_channel/service_config_parser.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
@@ -148,78 +150,145 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/transport/inproc/inproc_plugin.cc \
     src/core/ext/transport/inproc/inproc_transport.cc \
     src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \
+    src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c \
     src/core/ext/upb-generated/envoy/annotations/resource.upb.c \
+    src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/eds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/lds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/rds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c \
     src/core/ext/upb-generated/envoy/api/v2/srds.upb.c \
+    src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c \
+    src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c \
+    src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c \
+    src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c \
     src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c \
+    src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c \
     src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c \
+    src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c \
     src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c \
+    src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/http.upb.c \
+    src/core/ext/upb-generated/envoy/type/http.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c \
+    src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/matcher/string.upb.c \
+    src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c \
+    src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/percent.upb.c \
+    src/core/ext/upb-generated/envoy/type/percent.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/range.upb.c \
+    src/core/ext/upb-generated/envoy/type/range.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/semantic_version.upb.c \
+    src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c \
     src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c \
+    src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c \
     src/core/ext/upb-generated/gogoproto/gogo.upb.c \
+    src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c \
     src/core/ext/upb-generated/google/api/annotations.upb.c \
+    src/core/ext/upb-generated/google/api/annotations.upbdefs.c \
     src/core/ext/upb-generated/google/api/http.upb.c \
+    src/core/ext/upb-generated/google/api/http.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/any.upb.c \
+    src/core/ext/upb-generated/google/protobuf/any.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/descriptor.upb.c \
+    src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/duration.upb.c \
+    src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/empty.upb.c \
+    src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/struct.upb.c \
+    src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/timestamp.upb.c \
+    src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c \
     src/core/ext/upb-generated/google/protobuf/wrappers.upb.c \
+    src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c \
     src/core/ext/upb-generated/google/rpc/status.upb.c \
+    src/core/ext/upb-generated/google/rpc/status.upbdefs.c \
     src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \
     src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
     src/core/ext/upb-generated/udpa/annotations/migrate.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c \
     src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c \
     src/core/ext/upb-generated/udpa/annotations/status.upb.c \
+    src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c \
     src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \
     src/core/ext/upb-generated/validate/validate.upb.c \
+    src/core/ext/upb-generated/validate/validate.upbdefs.c \
     src/core/lib/avl/avl.cc \
     src/core/lib/backoff/backoff.cc \
     src/core/lib/channel/channel_args.cc \
@@ -824,10 +893,13 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl-with-bazel/src/ssl/tls_method.cc \
     third_party/boringssl-with-bazel/src/ssl/tls_record.cc \
     third_party/upb/upb/decode.c \
+    third_party/upb/upb/def.c \
     third_party/upb/upb/encode.c \
     third_party/upb/upb/msg.c \
     third_party/upb/upb/port.c \
+    third_party/upb/upb/reflection.c \
     third_party/upb/upb/table.c \
+    third_party/upb/upb/text_encode.c \
     third_party/upb/upb/upb.c \
     , $ext_shared, , -fvisibility=hidden \
     -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \

+ 72 - 0
config.w32

@@ -14,6 +14,7 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\filters\\client_channel\\client_channel_channelz.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\\config_selector.cc " +
     "src\\core\\ext\\filters\\client_channel\\global_subchannel_pool.cc " +
     "src\\core\\ext\\filters\\client_channel\\health\\health_check_client.cc " +
     "src\\core\\ext\\filters\\client_channel\\http_connect_handshaker.cc " +
@@ -61,6 +62,7 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
     "src\\core\\ext\\filters\\client_channel\\server_address.cc " +
     "src\\core\\ext\\filters\\client_channel\\service_config.cc " +
+    "src\\core\\ext\\filters\\client_channel\\service_config_channel_arg_filter.cc " +
     "src\\core\\ext\\filters\\client_channel\\service_config_parser.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " +
@@ -117,78 +119,145 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\transport\\inproc\\inproc_plugin.cc " +
     "src\\core\\ext\\transport\\inproc\\inproc_transport.cc " +
     "src\\core\\ext\\upb-generated\\envoy\\annotations\\deprecation.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\annotations\\deprecation.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\annotations\\resource.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\annotations\\resource.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\cert.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\cert.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\common.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\common.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\secret.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\secret.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\tls.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\auth\\tls.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cds.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cds.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\circuit_breaker.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\circuit_breaker.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\filter.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\filter.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\outlier_detection.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\cluster\\outlier_detection.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\address.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\address.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\backoff.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\backoff.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\base.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\base.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\config_source.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\config_source.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\event_service_config.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\event_service_config.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\grpc_service.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\grpc_service.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\health_check.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\health_check.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\http_uri.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\http_uri.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\protocol.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\protocol.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\socket_option.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\core\\socket_option.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\discovery.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\discovery.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\eds.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\eds.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint\\endpoint.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint\\endpoint.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint\\endpoint_components.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint\\endpoint_components.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint\\load_report.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\endpoint\\load_report.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\lds.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\lds.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\listener.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\listener.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\listener\\listener.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\listener\\listener.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\listener\\listener_components.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\listener\\listener_components.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\listener\\udp_listener_config.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\listener\\udp_listener_config.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\rds.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\rds.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\route.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\route.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\route\\route.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\route\\route.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\route\\route_components.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\route\\route_components.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\scoped_route.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\scoped_route.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\srds.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\api\\v2\\srds.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\config\\filter\\accesslog\\v2\\accesslog.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\config\\filter\\accesslog\\v2\\accesslog.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\config\\filter\\network\\http_connection_manager\\v2\\http_connection_manager.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\config\\filter\\network\\http_connection_manager\\v2\\http_connection_manager.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\config\\listener\\v2\\api_listener.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\config\\listener\\v2\\api_listener.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\config\\trace\\v2\\http_tracer.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\config\\trace\\v2\\http_tracer.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\service\\discovery\\v2\\ads.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\service\\discovery\\v2\\ads.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\service\\load_stats\\v2\\lrs.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\service\\load_stats\\v2\\lrs.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\http.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\type\\http.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\regex.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\regex.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\string.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\string.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\metadata\\v2\\metadata.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\type\\metadata\\v2\\metadata.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\percent.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\type\\percent.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\range.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\type\\range.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\semantic_version.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\type\\semantic_version.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\envoy\\type\\tracing\\v2\\custom_tag.upb.c " +
+    "src\\core\\ext\\upb-generated\\envoy\\type\\tracing\\v2\\custom_tag.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\gogoproto\\gogo.upb.c " +
+    "src\\core\\ext\\upb-generated\\gogoproto\\gogo.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\api\\annotations.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\api\\annotations.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\api\\http.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\api\\http.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\protobuf\\any.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\protobuf\\any.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\protobuf\\descriptor.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\protobuf\\descriptor.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\protobuf\\duration.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\protobuf\\duration.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\protobuf\\empty.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\protobuf\\empty.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\protobuf\\struct.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\protobuf\\struct.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\protobuf\\timestamp.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\protobuf\\timestamp.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\protobuf\\wrappers.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\protobuf\\wrappers.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\google\\rpc\\status.upb.c " +
+    "src\\core\\ext\\upb-generated\\google\\rpc\\status.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\gcp\\altscontext.upb.c " +
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\gcp\\handshaker.upb.c " +
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\gcp\\transport_security_common.upb.c " +
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\health\\v1\\health.upb.c " +
     "src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lb\\v1\\load_balancer.upb.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\migrate.upb.c " +
+    "src\\core\\ext\\upb-generated\\udpa\\annotations\\migrate.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\sensitive.upb.c " +
+    "src\\core\\ext\\upb-generated\\udpa\\annotations\\sensitive.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\udpa\\annotations\\status.upb.c " +
+    "src\\core\\ext\\upb-generated\\udpa\\annotations\\status.upbdefs.c " +
     "src\\core\\ext\\upb-generated\\udpa\\data\\orca\\v1\\orca_load_report.upb.c " +
     "src\\core\\ext\\upb-generated\\validate\\validate.upb.c " +
+    "src\\core\\ext\\upb-generated\\validate\\validate.upbdefs.c " +
     "src\\core\\lib\\avl\\avl.cc " +
     "src\\core\\lib\\backoff\\backoff.cc " +
     "src\\core\\lib\\channel\\channel_args.cc " +
@@ -793,10 +862,13 @@ if (PHP_GRPC != "no") {
     "third_party\\boringssl-with-bazel\\src\\ssl\\tls_method.cc " +
     "third_party\\boringssl-with-bazel\\src\\ssl\\tls_record.cc " +
     "third_party\\upb\\upb\\decode.c " +
+    "third_party\\upb\\upb\\def.c " +
     "third_party\\upb\\upb\\encode.c " +
     "third_party\\upb\\upb\\msg.c " +
     "third_party\\upb\\upb\\port.c " +
+    "third_party\\upb\\upb\\reflection.c " +
     "third_party\\upb\\upb\\table.c " +
+    "third_party\\upb\\upb\\text_encode.c " +
     "third_party\\upb\\upb\\upb.c " +
     "third_party\\zlib\\adler32.c " +
     "third_party\\zlib\\compress.c " +

+ 1 - 1
doc/PROTOCOL-WEB.md

@@ -17,7 +17,7 @@ with the protocol details specified in the
 For the gRPC-Web protocol, we have decided on the following design goals:
 
 * adopt the same framing as “application/grpc” whenever possible
-* decouple from HTTP/2 framing which is not, and will never, be directly
+* decouple from HTTP/2 framing which is not, and will never be, directly
 exposed by browsers
 * support text streams (e.g. base64) in order to provide cross-browser
 support (e.g. IE-10)

+ 5 - 5
doc/core/combiner-explainer.md

@@ -41,9 +41,9 @@ Instead, get a new property:
 class combiner {
   mpscq q; // multi-producer single-consumer queue can be made non-blocking
   state s; // is it empty or executing
-  
+
   run(f) {
-    if (q.push(f)) { 
+    if (q.push(f)) {
       // q.push returns true if it's the first thing
       while (q.pop(&f)) { // modulo some extra work to avoid races
         f();
@@ -73,9 +73,9 @@ class combiner {
   mpscq q; // multi-producer single-consumer queue can be made non-blocking
   state s; // is it empty or executing
   queue finally; // you can only do run_finally when you are already running something from the combiner
-  
+
   run(f) {
-    if (q.push(f)) { 
+    if (q.push(f)) {
       // q.push returns true if it's the first thing
       loop:
       while (q.pop(&f)) { // modulo some extra work to avoid races
@@ -127,7 +127,7 @@ tries to spray events onto as many threads as possible to get as much concurrenc
 
 So `offload` really does:
 
-``` 
+```
   workqueue.run(continue_from_while_loop);
   break;
 ```

+ 1 - 1
doc/core/epoll-polling-engine.md

@@ -104,7 +104,7 @@ void grpc_use_signal(int signal_num)
 
 If the calling application does not provide a signal number, then the gRPC library will relegate to using a model similar to the current implementation (where every thread does a blocking `poll()` on its `wakeup_fd` and the `epoll_fd`).  The function` psi_wait() `in figure 2 implements this logic.
 
-**>> **(**NOTE**: Or alternatively, we can implement a turnstile polling (i.e having only one thread calling `epoll_wait()` on the epoll set at any time - which all other threads call poll on their `wakeup_fds`) 
+**>> **(**NOTE**: Or alternatively, we can implement a turnstile polling (i.e having only one thread calling `epoll_wait()` on the epoll set at any time - which all other threads call poll on their `wakeup_fds`)
 in case of not getting a signal number from the applications.
 
 

+ 1 - 1
doc/core/grpc-client-server-polling-engine-usage.md

@@ -7,7 +7,7 @@ This document talks about how polling engine is used in gRPC core (both on clien
 
 ## gRPC client
 
-### Relation between Call, Channel (sub-channels), Completion queue, `grpc_pollset` 
+### Relation between Call, Channel (sub-channels), Completion queue, `grpc_pollset`
 - A gRPC Call is tied to a channel (more specifically a sub-channel) and a completion queue for the lifetime of the call.
 - Once a _sub-channel_ is picked for the call, the file-descriptor (socket fd in case of TCP channels) is added to the pollset corresponding to call's completion queue. (Recall that as per [grpc-cq](grpc-cq.md), a completion queue has a pollset by default)
 

+ 1 - 1
doc/core/grpc-cq.md

@@ -61,4 +61,4 @@ grpc_cq_end_op(cq, tag) {
 }
 
 ```
- 
+

+ 3 - 3
doc/core/moving-to-c++.md

@@ -11,7 +11,7 @@ gRPC core was originally written in C89 for several reasons
 support, etc). Over time, this was changed to C99 as all relevant
 compilers in active use came to support C99 effectively.
 
-gRPC started allowing to use C++ with a couple of exceptions not to 
+gRPC started allowing to use C++ with a couple of exceptions not to
 have C++ library linked such as `libstdc++.so`.
 (For more detail, see the [proposal](https://github.com/grpc/proposal/blob/master/L6-core-allow-cpp.md))
 
@@ -25,12 +25,12 @@ C++ compatible with
 
 ## Constraints
 
-- Most of features available in C++11 are allowed to use but there are some exceptions 
+- Most of features available in C++11 are allowed to use but there are some exceptions
   because gRPC should support old systems.
   - Should be built with gcc 4.8, clang 3.3, and Visual C++ 2015.
   - Should be run on Linux system with libstdc++ 6.0.9 to support
     [manylinux1](https://www.python.org/dev/peps/pep-0513).
-- This would limit us not to use modern C++11 standard library such as `filesystem`. 
+- This would limit us not to use modern C++11 standard library such as `filesystem`.
   You can easily see whether PR is free from this issue by checking the result of
   `Artifact Build Linux` test.
 - `thread_local` is not allowed to use on Apple's products because their old OSes

+ 1 - 1
doc/environment_variables.md

@@ -73,7 +73,7 @@ some configuration as environment variables that can be set.
     completion queue
   - pick_first - traces the pick first load balancing policy
   - plugin_credentials - traces plugin credentials
-  - pollable_refcount - traces reference counting of 'pollable' objects (only 
+  - pollable_refcount - traces reference counting of 'pollable' objects (only
     in DEBUG)
   - priority_lb - traces priority LB policy
   - resource_quota - trace resource quota objects internals

+ 1 - 1
doc/fork_support.md

@@ -25,7 +25,7 @@ A regression was noted in cases where users are doing fork/exec. This
 was due to ```pthread_atfork()``` handler that was added in 1.7 to partially
 support forking in gRPC. A deadlock can happen when pthread_atfork
 handler is running, and an application thread is calling into gRPC.
-We have provided a workaround for this issue by allowing users to turn 
+We have provided a workaround for this issue by allowing users to turn
 off the handler using env flag ```GRPC_ENABLE_FORK_SUPPORT=False```.
 This should be set whenever a user expects to always call exec
 immediately following fork.  It will disable the fork handlers.

+ 2 - 1
doc/g_stands_for.md

@@ -29,4 +29,5 @@
 - 1.27 'g' stands for ['guantao'](https://github.com/grpc/grpc/tree/v1.27.x)
 - 1.28 'g' stands for ['galactic'](https://github.com/grpc/grpc/tree/v1.28.x)
 - 1.29 'g' stands for ['gringotts'](https://github.com/grpc/grpc/tree/v1.29.x)
-- 1.30 'g' stands for ['gradius'](https://github.com/grpc/grpc/tree/master)
+- 1.30 'g' stands for ['gradius'](https://github.com/grpc/grpc/tree/v1.30.x)
+- 1.31 'g' stands for ['galore'](https://github.com/grpc/grpc/tree/master)

+ 40 - 0
doc/grpc_xds_features.md

@@ -0,0 +1,40 @@
+# xDS Features in gRPC
+
+This document lists the [xDS](https://github.com/envoyproxy/data-plane-api/tree/master/envoy/api/v2)
+features supported in various gRPC language implementations and versions.
+
+Note that a gRPC client will simply ignore the configuration of a feature it
+does not support. The gRPC client does not generate a log
+to indicate that some configuration was ignored. It is impractical to generate
+a log and keep it up-to-date because xDS has a large number of APIs that gRPC
+does not support and the APIs keep evolving too. We recommend reading the
+[first gRFC](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md)
+on xDS support in gRPC to understand the design philosophy.
+
+The EDS policy will *not* support
+[overprovisioning](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/overprovisioning),
+which is different from Envoy.  Envoy takes the overprovisioning into
+account in both [locality-weighted load balancing](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/locality_weight)
+and [priority failover](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/priority),
+but gRPC assumes that the xDS server will update it to redirect traffic
+when this kind of graceful failover is needed.  gRPC will send the
+[`envoy.lb.does_not_support_overprovisioning` client
+feature](https://github.com/envoyproxy/envoy/pull/10136) to the xDS
+server to tell the xDS server that it will not perform graceful failover;
+xDS server implementations may use this to decide whether to perform
+graceful failover themselves.
+
+The EDS policy will not support per-endpoint stats; it will report only
+per-locality stats.
+
+An [`lb_endpoint`](https://github.com/envoyproxy/envoy/blob/12a4bc430eaf440ceb0d11286cfbd4c16b79cdd1/api/envoy/api/v2/endpoint/endpoint_components.proto#L72)
+is ignored if the `health_status` is not HEALTHY or UNKNOWN.
+The optional `load_balancing_weight` is always ignored.
+
+Initially, only `google_default` channel creds will be supported
+to authenticate with the xDS server.
+
+Features | gRFCs  | [C++, Python,<br> Ruby, PHP, C#](https://github.com/grpc/grpc/releases) | [Java](https://github.com/grpc/grpc-java/releases) | [Go](https://github.com/grpc/grpc-go/releases)
+---------|--------|--------------|------|------
+**xDS Infrastructure in gRPC client channel:**<br>LDS->RDS->CDS->EDS flow,<br>ADS stream, | [A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md) | v1.30.0  | v1.30.0 | v1.30.0 |
+**Load Balancing:**<br>Virtual host matching,<br>Only default path ("" or "/") matching,<br>Priority-based weighted round-robin locality picking,<br>Round-robin endpoint picking within locality,<br>Cluster route action,<br>Client-side Load reporting via [LRS](https://github.com/envoyproxy/data-plane-api/blob/master/envoy/service/load_stats/v2/lrs.proto)| [A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md) | v1.30.0  | v1.30.0 | v1.30.0 |

+ 1 - 0
doc/health-checking.md

@@ -37,6 +37,7 @@ message HealthCheckResponse {
     UNKNOWN = 0;
     SERVING = 1;
     NOT_SERVING = 2;
+    SERVICE_UNKNOWN = 3;  // Used only by the Watch method.
   }
   ServingStatus status = 1;
 }

+ 13 - 13
doc/http2-interop-test-descriptions.md

@@ -8,7 +8,7 @@ Server
 ------
 The code for the custom http2 server can be found
 [here](https://github.com/grpc/grpc/tree/master/test/http2_test).
-It is responsible for handling requests and sending responses, and also for 
+It is responsible for handling requests and sending responses, and also for
 fulfilling the behavior of each particular test case.
 
 Server should accept these arguments:
@@ -51,7 +51,7 @@ the user application having to do a thing.
 Client Procedure:
  1. Client sends two UnaryCall requests (and sleeps for 1 second in-between).
  TODO: resolve [9300](https://github.com/grpc/grpc/issues/9300) and remove the 1 second sleep
- 
+
     ```
     {
       response_size: 314159
@@ -78,7 +78,7 @@ RST_STREAM immediately after sending headers to the client.
 
 Procedure:
  1. Client sends UnaryCall with:
- 
+
     ```
     {
       response_size: 314159
@@ -93,7 +93,7 @@ Client asserts:
 
 Server Procedure:
   1. Server sends a RST_STREAM with error code 0 after sending headers to the client.
-  
+
 *At the moment the error code and message returned are not standardized throughout all
 languages. Those checks will be added once all client languages behave the same way. [#9142](https://github.com/grpc/grpc/issues/9142) is in flight.*
 
@@ -104,7 +104,7 @@ RST_STREAM halfway through sending data to the client.
 
 Procedure:
  1. Client sends UnaryCall with:
- 
+
     ```
     {
       response_size: 314159
@@ -118,7 +118,7 @@ Client asserts:
 * Call was not successful.
 
 Server Procedure:
-  1. Server sends a RST_STREAM with error code 0 after sending half of 
+  1. Server sends a RST_STREAM with error code 0 after sending half of
      the requested data to the client.
 
 ### rst_after_data
@@ -128,7 +128,7 @@ RST_STREAM after sending all of the data to the client.
 
 Procedure:
  1. Client sends UnaryCall with:
- 
+
     ```
     {
       response_size: 314159
@@ -156,7 +156,7 @@ server.
 
 Procedure:
  1. Client sends UnaryCall with:
- 
+
     ```
     {
       response_size: 314159
@@ -165,16 +165,16 @@ Procedure:
       }
     }
     ```
-  
+
 Client asserts:
 * call was successful.
 * response payload body is 314159 bytes in size.
 
 Server Procedure:
-  1. Server tracks the number of outstanding pings (i.e. +1 when it sends a ping, and -1 
+  1. Server tracks the number of outstanding pings (i.e. +1 when it sends a ping, and -1
   when it receives an ack from the client).
   2. Server sends pings before and after sending headers, also before and after sending data.
-  
+
 Server Asserts:
 * Number of outstanding pings is 0 when the connection is lost.
 
@@ -185,10 +185,10 @@ This test verifies that the client observes the MAX_CONCURRENT_STREAMS limit set
 Client Procedure:
   1. Client sends initial UnaryCall to allow the server to update its MAX_CONCURRENT_STREAMS settings.
   2. Client concurrently sends 10 UnaryCalls.
-  
+
 Client Asserts:
 * All UnaryCalls were successful, and had the correct type and payload size.
- 
+
 Server Procedure:
   1. Sets MAX_CONCURRENT_STREAMS to one after the connection is made.
 

+ 1 - 1
doc/internationalization.md

@@ -1,7 +1,7 @@
 gRPC Internationalization
 =========================
 
-As a universal RPC framework, gRPC needs to be fully usable within/across different international environments. 
+As a universal RPC framework, gRPC needs to be fully usable within/across different international environments.
 This document describes gRPC API and behavior specifics when used in a non-english environment.
 
 ## API Concepts

+ 5 - 5
doc/interop-test-descriptions.md

@@ -1007,21 +1007,21 @@ languages. Therefore they are not part of our interop matrix.
 
 #### rpc_soak
 
-The client performs many large_unary RPCs in sequence over the same channel. 
+The client performs many large_unary RPCs in sequence over the same channel.
 The number of RPCs is configured by the experimental flag, `soak_iterations`.
 
 #### channel_soak
 
-The client performs many large_unary RPCs in sequence. Before each RPC, it 
-tears down and rebuilds the channel. The number of RPCs is configured by 
+The client performs many large_unary RPCs in sequence. Before each RPC, it
+tears down and rebuilds the channel. The number of RPCs is configured by
 the experimental flag, `soak_iterations`.
 
-This tests puts stress on several gRPC components; the resolver, the load 
+This tests puts stress on several gRPC components; the resolver, the load
 balancer, and the RPC hotpath.
 
 #### long_lived_channel
 
-The client performs a number of large_unary RPCs over a single long-lived 
+The client performs a number of large_unary RPCs over a single long-lived
 channel with a fixed but configurable interval between each RPC.
 
 ### TODO Tests

+ 4 - 4
doc/keepalive.md

@@ -14,13 +14,13 @@ The keepalive ping is controlled by two important channel arguments -
 The above two channel arguments should be sufficient for most users, but the following arguments can also be useful in certain use cases.
 
 * **GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS**
-  * This channel argument if set to 1 (0 : false; 1 : true), allows keepalive pings to be sent even if there are no calls in flight. 
+  * This channel argument if set to 1 (0 : false; 1 : true), allows keepalive pings to be sent even if there are no calls in flight.
 * **GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA**
-  * This channel argument controls the maximum number of pings that can be sent when there is no other data (data frame or header frame) to be sent. GRPC Core will not continue sending pings if we run over the limit. Setting it to 0 allows sending pings without sending data.
+  * This channel argument controls the maximum number of pings that can be sent when there is no data/header frame to be sent. GRPC Core will not continue sending pings if we run over the limit. Setting it to 0 allows sending pings without such a restriction.
 * **GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS**
-  * If there are no data frames being received on the transport, this channel argument controls the minimum time (in milliseconds) gRPC Core will wait between successive pings.
+  * If there are no data/header frames being received on the transport, this channel argument controls the minimum time (in milliseconds) gRPC Core will wait between successive pings.
 * **GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS**
-  * If there are no data frames being sent on the transport, this channel argument on the server side controls the minimum time (in milliseconds) that gRPC Core would expect between receiving successive pings. If the time between successive pings is less that than this time, then the ping will be considered a bad ping from the peer. Such a ping counts as a ‘ping strike’.
+  * If there are no data/header frames being sent on the transport, this channel argument on the server side controls the minimum time (in milliseconds) that gRPC Core would expect between receiving successive pings. If the time between successive pings is less that than this time, then the ping will be considered a bad ping from the peer. Such a ping counts as a ‘ping strike’.
 On the client side, this does not have any effect.
 * **GRPC_ARG_HTTP2_MAX_PING_STRIKES**
   * This arg controls the maximum number of bad pings that the server will tolerate before sending an HTTP2 GOAWAY frame and closing the transport. Setting it to 0 allows the server to accept any number of bad pings.

+ 2 - 2
doc/python/server_reflection.md

@@ -6,7 +6,7 @@ and more examples how to use server reflection.
 
 ## Enable server reflection in Python servers
 
-gRPC Python Server Reflection is an add-on library. To use it, first install 
+gRPC Python Server Reflection is an add-on library. To use it, first install
 the [grpcio-reflection] PyPI package into your project.
 
 Note that with Python you need to manually register the service
@@ -29,7 +29,7 @@ def serve():
     server.start()
 ```
 
-Please see [greeter_server_with_reflection.py] in the examples directory for the full 
+Please see [greeter_server_with_reflection.py] in the examples directory for the full
 example, which extends the gRPC [Python `Greeter` example] on a reflection-enabled server.
 
 After starting the server, you can verify that the server reflection

+ 2 - 2
doc/python/sphinx/grpc.rst

@@ -6,8 +6,8 @@ gRPC
 Tutorial
 --------
 
-If you want to see gRPC in action first, visit the `Python Quickstart <https://grpc.io/docs/quickstart/python.html>`_.
-Or, if you would like dive in with more extensive usage of gRPC Python, check `gRPC Basics - Python <https://grpc.io/docs/tutorials/basic/python.html>`_ out.
+If you want to see gRPC in action first, visit the `Python Quickstart <https://grpc.io/docs/languages/python/quickstart>`_.
+Or, if you would like dive in with more extensive usage of gRPC Python, check `gRPC Basics - Python <https://grpc.io/docs/languages/python/basics>`_ out.
 
 
 Example

+ 7 - 18
doc/python/sphinx/grpc_asyncio.rst

@@ -24,27 +24,16 @@ gRPC Async API objects may only be used on the thread on which they were
 created. AsyncIO doesn't provide thread safety for most of its APIs.
 
 
-Module Contents
----------------
-
-Enable AsyncIO in gRPC
-^^^^^^^^^^^^^^^^^^^^^^
-
-.. function:: init_grpc_aio
+Blocking Code in AsyncIO
+------------------------
 
-    Enable AsyncIO for gRPC Python.
+Making blocking function calls in coroutines or in the thread running event
+loop will block the event loop, potentially starving all RPCs in the process.
+Refer to the Python language documentation on AsyncIO for more details (`running-blocking-code <https://docs.python.org/3/library/asyncio-dev.html#running-blocking-code>`_).
 
-    This function is idempotent and it should be invoked before creation of
-    AsyncIO stack objects. Otherwise, the application might deadlock.
 
-    This function configurates the gRPC C-Core to invoke AsyncIO methods for IO
-    operations (e.g., socket read, write). The configuration applies to the
-    entire process.
-
-    After invoking this function, making blocking function calls in coroutines
-    or in the thread running event loop will block the event loop, potentially
-    starving all RPCs in the process. Refer to the Python language
-    documentation on AsyncIO for more details (`running-blocking-code <https://docs.python.org/3/library/asyncio-dev.html#running-blocking-code>`_).
+Module Contents
+---------------
 
 
 Create Channel

+ 4 - 4
doc/security_audit.md

@@ -1,6 +1,6 @@
 # gRPC Security Audit
 
-A third-party security audit of gRPC C++ stack was performed by [Cure53](https://cure53.de) in October 2019. The full report can be found [here](https://github.com/grpc/grpc/tree/master/doc/grpc_security_audit.pdf). 
+A third-party security audit of gRPC C++ stack was performed by [Cure53](https://cure53.de) in October 2019. The full report can be found [here](https://github.com/grpc/grpc/tree/master/doc/grpc_security_audit.pdf).
 
 # Addressing grpc_security_audit
 
@@ -21,7 +21,7 @@ Below is a list of alternatives that gRPC team considered.
 
 
 ### Alternative #1: Rewrite gpr_free to take void\*\*
-One solution is to change the API of `gpr_free` so that it automatically nulls the given pointer after freeing it. 
+One solution is to change the API of `gpr_free` so that it automatically nulls the given pointer after freeing it.
 
 ```
 gpr_free (void** ptr) {
@@ -30,7 +30,7 @@ gpr_free (void** ptr) {
 }
 ```
 
-This defensive programming pattern would help protect gRPC from the potential exploits and latent dangling pointer bugs mentioned in the security report. 
+This defensive programming pattern would help protect gRPC from the potential exploits and latent dangling pointer bugs mentioned in the security report.
 
 However, performance would be a significant concern as we are now unconditionally adding a store to every gpr_free call, and there are potentially hundreds of these per RPC. At the RPC layer, this can add up to prohibitive costs.
 
@@ -61,7 +61,7 @@ Because of performance and maintainability concerns, GRP-01-002 will be addresse
 ## GRP-01-003 Calls to malloc suffer from potential integer overflows
 The vulnerability, as defined by the report, is that calls to `gpr_malloc` in the C-core codebase may suffer from potential integer overflow in cases where we multiply the array element size by the size of the array. The penetration testers did not identify a concrete place where this occurred, but rather emphasized that the coding pattern itself had potential to lead to vulnerabilities. The report’s suggested solution for GRP-01-003 was to create a `calloc(size_t nmemb, size_t size)` wrapper that contains integer overflow checks.
 
-However, gRPC team firmly believes that gRPC Core should only use integer overflow checks in the places where they’re needed; for example, any place where remote input influences the input to `gpr_malloc` in an unverified way. This is because bounds-checking is very expensive at the RPC layer. 
+However, gRPC team firmly believes that gRPC Core should only use integer overflow checks in the places where they’re needed; for example, any place where remote input influences the input to `gpr_malloc` in an unverified way. This is because bounds-checking is very expensive at the RPC layer.
 
 Determining exactly where bounds-checking is needed requires an audit of tracing each `gpr_malloc` (or `gpr_realloc` or `gpr_zalloc`) call up the stack to determine if the sufficient bounds-checking was performed. This kind of audit, done manually, is fairly expensive engineer-wise.
 

+ 1 - 1
doc/unit_testing.md

@@ -75,7 +75,7 @@ grpc_proto_library(
 ```
 
 
-By adding such a flag now a header file `echo_mock.grpc.pb.h` containing the mocked stub will also be generated. 
+By adding such a flag now a header file `echo_mock.grpc.pb.h` containing the mocked stub will also be generated.
 
 This header file can then be included in test files along with a gmock dependency.
 

+ 2 - 2
doc/versioning.md

@@ -3,7 +3,7 @@
 ## Versioning Overview
 
 All gRPC implementations use a three-part version number (`vX.Y.Z`) and follow [semantic versioning](https://semver.org/), which defines the semantics of major, minor and patch components of the version number. In addition to that, gRPC versions evolve according to these rules:
-- **Major version bumps** only happen on rare occasions. In order to qualify for a major version bump, certain criteria described later in this document need to be met. Most importantly, a major version increase must not break wire compatibility with other gRPC implementations so that existing gRPC libraries remain fully interoperable. 
+- **Major version bumps** only happen on rare occasions. In order to qualify for a major version bump, certain criteria described later in this document need to be met. Most importantly, a major version increase must not break wire compatibility with other gRPC implementations so that existing gRPC libraries remain fully interoperable.
 - **Minor version bumps** happen approx. every 6 weeks as part of the normal release cycle as defined by the gRPC release process. A new release branch named vMAJOR.MINOR.PATCH) is cut every 6 weeks based on the [release schedule](https://github.com/grpc/grpc/blob/master/doc/grpc_release_schedule.md).
 - **Patch version bump** corresponds to bugfixes done on release branch.
 
@@ -24,7 +24,7 @@ There are also a few extra rules regarding adding new gRPC implementations (e.g.
 To avoid user confusion and simplify reasoning, the gRPC releases in different languages try to stay synchronized in terms of major and minor version (all languages follow the same release schedule). Nevertheless, because we also strictly follow semantic versioning, there are circumstances in which a gRPC implementation needs to break the version synchronicity and do a major version bump independently of other languages.
 
 ### Situations when it's ok to do a major version bump
-- **change forced by the language ecosystem:** when the language itself or its standard libraries that we depend on make a breaking change (something which is out of our control), reacting with updating gRPC APIs may be the only adequate response. 
+- **change forced by the language ecosystem:** when the language itself or its standard libraries that we depend on make a breaking change (something which is out of our control), reacting with updating gRPC APIs may be the only adequate response.
 - **voluntary change:** Even in non-forced situations, there might be circumstances in which a breaking API change makes sense and represents a net win, but as a rule of thumb breaking changes are very disruptive for users, cause user fragmentation and incur high maintenance costs. Therefore, breaking API changes should be very rare events that need to be considered with extreme care and the bar for accepting such changes is intentionally set very high.
   Example scenarios where a breaking API change might be adequate:
   - fixing a security problem which requires changes to API (need to consider the non-breaking alternatives first)

+ 36 - 8
doc/xds-test-descriptions.md

@@ -90,7 +90,7 @@ This test verifies that every backend receives traffic.
 Client parameters:
 
 1.  --num_channels=1
-1.  --qps=10
+1.  --qps=100
 1.  --fail_on_failed_rpc=true
 
 Load balancer configuration:
@@ -109,7 +109,7 @@ robin policy.
 Client parameters:
 
 1.  --num_channels=1
-1.  --qps=10
+1.  --qps=100
 1.  --fail_on_failed_rpc=true
 
 Load balancer configuration:
@@ -129,7 +129,7 @@ of backends that is stopped and then resumed.
 Client parameters:
 
 1.  --num_channels=1
-1.  --qps=10
+1.  --qps=100
 
 Load balancer configuration:
 
@@ -161,7 +161,7 @@ all backends in the primary locality fail.
 Client parameters:
 
 1.  --num_channels=1
-1.  --qps=10
+1.  --qps=100
 
 Load balancer configuration:
 
@@ -197,7 +197,7 @@ changes to this test case.
 Client parameters:
 
 1.  --num_channels=1
-1.  --qps=10
+1.  --qps=100
 
 Load balancer configuration:
 
@@ -224,7 +224,7 @@ same zone receive traffic.
 Client parameters:
 
 1.  --num_channels=1
-1.  --qps=10
+1.  --qps=100
 1.  --fail_on_failed_rpc=true
 
 Load balancer configuration:
@@ -249,7 +249,7 @@ after removal of another instance group in the same zone.
 Client parameters:
 
 1.  --num_channels=1
-1.  --qps=10
+1.  --qps=100
 
 Load balancer configuration:
 
@@ -273,7 +273,7 @@ to the new backends.
 Client parameters:
 
 1.  --num_channels=1
-1.  --qps=10
+1.  --qps=100
 1.  --fail_on_failed_rpc=true
 
 Load balancer configuration:
@@ -291,3 +291,31 @@ Test driver asserts:
 
 1.  All RPCs are directed to the new backend service.
 
+### traffic_splitting
+
+This test verifies that the traffic will be distributed between backend
+services with the correct weights when route action is set to weighted
+backend services.
+
+Client parameters:
+
+1.  --num_channels=1
+1.  --qps=100
+
+Load balancer configuration:
+
+1.  One MIG with one backend
+
+Assert:
+
+1. Once all backends receive at least one RPC, the following 1000 RPCs are
+all sent to MIG_a.
+
+The test driver adds a new MIG with 1 backend, and changes the route action
+to weighted backend services with {a: 20, b: 80}.
+
+Assert:
+
+1. Once all backends receive at least one RPC, the following 1000 RPCs are
+distributed across the 2 backends as a: 20, b: 80.
+

+ 2 - 2
examples/cpp/README.md

@@ -7,7 +7,7 @@
 For information about the other examples in this directory, see their respective
 README files.
 
-[gRPC Basics]: https://grpc.io/docs/tutorials/basic/cpp
+[gRPC Basics]: https://grpc.io/docs/languages/cpp/basics
 [Hello World]: helloworld
-[Quick Start]: https://grpc.io/docs/quickstart/cpp
+[Quick Start]: https://grpc.io/docs/languages/cpp/quickstart
 [Route Guide]: route_guide

+ 1 - 1
examples/cpp/helloworld/README.md

@@ -3,4 +3,4 @@
 You can find a complete set of instructions for building gRPC and running the
 Hello World app in the [C++ Quick Start][].
 
-[C++ Quick Start]: https://grpc.io/docs/quickstart/cpp
+[C++ Quick Start]: https://grpc.io/docs/languages/cpp/quickstart

+ 1 - 1
examples/cpp/route_guide/README.md

@@ -3,4 +3,4 @@
 The files in this folder are the samples used in [gRPC Basics: C++][],
 a detailed tutorial for using gRPC in C++.
 
-[gRPC Basics: C++]:https://grpc.io/docs/tutorials/basic/cpp
+[gRPC Basics: C++]:https://grpc.io/docs/languages/cpp/basics

+ 1 - 1
examples/csharp/Helloworld/README.md

@@ -36,4 +36,4 @@ Tutorial
 You can find a more detailed tutorial about Grpc in [gRPC Basics: C#][]
 
 [helloworld.proto]:../../protos/helloworld.proto
-[gRPC Basics: C#]:https://grpc.io/docs/tutorials/basic/csharp.html
+[gRPC Basics: C#]:https://grpc.io/docs/languages/csharp/basics

+ 2 - 2
examples/csharp/HelloworldLegacyCsproj/README.md

@@ -40,7 +40,7 @@ download all of the NuGet dependencies of gRPC.
 
 Using these IDEs, a workaround is as follows:
 * Obtain a nuget executable for your platform and update it with
- `nuget update -self`. 
+ `nuget update -self`.
 * Navigate to this directory and run `nuget restore`.
 * Now that packages have been restored into their proper package folder, build the solution from your IDE.
 
@@ -71,4 +71,4 @@ Tutorial
 You can find a more detailed tutorial in [gRPC Basics: C#][]
 
 [helloworld.proto]:../../protos/helloworld.proto
-[gRPC Basics: C#]:https://grpc.io/docs/tutorials/basic/csharp.html
+[gRPC Basics: C#]:https://grpc.io/docs/languages/csharp/basics

+ 1 - 1
examples/csharp/RouteGuide/README.md

@@ -3,4 +3,4 @@
 The files in this folder are the samples used in [gRPC Basics: C#][],
 a detailed tutorial for using gRPC in C#.
 
-[gRPC Basics: C#]:https://grpc.io/docs/tutorials/basic/csharp.html
+[gRPC Basics: C#]:https://grpc.io/docs/languages/csharp/basics

+ 1 - 1
examples/node/README.md

@@ -47,4 +47,4 @@ TUTORIAL
 You can find a more detailed tutorial in [gRPC Basics: Node.js][]
 
 [Install gRPC Node]:../../src/node
-[gRPC Basics: Node.js]:https://grpc.io/docs/tutorials/basic/node.html
+[gRPC Basics: Node.js]:https://grpc.io/docs/languages/node/basics

+ 1 - 1
examples/node/dynamic_codegen/route_guide/README.md

@@ -2,4 +2,4 @@
 
 The files in this folder are the samples used in [gRPC Basics: Node.js][], a detailed tutorial for using gRPC in Node.js.
 
-[gRPC Basics: Node.js]:https://grpc.io/docs/tutorials/basic/node.html
+[gRPC Basics: Node.js]:https://grpc.io/docs/languages/node/basics

+ 1 - 1
examples/node/static_codegen/route_guide/README.md

@@ -2,4 +2,4 @@
 
 The files in this folder are the samples used in [gRPC Basics: Node.js][], a detailed tutorial for using gRPC in Node.js.
 
-[gRPC Basics: Node.js]:https://grpc.io/docs/tutorials/basic/node.html
+[gRPC Basics: Node.js]:https://grpc.io/docs/languages/node/basics

+ 1 - 1
examples/objective-c/auth_sample/README.md

@@ -1,3 +1,3 @@
 # OAuth2 on gRPC: Objective-C
 
-This is the supporting code for the tutorial "[OAuth2 on gRPC: Objective-C](https://grpc.io/docs/tutorials/auth/oauth2-objective-c.html)."
+This is the supporting code for the tutorial "[OAuth2 on gRPC: Objective-C](https://grpc.io/docs/languages/objective-c/oauth2)."

+ 1 - 1
examples/objective-c/helloworld/README.md

@@ -104,4 +104,4 @@ $ bazel run :HelloWorld --ios_simulator_version='<runtime>' --ios_sumlator_devic
 
 ## Tutorial
 
-You can find a more detailed tutorial in [gRPC Basics: Objective-C](https://grpc.io/docs/tutorials/basic/objective-c.html).
+You can find a more detailed tutorial in [gRPC Basics: Objective-C](https://grpc.io/docs/languages/objective-c/basics).

+ 1 - 1
examples/objective-c/route_guide/README.md

@@ -1,4 +1,4 @@
 # gRPC Basics: Objective-C
 
-This is the supporting code for the tutorial "[gRPC Basics: Objective-C](https://grpc.io/docs/tutorials/basic/objective-c.html)."
+This is the supporting code for the tutorial "[gRPC Basics: Objective-C](https://grpc.io/docs/languages/objective-c/basics)."
 

+ 1 - 1
examples/php/README.md

@@ -53,4 +53,4 @@ This requires `php` >= 5.5, `pecl`, `composer`
 You can find a more detailed tutorial in [gRPC Basics: PHP][]
 
 [Node]:https://github.com/grpc/grpc/tree/master/examples/node
-[gRPC Basics: PHP]:https://grpc.io/docs/tutorials/basic/php.html
+[gRPC Basics: PHP]:https://grpc.io/docs/languages/php/basics

+ 1 - 1
examples/php/route_guide/README.md

@@ -3,4 +3,4 @@
 The files in this folder are the samples used in [gRPC Basics: PHP][],
 a detailed tutorial for using gRPC in PHP.
 
-[gRPC Basics: PHP]:https://grpc.io/docs/tutorials/basic/php.html
+[gRPC Basics: PHP]:https://grpc.io/docs/languages/php/basics

+ 1 - 1
examples/python/README.md

@@ -1 +1 @@
-[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/quickstart/python.html)
+[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/languages/python/quickstart)

+ 1 - 1
examples/python/helloworld/README.md

@@ -1 +1 @@
-[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/quickstart/python.html)
+[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/languages/python/quickstart)

+ 1 - 1
examples/python/metadata/README.md

@@ -2,5 +2,5 @@ An example showing how to add custom HTTP2 headers (or [metadata](https://grpc.i
 
 HTTP2 supports initial headers and trailing headers, which gRPC utilizes both of them ([learn more](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)).
 
-More complete documentation lives at [grpc.io](https://grpc.io/docs/tutorials/basic/python.html).
+More complete documentation lives at [grpc.io](https://grpc.io/docs/languages/python/basics).
 For API reference please see [API](https://grpc.io/grpc/python/grpc.html).

+ 1 - 1
examples/python/multiplex/README.md

@@ -1,3 +1,3 @@
 An example showing two stubs sharing a channel and two servicers sharing a server.
 
-More complete documentation lives at [grpc.io](https://grpc.io/docs/tutorials/basic/python.html).
+More complete documentation lives at [grpc.io](https://grpc.io/docs/languages/python/basics).

+ 1 - 1
examples/python/route_guide/README.md

@@ -1 +1 @@
-[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/tutorials/basic/python.html)
+[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/languages/python/basics)

+ 1 - 1
examples/ruby/README.md

@@ -60,4 +60,4 @@ You can find a more detailed tutorial in [gRPC Basics: Ruby][]
 [helloworld.proto]:../protos/helloworld.proto
 [RVM]:https://www.rvm.io/
 [Install gRPC ruby]:../../src/ruby#installation
-[gRPC Basics: Ruby]:https://grpc.io/docs/tutorials/basic/ruby.html
+[gRPC Basics: Ruby]:https://grpc.io/docs/languages/ruby/basics

+ 1 - 1
examples/ruby/route_guide/README.md

@@ -3,4 +3,4 @@
 The files in this folder are the samples used in [gRPC Basics: Ruby][],
 a detailed tutorial for using gRPC in Ruby.
 
-[gRPC Basics: Ruby]:https://grpc.io/docs/tutorials/basic/ruby.html
+[gRPC Basics: Ruby]:https://grpc.io/docs/languages/ruby/basics

+ 150 - 9
gRPC-C++.podspec

@@ -22,7 +22,7 @@
 Pod::Spec.new do |s|
   s.name     = 'gRPC-C++'
   # TODO (mxyan): use version that match gRPC version when pod is stabilized
-  version = '1.30.0-dev'
+  version = '1.31.0-dev'
   s.version  = version
   s.summary  = 'gRPC C++ library'
   s.homepage = 'https://grpc.io'
@@ -93,7 +93,6 @@ Pod::Spec.new do |s|
                       'include/grpcpp/generic/generic_stub_impl.h',
                       'include/grpcpp/grpcpp.h',
                       'include/grpcpp/health_check_service_interface.h',
-                      'include/grpcpp/health_check_service_interface_impl.h',
                       'include/grpcpp/impl/call.h',
                       'include/grpcpp/impl/channel_argument_option.h',
                       'include/grpcpp/impl/client_unary_call.h',
@@ -164,7 +163,6 @@ Pod::Spec.new do |s|
                       'include/grpcpp/impl/server_initializer_impl.h',
                       'include/grpcpp/impl/service_type.h',
                       'include/grpcpp/resource_quota.h',
-                      'include/grpcpp/resource_quota_impl.h',
                       'include/grpcpp/security/auth_context.h',
                       'include/grpcpp/security/auth_metadata_processor.h',
                       'include/grpcpp/security/auth_metadata_processor_impl.h',
@@ -227,6 +225,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/client_channel.h',
                       'src/core/ext/filters/client_channel/client_channel_channelz.h',
                       'src/core/ext/filters/client_channel/client_channel_factory.h',
+                      'src/core/ext/filters/client_channel/config_selector.h',
                       'src/core/ext/filters/client_channel/connector.h',
                       'src/core/ext/filters/client_channel/global_subchannel_pool.h',
                       'src/core/ext/filters/client_channel/health/health_check_client.h',
@@ -309,78 +308,145 @@ Pod::Spec.new do |s|
                       'src/core/ext/transport/chttp2/transport/varint.h',
                       'src/core/ext/transport/inproc/inproc_transport.h',
                       'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h',
+                      'src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/annotations/resource.upb.h',
+                      'src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/eds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/lds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/listener.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/rds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/route.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/srds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h',
+                      'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h',
+                      'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/http.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/http.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/matcher/string.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/percent.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/percent.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/range.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/range.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/semantic_version.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h',
                       'src/core/ext/upb-generated/gogoproto/gogo.upb.h',
+                      'src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h',
                       'src/core/ext/upb-generated/google/api/annotations.upb.h',
+                      'src/core/ext/upb-generated/google/api/annotations.upbdefs.h',
                       'src/core/ext/upb-generated/google/api/http.upb.h',
+                      'src/core/ext/upb-generated/google/api/http.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/any.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/any.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/descriptor.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/duration.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/empty.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/struct.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/timestamp.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/wrappers.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h',
                       'src/core/ext/upb-generated/google/rpc/status.upb.h',
+                      'src/core/ext/upb-generated/google/rpc/status.upbdefs.h',
                       'src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h',
                       'src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h',
                       'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h',
                       'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h',
                       'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
+                      'src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h',
                       'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
+                      'src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h',
                       'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
+                      'src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h',
                       'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
                       'src/core/ext/upb-generated/validate/validate.upb.h',
+                      'src/core/ext/upb-generated/validate/validate.upbdefs.h',
                       'src/core/lib/avl/avl.h',
                       'src/core/lib/backoff/backoff.h',
                       'src/core/lib/channel/channel_args.h',
@@ -616,6 +682,7 @@ Pod::Spec.new do |s|
                       'src/core/tsi/transport_security_grpc.h',
                       'src/core/tsi/transport_security_interface.h',
                       'src/cpp/client/channel_cc.cc',
+                      'src/cpp/client/client_callback.cc',
                       'src/cpp/client/client_context.cc',
                       'src/cpp/client/client_interceptor.cc',
                       'src/cpp/client/create_channel.cc',
@@ -673,19 +740,23 @@ Pod::Spec.new do |s|
                       'src/cpp/util/string_ref.cc',
                       'src/cpp/util/time_cc.cc',
                       'third_party/upb/upb/decode.h',
+                      'third_party/upb/upb/def.h',
                       'third_party/upb/upb/encode.h',
-                      'third_party/upb/upb/generated_util.h',
                       'third_party/upb/upb/msg.h',
                       'third_party/upb/upb/port_def.inc',
                       'third_party/upb/upb/port_undef.inc',
+                      'third_party/upb/upb/reflection.h',
                       'third_party/upb/upb/table.int.h',
-                      'third_party/upb/upb/upb.h'
+                      'third_party/upb/upb/text_encode.h',
+                      'third_party/upb/upb/upb.h',
+                      'third_party/upb/upb/upb.hpp'
 
     ss.private_header_files = 'src/core/ext/filters/client_channel/backend_metric.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_channelz.h',
                               'src/core/ext/filters/client_channel/client_channel_factory.h',
+                              'src/core/ext/filters/client_channel/config_selector.h',
                               'src/core/ext/filters/client_channel/connector.h',
                               'src/core/ext/filters/client_channel/global_subchannel_pool.h',
                               'src/core/ext/filters/client_channel/health/health_check_client.h',
@@ -768,78 +839,145 @@ Pod::Spec.new do |s|
                               'src/core/ext/transport/chttp2/transport/varint.h',
                               'src/core/ext/transport/inproc/inproc_transport.h',
                               'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h',
+                              'src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/annotations/resource.upb.h',
+                              'src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/eds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/lds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/listener.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/rds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/route.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/srds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h',
+                              'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h',
+                              'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/http.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/http.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/matcher/string.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/percent.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/percent.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/range.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/range.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/semantic_version.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h',
                               'src/core/ext/upb-generated/gogoproto/gogo.upb.h',
+                              'src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h',
                               'src/core/ext/upb-generated/google/api/annotations.upb.h',
+                              'src/core/ext/upb-generated/google/api/annotations.upbdefs.h',
                               'src/core/ext/upb-generated/google/api/http.upb.h',
+                              'src/core/ext/upb-generated/google/api/http.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/any.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/any.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/descriptor.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/duration.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/empty.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/struct.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/timestamp.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/wrappers.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h',
                               'src/core/ext/upb-generated/google/rpc/status.upb.h',
+                              'src/core/ext/upb-generated/google/rpc/status.upbdefs.h',
                               'src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
+                              'src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h',
                               'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
+                              'src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h',
                               'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
+                              'src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h',
                               'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
                               'src/core/ext/upb-generated/validate/validate.upb.h',
+                              'src/core/ext/upb-generated/validate/validate.upbdefs.h',
                               'src/core/lib/avl/avl.h',
                               'src/core/lib/backoff/backoff.h',
                               'src/core/lib/channel/channel_args.h',
@@ -1086,13 +1224,16 @@ Pod::Spec.new do |s|
                               'src/cpp/server/thread_pool_interface.h',
                               'src/cpp/thread_manager/thread_manager.h',
                               'third_party/upb/upb/decode.h',
+                              'third_party/upb/upb/def.h',
                               'third_party/upb/upb/encode.h',
-                              'third_party/upb/upb/generated_util.h',
                               'third_party/upb/upb/msg.h',
                               'third_party/upb/upb/port_def.inc',
                               'third_party/upb/upb/port_undef.inc',
+                              'third_party/upb/upb/reflection.h',
                               'third_party/upb/upb/table.int.h',
-                              'third_party/upb/upb/upb.h'
+                              'third_party/upb/upb/text_encode.h',
+                              'third_party/upb/upb/upb.h',
+                              'third_party/upb/upb/upb.hpp'
   end
 
   s.subspec 'Protobuf' do |ss|
@@ -1125,8 +1266,8 @@ Pod::Spec.new do |s|
 
   s.prepare_command = <<-END_OF_COMMAND
     sed -E -i '' 's;#include <openssl/(.*)>;#if COCOAPODS==1\\\n  #include <openssl_grpc/\\1>\\\n#else\\\n  #include <openssl/\\1>\\\n#endif;g' $(find src/core -type f \\( -path '*.h' -or -path '*.cc' \\) -print | xargs grep -H -c '#include <openssl_grpc/' | grep 0$ | cut -d':' -f1)
-    find src/core/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "upb/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/upb/\\1"\\\n#else\\\n  #include  "upb/\\1"\\\n#endif;g'
-    find src/core/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
+    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "upb/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/upb/\\1"\\\n#else\\\n  #include  "upb/\\1"\\\n#endif;g'
+    find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
     find src/core/ src/cpp/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upb.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upb-generated/\\1.upb.h"\\\n#else\\\n  #include  "\\1.upb.h"\\\n#endif;g'
     find src/core/ src/cpp/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
   END_OF_COMMAND

+ 224 - 9
gRPC-Core.podspec

@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-Core'
-  version = '1.30.0-dev'
+  version = '1.31.0-dev'
   s.version  = version
   s.summary  = 'Core cross-platform gRPC library, written in C'
   s.homepage = 'https://grpc.io'
@@ -195,6 +195,8 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/client_channel_factory.cc',
                       'src/core/ext/filters/client_channel/client_channel_factory.h',
                       'src/core/ext/filters/client_channel/client_channel_plugin.cc',
+                      'src/core/ext/filters/client_channel/config_selector.cc',
+                      'src/core/ext/filters/client_channel/config_selector.h',
                       'src/core/ext/filters/client_channel/connector.h',
                       'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
                       'src/core/ext/filters/client_channel/global_subchannel_pool.h',
@@ -277,6 +279,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/service_config.cc',
                       'src/core/ext/filters/client_channel/service_config.h',
                       'src/core/ext/filters/client_channel/service_config_call_data.h',
+                      'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
                       'src/core/ext/filters/client_channel/service_config_parser.cc',
                       'src/core/ext/filters/client_channel/service_config_parser.h',
                       'src/core/ext/filters/client_channel/subchannel.cc',
@@ -380,130 +383,256 @@ Pod::Spec.new do |s|
                       'src/core/ext/transport/inproc/inproc_transport.h',
                       'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c',
                       'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h',
+                      'src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/annotations/resource.upb.c',
                       'src/core/ext/upb-generated/envoy/annotations/resource.upb.h',
+                      'src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cds.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/cds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/eds.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/eds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/lds.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/lds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/listener.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/listener.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/rds.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/rds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/route.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/route.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/api/v2/srds.upb.c',
                       'src/core/ext/upb-generated/envoy/api/v2/srds.upb.h',
+                      'src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c',
                       'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c',
                       'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c',
                       'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c',
                       'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h',
+                      'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c',
                       'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h',
+                      'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c',
                       'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h',
+                      'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/http.upb.c',
                       'src/core/ext/upb-generated/envoy/type/http.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/http.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/type/http.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c',
                       'src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/matcher/string.upb.c',
                       'src/core/ext/upb-generated/envoy/type/matcher/string.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c',
                       'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/percent.upb.c',
                       'src/core/ext/upb-generated/envoy/type/percent.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/percent.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/type/percent.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/range.upb.c',
                       'src/core/ext/upb-generated/envoy/type/range.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/range.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/type/range.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/semantic_version.upb.c',
                       'src/core/ext/upb-generated/envoy/type/semantic_version.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h',
                       'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c',
                       'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h',
+                      'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c',
+                      'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h',
                       'src/core/ext/upb-generated/gogoproto/gogo.upb.c',
                       'src/core/ext/upb-generated/gogoproto/gogo.upb.h',
+                      'src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c',
+                      'src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h',
                       'src/core/ext/upb-generated/google/api/annotations.upb.c',
                       'src/core/ext/upb-generated/google/api/annotations.upb.h',
+                      'src/core/ext/upb-generated/google/api/annotations.upbdefs.c',
+                      'src/core/ext/upb-generated/google/api/annotations.upbdefs.h',
                       'src/core/ext/upb-generated/google/api/http.upb.c',
                       'src/core/ext/upb-generated/google/api/http.upb.h',
+                      'src/core/ext/upb-generated/google/api/http.upbdefs.c',
+                      'src/core/ext/upb-generated/google/api/http.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/any.upb.c',
                       'src/core/ext/upb-generated/google/protobuf/any.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/any.upbdefs.c',
+                      'src/core/ext/upb-generated/google/protobuf/any.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/descriptor.upb.c',
                       'src/core/ext/upb-generated/google/protobuf/descriptor.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c',
+                      'src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/duration.upb.c',
                       'src/core/ext/upb-generated/google/protobuf/duration.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c',
+                      'src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/empty.upb.c',
                       'src/core/ext/upb-generated/google/protobuf/empty.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c',
+                      'src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/struct.upb.c',
                       'src/core/ext/upb-generated/google/protobuf/struct.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c',
+                      'src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/timestamp.upb.c',
                       'src/core/ext/upb-generated/google/protobuf/timestamp.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c',
+                      'src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h',
                       'src/core/ext/upb-generated/google/protobuf/wrappers.upb.c',
                       'src/core/ext/upb-generated/google/protobuf/wrappers.upb.h',
+                      'src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c',
+                      'src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h',
                       'src/core/ext/upb-generated/google/rpc/status.upb.c',
                       'src/core/ext/upb-generated/google/rpc/status.upb.h',
+                      'src/core/ext/upb-generated/google/rpc/status.upbdefs.c',
+                      'src/core/ext/upb-generated/google/rpc/status.upbdefs.h',
                       'src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c',
                       'src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h',
                       'src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c',
@@ -516,14 +645,22 @@ Pod::Spec.new do |s|
                       'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
                       'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
                       'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
+                      'src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c',
+                      'src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h',
                       'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
                       'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
+                      'src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c',
+                      'src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h',
                       'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
                       'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
+                      'src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c',
+                      'src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h',
                       'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
                       'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
                       'src/core/ext/upb-generated/validate/validate.upb.c',
                       'src/core/ext/upb-generated/validate/validate.upb.h',
+                      'src/core/ext/upb-generated/validate/validate.upbdefs.c',
+                      'src/core/ext/upb-generated/validate/validate.upbdefs.h',
                       'src/core/lib/avl/avl.cc',
                       'src/core/lib/avl/avl.h',
                       'src/core/lib/backoff/backoff.cc',
@@ -1034,23 +1171,30 @@ Pod::Spec.new do |s|
                       'src/core/tsi/transport_security_interface.h',
                       'third_party/upb/upb/decode.c',
                       'third_party/upb/upb/decode.h',
+                      'third_party/upb/upb/def.c',
+                      'third_party/upb/upb/def.h',
                       'third_party/upb/upb/encode.c',
                       'third_party/upb/upb/encode.h',
-                      'third_party/upb/upb/generated_util.h',
                       'third_party/upb/upb/msg.c',
                       'third_party/upb/upb/msg.h',
                       'third_party/upb/upb/port.c',
                       'third_party/upb/upb/port_def.inc',
                       'third_party/upb/upb/port_undef.inc',
+                      'third_party/upb/upb/reflection.c',
+                      'third_party/upb/upb/reflection.h',
                       'third_party/upb/upb/table.c',
                       'third_party/upb/upb/table.int.h',
+                      'third_party/upb/upb/text_encode.c',
+                      'third_party/upb/upb/text_encode.h',
                       'third_party/upb/upb/upb.c',
-                      'third_party/upb/upb/upb.h'
+                      'third_party/upb/upb/upb.h',
+                      'third_party/upb/upb/upb.hpp'
     ss.private_header_files = 'src/core/ext/filters/client_channel/backend_metric.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_channelz.h',
                               'src/core/ext/filters/client_channel/client_channel_factory.h',
+                              'src/core/ext/filters/client_channel/config_selector.h',
                               'src/core/ext/filters/client_channel/connector.h',
                               'src/core/ext/filters/client_channel/global_subchannel_pool.h',
                               'src/core/ext/filters/client_channel/health/health_check_client.h',
@@ -1133,78 +1277,145 @@ Pod::Spec.new do |s|
                               'src/core/ext/transport/chttp2/transport/varint.h',
                               'src/core/ext/transport/inproc/inproc_transport.h',
                               'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h',
+                              'src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/annotations/resource.upb.h',
+                              'src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/eds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/lds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/listener.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/rds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/route.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/api/v2/srds.upb.h',
+                              'src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h',
+                              'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h',
+                              'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h',
+                              'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/http.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/http.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/matcher/string.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/percent.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/percent.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/range.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/range.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/semantic_version.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h',
                               'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h',
+                              'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h',
                               'src/core/ext/upb-generated/gogoproto/gogo.upb.h',
+                              'src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h',
                               'src/core/ext/upb-generated/google/api/annotations.upb.h',
+                              'src/core/ext/upb-generated/google/api/annotations.upbdefs.h',
                               'src/core/ext/upb-generated/google/api/http.upb.h',
+                              'src/core/ext/upb-generated/google/api/http.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/any.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/any.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/descriptor.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/duration.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/empty.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/struct.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/timestamp.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h',
                               'src/core/ext/upb-generated/google/protobuf/wrappers.upb.h',
+                              'src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h',
                               'src/core/ext/upb-generated/google/rpc/status.upb.h',
+                              'src/core/ext/upb-generated/google/rpc/status.upbdefs.h',
                               'src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h',
                               'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
                               'src/core/ext/upb-generated/udpa/annotations/migrate.upb.h',
+                              'src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h',
                               'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h',
+                              'src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h',
                               'src/core/ext/upb-generated/udpa/annotations/status.upb.h',
+                              'src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h',
                               'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h',
                               'src/core/ext/upb-generated/validate/validate.upb.h',
+                              'src/core/ext/upb-generated/validate/validate.upbdefs.h',
                               'src/core/lib/avl/avl.h',
                               'src/core/lib/backoff/backoff.h',
                               'src/core/lib/channel/channel_args.h',
@@ -1440,13 +1651,16 @@ Pod::Spec.new do |s|
                               'src/core/tsi/transport_security_grpc.h',
                               'src/core/tsi/transport_security_interface.h',
                               'third_party/upb/upb/decode.h',
+                              'third_party/upb/upb/def.h',
                               'third_party/upb/upb/encode.h',
-                              'third_party/upb/upb/generated_util.h',
                               'third_party/upb/upb/msg.h',
                               'third_party/upb/upb/port_def.inc',
                               'third_party/upb/upb/port_undef.inc',
+                              'third_party/upb/upb/reflection.h',
                               'third_party/upb/upb/table.int.h',
-                              'third_party/upb/upb/upb.h'
+                              'third_party/upb/upb/text_encode.h',
+                              'third_party/upb/upb/upb.h',
+                              'third_party/upb/upb/upb.hpp'
   end
 
   # CFStream is now default. Leaving this subspec only for compatibility purpose.
@@ -1617,9 +1831,10 @@ Pod::Spec.new do |s|
   # TODO (mxyan): Instead of this hack, add include path "third_party" to C core's include path?
   s.prepare_command = <<-END_OF_COMMAND
     sed -E -i '' 's;#include <openssl/(.*)>;#if COCOAPODS==1\\\n  #include <openssl_grpc/\\1>\\\n#else\\\n  #include <openssl/\\1>\\\n#endif;g' $(find src/core -type f \\( -path '*.h' -or -path '*.cc' \\) -print | xargs grep -H -c '#include <openssl_grpc/' | grep 0$ | cut -d':' -f1)
-    find src/core/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "upb/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/upb/\\1"\\\n#else\\\n  #include  "upb/\\1"\\\n#endif;g'
-    find src/core/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
-    find src/core/ src/cpp/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upb.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upb-generated/\\1.upb.h"\\\n#else\\\n  #include  "\\1.upb.h"\\\n#endif;g'
-    find src/core/ src/cpp/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
+    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.hpp' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "upb/(.*)";#if COCOAPODS==1\\\n  #include  "third_party/upb/upb/\\1"\\\n#else\\\n  #include  "upb/\\1"\\\n#endif;g'
+    find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
+    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upb.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upb-generated/\\1.upb.h"\\\n#else\\\n  #include  "\\1.upb.h"\\\n#endif;g'
+    find src/core/ src/cpp/ third_party/upb/ -type f \\( -name '*.h' -or -name '*.c' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(.*).upbdefs.h";#if COCOAPODS==1\\\n  #include  "src/core/ext/upb-generated/\\1.upbdefs.h"\\\n#else\\\n  #include  "\\1.upbdefs.h"\\\n#endif;g'
+    find src/core/ src/cpp/ third_party/upb/ -type f -name '*.grpc_back' -print0 | xargs -0 rm
   END_OF_COMMAND
 end

+ 1 - 1
gRPC-ProtoRPC.podspec

@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-ProtoRPC'
-  version = '1.30.0-dev'
+  version = '1.31.0-dev'
   s.version  = version
   s.summary  = 'RPC library for Protocol Buffers, based on gRPC'
   s.homepage = 'https://grpc.io'

+ 1 - 1
gRPC-RxLibrary.podspec

@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-RxLibrary'
-  version = '1.30.0-dev'
+  version = '1.31.0-dev'
   s.version  = version
   s.summary  = 'Reactive Extensions library for iOS/OSX.'
   s.homepage = 'https://grpc.io'

+ 1 - 1
gRPC.podspec

@@ -20,7 +20,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC'
-  version = '1.30.0-dev'
+  version = '1.31.0-dev'
   s.version  = version
   s.summary  = 'gRPC client library for iOS/OSX'
   s.homepage = 'https://grpc.io'

+ 144 - 1
grpc.gemspec

@@ -117,6 +117,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.cc )
   s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.h )
   s.files += %w( src/core/ext/filters/client_channel/client_channel_plugin.cc )
+  s.files += %w( src/core/ext/filters/client_channel/config_selector.cc )
+  s.files += %w( src/core/ext/filters/client_channel/config_selector.h )
   s.files += %w( src/core/ext/filters/client_channel/connector.h )
   s.files += %w( src/core/ext/filters/client_channel/global_subchannel_pool.cc )
   s.files += %w( src/core/ext/filters/client_channel/global_subchannel_pool.h )
@@ -199,6 +201,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/service_config.cc )
   s.files += %w( src/core/ext/filters/client_channel/service_config.h )
   s.files += %w( src/core/ext/filters/client_channel/service_config_call_data.h )
+  s.files += %w( src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc )
   s.files += %w( src/core/ext/filters/client_channel/service_config_parser.cc )
   s.files += %w( src/core/ext/filters/client_channel/service_config_parser.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.cc )
@@ -302,130 +305,256 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/transport/inproc/inproc_transport.h )
   s.files += %w( src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/annotations/resource.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/annotations/resource.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cds.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cds.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/eds.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/eds.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/lds.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/lds.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/rds.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/rds.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/srds.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/api/v2/srds.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/type/http.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/type/http.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/http.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/http.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/string.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/string.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/type/percent.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/type/percent.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/percent.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/percent.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/type/range.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/type/range.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/range.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/range.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/type/semantic_version.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/type/semantic_version.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c )
   s.files += %w( src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/gogoproto/gogo.upb.c )
   s.files += %w( src/core/ext/upb-generated/gogoproto/gogo.upb.h )
+  s.files += %w( src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/api/annotations.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/api/annotations.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/api/annotations.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/api/annotations.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/api/http.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/api/http.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/api/http.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/api/http.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/any.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/any.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/any.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/any.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/descriptor.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/descriptor.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/duration.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/duration.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/empty.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/empty.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/struct.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/struct.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/timestamp.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/timestamp.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/wrappers.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/protobuf/wrappers.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/google/rpc/status.upb.c )
   s.files += %w( src/core/ext/upb-generated/google/rpc/status.upb.h )
+  s.files += %w( src/core/ext/upb-generated/google/rpc/status.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/google/rpc/status.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c )
   s.files += %w( src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h )
   s.files += %w( src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c )
@@ -438,14 +567,22 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upb.c )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upb.h )
+  s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h )
+  s.files += %w( src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/status.upb.c )
   s.files += %w( src/core/ext/upb-generated/udpa/annotations/status.upb.h )
+  s.files += %w( src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h )
   s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c )
   s.files += %w( src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h )
   s.files += %w( src/core/ext/upb-generated/validate/validate.upb.c )
   s.files += %w( src/core/ext/upb-generated/validate/validate.upb.h )
+  s.files += %w( src/core/ext/upb-generated/validate/validate.upbdefs.c )
+  s.files += %w( src/core/ext/upb-generated/validate/validate.upbdefs.h )
   s.files += %w( src/core/lib/avl/avl.cc )
   s.files += %w( src/core/lib/avl/avl.h )
   s.files += %w( src/core/lib/backoff/backoff.cc )
@@ -1654,18 +1791,24 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/cares/config_openbsd/ares_config.h )
   s.files += %w( third_party/upb/upb/decode.c )
   s.files += %w( third_party/upb/upb/decode.h )
+  s.files += %w( third_party/upb/upb/def.c )
+  s.files += %w( third_party/upb/upb/def.h )
   s.files += %w( third_party/upb/upb/encode.c )
   s.files += %w( third_party/upb/upb/encode.h )
-  s.files += %w( third_party/upb/upb/generated_util.h )
   s.files += %w( third_party/upb/upb/msg.c )
   s.files += %w( third_party/upb/upb/msg.h )
   s.files += %w( third_party/upb/upb/port.c )
   s.files += %w( third_party/upb/upb/port_def.inc )
   s.files += %w( third_party/upb/upb/port_undef.inc )
+  s.files += %w( third_party/upb/upb/reflection.c )
+  s.files += %w( third_party/upb/upb/reflection.h )
   s.files += %w( third_party/upb/upb/table.c )
   s.files += %w( third_party/upb/upb/table.int.h )
+  s.files += %w( third_party/upb/upb/text_encode.c )
+  s.files += %w( third_party/upb/upb/text_encode.h )
   s.files += %w( third_party/upb/upb/upb.c )
   s.files += %w( third_party/upb/upb/upb.h )
+  s.files += %w( third_party/upb/upb/upb.hpp )
   s.files += %w( third_party/zlib/adler32.c )
   s.files += %w( third_party/zlib/compress.c )
   s.files += %w( third_party/zlib/crc32.c )

+ 157 - 2
grpc.gyp

@@ -440,6 +440,7 @@
         'src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc',
         'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
         'src/core/ext/filters/client_channel/health/health_check_client.cc',
         'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
@@ -487,6 +488,7 @@
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/server_address.cc',
         'src/core/ext/filters/client_channel/service_config.cc',
+        'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
         'src/core/ext/filters/client_channel/service_config_parser.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
@@ -543,78 +545,144 @@
         'src/core/ext/transport/inproc/inproc_plugin.cc',
         'src/core/ext/transport/inproc/inproc_transport.cc',
         'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c',
+        'src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c',
         'src/core/ext/upb-generated/envoy/annotations/resource.upb.c',
+        'src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/eds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/lds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/listener.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/rds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/route.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/srds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c',
+        'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c',
         'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c',
+        'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c',
         'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c',
+        'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c',
         'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c',
+        'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c',
         'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c',
+        'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c',
         'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c',
+        'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/http.upb.c',
+        'src/core/ext/upb-generated/envoy/type/http.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c',
+        'src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/matcher/string.upb.c',
+        'src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c',
+        'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/percent.upb.c',
+        'src/core/ext/upb-generated/envoy/type/percent.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/range.upb.c',
+        'src/core/ext/upb-generated/envoy/type/range.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/semantic_version.upb.c',
+        'src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c',
+        'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c',
         'src/core/ext/upb-generated/gogoproto/gogo.upb.c',
+        'src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c',
         'src/core/ext/upb-generated/google/api/annotations.upb.c',
+        'src/core/ext/upb-generated/google/api/annotations.upbdefs.c',
         'src/core/ext/upb-generated/google/api/http.upb.c',
+        'src/core/ext/upb-generated/google/api/http.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/any.upb.c',
-        'src/core/ext/upb-generated/google/protobuf/descriptor.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/any.upbdefs.c',
+        'src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/duration.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/empty.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/struct.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/timestamp.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/wrappers.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c',
         'src/core/ext/upb-generated/google/rpc/status.upb.c',
+        'src/core/ext/upb-generated/google/rpc/status.upbdefs.c',
         'src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
+        'src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c',
         'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
+        'src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c',
         'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
+        'src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c',
         'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
         'src/core/ext/upb-generated/validate/validate.upb.c',
+        'src/core/ext/upb-generated/validate/validate.upbdefs.c',
         'src/core/lib/avl/avl.cc',
         'src/core/lib/backoff/backoff.cc',
         'src/core/lib/channel/channel_args.cc',
@@ -947,6 +1015,7 @@
         'src/core/ext/filters/client_channel/client_channel_channelz.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/config_selector.cc',
         'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
         'src/core/ext/filters/client_channel/health/health_check_client.cc',
         'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
@@ -994,6 +1063,7 @@
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/server_address.cc',
         'src/core/ext/filters/client_channel/service_config.cc',
+        'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
         'src/core/ext/filters/client_channel/service_config_parser.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
@@ -1048,75 +1118,141 @@
         'src/core/ext/transport/inproc/inproc_plugin.cc',
         'src/core/ext/transport/inproc/inproc_transport.cc',
         'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c',
+        'src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c',
         'src/core/ext/upb-generated/envoy/annotations/resource.upb.c',
+        'src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/eds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/lds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/listener.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/rds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/route.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c',
         'src/core/ext/upb-generated/envoy/api/v2/srds.upb.c',
+        'src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c',
         'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c',
+        'src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c',
         'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c',
+        'src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c',
         'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c',
+        'src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c',
         'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c',
+        'src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c',
         'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c',
+        'src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c',
         'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c',
+        'src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/http.upb.c',
+        'src/core/ext/upb-generated/envoy/type/http.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c',
+        'src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/matcher/string.upb.c',
+        'src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c',
+        'src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/percent.upb.c',
+        'src/core/ext/upb-generated/envoy/type/percent.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/range.upb.c',
+        'src/core/ext/upb-generated/envoy/type/range.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/semantic_version.upb.c',
+        'src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c',
         'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c',
+        'src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c',
         'src/core/ext/upb-generated/gogoproto/gogo.upb.c',
+        'src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c',
         'src/core/ext/upb-generated/google/api/annotations.upb.c',
+        'src/core/ext/upb-generated/google/api/annotations.upbdefs.c',
         'src/core/ext/upb-generated/google/api/http.upb.c',
+        'src/core/ext/upb-generated/google/api/http.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/any.upb.c',
-        'src/core/ext/upb-generated/google/protobuf/descriptor.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/any.upbdefs.c',
+        'src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/duration.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/empty.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/struct.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/timestamp.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c',
         'src/core/ext/upb-generated/google/protobuf/wrappers.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c',
         'src/core/ext/upb-generated/google/rpc/status.upb.c',
+        'src/core/ext/upb-generated/google/rpc/status.upbdefs.c',
         'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c',
         'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
         'src/core/ext/upb-generated/udpa/annotations/migrate.upb.c',
+        'src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c',
         'src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c',
+        'src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c',
         'src/core/ext/upb-generated/udpa/annotations/status.upb.c',
+        'src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c',
         'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c',
         'src/core/ext/upb-generated/validate/validate.upb.c',
+        'src/core/ext/upb-generated/validate/validate.upbdefs.c',
         'src/core/lib/avl/avl.cc',
         'src/core/lib/backoff/backoff.cc',
         'src/core/lib/channel/channel_args.cc',
@@ -1313,6 +1449,7 @@
       ],
       'sources': [
         'src/cpp/client/channel_cc.cc',
+        'src/cpp/client/client_callback.cc',
         'src/cpp/client/client_context.cc',
         'src/cpp/client/client_interceptor.cc',
         'src/cpp/client/create_channel.cc',
@@ -1464,6 +1601,7 @@
       ],
       'sources': [
         'src/cpp/client/channel_cc.cc',
+        'src/cpp/client/client_callback.cc',
         'src/cpp/client/client_context.cc',
         'src/cpp/client/client_interceptor.cc',
         'src/cpp/client/create_channel.cc',
@@ -1861,6 +1999,23 @@
         'third_party/upb/upb/port.c',
         'third_party/upb/upb/table.c',
         'third_party/upb/upb/upb.c',
+        'third_party/upb/upb/def.c',
+        'third_party/upb/upb/reflection.c',
+        'third_party/upb/upb/text_encode.c',
+        'src/core/ext/upb-generated/google/protobuf/any.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/any.upbdefs.c',
+        'src/core/ext/upb-generated/google/protobuf/descriptor.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c',
+        'src/core/ext/upb-generated/google/protobuf/duration.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c',
+        'src/core/ext/upb-generated/google/protobuf/empty.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c',
+        'src/core/ext/upb-generated/google/protobuf/struct.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c',
+        'src/core/ext/upb-generated/google/protobuf/timestamp.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c',
+        'src/core/ext/upb-generated/google/protobuf/wrappers.upb.c',
+        'src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c',
       ],
     },
     {

+ 10 - 7
include/grpc/impl/codegen/grpc_types.h

@@ -203,18 +203,19 @@ typedef struct {
 /** Should BDP probing be performed? */
 #define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe"
 /** Minimum time between sending successive ping frames without receiving any
-    data frame, Int valued, milliseconds. */
+    data/header frame, Int valued, milliseconds. */
 #define GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS \
   "grpc.http2.min_time_between_pings_ms"
 /** Minimum allowed time between a server receiving successive ping frames
-   without sending any data frame. Int valued, milliseconds */
+   without sending any data/header frame. Int valued, milliseconds
+ */
 #define GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS \
   "grpc.http2.min_ping_interval_without_data_ms"
 /** Channel arg to override the http2 :scheme header */
 #define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme"
-/** How many pings can we send before needing to send a data frame or header
-    frame? (0 indicates that an infinite number of pings can be sent without
-    sending a data frame or header frame) */
+/** How many pings can we send before needing to send a
+   data/header frame? (0 indicates that an infinite number of
+   pings can be sent without sending a data frame or header frame) */
 #define GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA \
   "grpc.http2.max_pings_without_data"
 /** How many misbehaving pings the server can bear before sending goaway and
@@ -673,8 +674,10 @@ typedef struct grpc_op {
       const char** error_string;
     } recv_status_on_client;
     struct grpc_op_recv_close_on_server {
-      /** out argument, set to 1 if the call failed in any way (seen as a
-          cancellation on the server), or 0 if the call succeeded */
+      /** out argument, set to 1 if the call failed at the server for
+          a reason other than a non-OK status (cancel, deadline
+          exceeded, network failure, etc.), 0 otherwise (RPC processing ran to
+          completion and was able to provide any status from the server) */
       int* cancelled;
     } recv_close_on_server;
   } data;

+ 0 - 25
include/grpc/impl/codegen/port_platform.h

@@ -112,31 +112,6 @@
 #define GPR_WINDOWS_ATOMIC 1
 #define GPR_MSVC_TLS 1
 #endif
-#elif defined(GPR_MANYLINUX1)
-// TODO(atash): manylinux1 is just another __linux__ but with ancient
-// libraries; it should be integrated with the `__linux__` definitions below.
-#define GPR_PLATFORM_STRING "manylinux"
-#define GPR_POSIX_CRASH_HANDLER 1
-#define GPR_CPU_POSIX 1
-#define GPR_GCC_ATOMIC 1
-#define GPR_GCC_TLS 1
-#define GPR_LINUX 1
-#define GPR_LINUX_LOG 1
-#define GPR_SUPPORT_CHANNELS_FROM_FD 1
-#define GPR_LINUX_ENV 1
-#define GPR_POSIX_TMPFILE 1
-#define GPR_POSIX_STRING 1
-#define GPR_POSIX_SUBPROCESS 1
-#define GPR_POSIX_SYNC 1
-#define GPR_POSIX_TIME 1
-#define GPR_HAS_PTHREAD_H 1
-#define GPR_GETPID_IN_UNISTD_H 1
-#ifdef _LP64
-#define GPR_ARCH_64 1
-#else /* _LP64 */
-#define GPR_ARCH_32 1
-#endif /* _LP64 */
-#include <linux/version.h>
 #elif defined(ANDROID) || defined(__ANDROID__)
 #define GPR_PLATFORM_STRING "android"
 #define GPR_ANDROID 1

+ 28 - 11
include/grpcpp/health_check_service_interface.h

@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2019 gRPC authors.
+ * 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.
@@ -19,22 +19,39 @@
 #ifndef GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H
 #define GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H
 
-#include <grpcpp/health_check_service_interface_impl.h>
+#include <grpcpp/support/config.h>
 
 namespace grpc {
 
 const char kHealthCheckServiceInterfaceArg[] =
     "grpc.health_check_service_interface";
 
-typedef ::grpc_impl::HealthCheckServiceInterface HealthCheckServiceInterface;
-
-static inline void EnableDefaultHealthCheckService(bool enable) {
-  ::grpc_impl::EnableDefaultHealthCheckService(enable);
-}
-
-static inline bool DefaultHealthCheckServiceEnabled() {
-  return ::grpc_impl::DefaultHealthCheckServiceEnabled();
-}
+/// The gRPC server uses this interface to expose the health checking service
+/// without depending on protobuf.
+class HealthCheckServiceInterface {
+ public:
+  virtual ~HealthCheckServiceInterface() {}
+
+  /// Set or change the serving status of the given \a service_name.
+  virtual void SetServingStatus(const grpc::string& service_name,
+                                bool serving) = 0;
+  /// Apply to all registered service names.
+  virtual void SetServingStatus(bool serving) = 0;
+
+  /// Set all registered service names to not serving and prevent future
+  /// state changes.
+  virtual void Shutdown() {}
+};
+
+/// Enable/disable the default health checking service. This applies to all C++
+/// servers created afterwards. For each server, user can override the default
+/// with a HealthCheckServiceServerBuilderOption.
+/// NOT thread safe.
+void EnableDefaultHealthCheckService(bool enable);
+
+/// Returns whether the default health checking service is enabled.
+/// NOT thread safe.
+bool DefaultHealthCheckServiceEnabled();
 
 }  // namespace grpc
 

+ 0 - 55
include/grpcpp/health_check_service_interface_impl.h

@@ -1,55 +0,0 @@
-/*
- *
- * Copyright 2016 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H
-#define GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H
-
-#include <grpcpp/support/config.h>
-
-namespace grpc_impl {
-
-/// The gRPC server uses this interface to expose the health checking service
-/// without depending on protobuf.
-class HealthCheckServiceInterface {
- public:
-  virtual ~HealthCheckServiceInterface() {}
-
-  /// Set or change the serving status of the given \a service_name.
-  virtual void SetServingStatus(const grpc::string& service_name,
-                                bool serving) = 0;
-  /// Apply to all registered service names.
-  virtual void SetServingStatus(bool serving) = 0;
-
-  /// Set all registered service names to not serving and prevent future
-  /// state changes.
-  virtual void Shutdown() {}
-};
-
-/// Enable/disable the default health checking service. This applies to all C++
-/// servers created afterwards. For each server, user can override the default
-/// with a HealthCheckServiceServerBuilderOption.
-/// NOT thread safe.
-void EnableDefaultHealthCheckService(bool enable);
-
-/// Returns whether the default health checking service is enabled.
-/// NOT thread safe.
-bool DefaultHealthCheckServiceEnabled();
-
-}  // namespace grpc_impl
-
-#endif  // GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H

+ 333 - 212
include/grpcpp/impl/codegen/client_callback_impl.h

@@ -101,6 +101,29 @@ class CallbackUnaryCallImpl {
     call.PerformOps(ops);
   }
 };
+
+// Base class for public API classes.
+class ClientReactor {
+ public:
+  /// Called by the library when all operations associated with this RPC have
+  /// completed and all Holds have been removed. OnDone provides the RPC status
+  /// outcome for both successful and failed RPCs. If it is never called on an
+  /// RPC, it indicates an application-level problem (like failure to remove a
+  /// hold).
+  ///
+  /// \param[in] s The status outcome of this RPC
+  virtual void OnDone(const ::grpc::Status& /*s*/) = 0;
+
+  /// InternalScheduleOnDone is not part of the API and is not meant to be
+  /// overridden. It is virtual to allow successful builds for certain bazel
+  /// build users that only want to depend on gRPC codegen headers and not the
+  /// full library (although this is not a generally-supported option). Although
+  /// the virtual call is slower than a direct call, this function is
+  /// heavyweight and the cost of the virtual call is not much in comparison.
+  /// This function may be removed or devirtualized in the future.
+  virtual void InternalScheduleOnDone(::grpc::Status s);
+};
+
 }  // namespace internal
 
 // Forward declarations
@@ -189,7 +212,7 @@ class ClientCallbackUnary {
 
 /// \a ClientBidiReactor is the interface for a bidirectional streaming RPC.
 template <class Request, class Response>
-class ClientBidiReactor {
+class ClientBidiReactor : public internal::ClientReactor {
  public:
   virtual ~ClientBidiReactor() {}
 
@@ -282,7 +305,7 @@ class ClientBidiReactor {
   /// (like failure to remove a hold).
   ///
   /// \param[in] s The status outcome of this RPC
-  virtual void OnDone(const ::grpc::Status& /*s*/) {}
+  void OnDone(const ::grpc::Status& /*s*/) override {}
 
   /// Notifies the application that a read of initial metadata from the
   /// server is done. If the application chooses not to implement this method,
@@ -327,7 +350,7 @@ class ClientBidiReactor {
 /// \a ClientReadReactor is the interface for a server-streaming RPC.
 /// All public methods behave as in ClientBidiReactor.
 template <class Response>
-class ClientReadReactor {
+class ClientReadReactor : public internal::ClientReactor {
  public:
   virtual ~ClientReadReactor() {}
 
@@ -341,7 +364,7 @@ class ClientReadReactor {
   }
   void RemoveHold() { reader_->RemoveHold(); }
 
-  virtual void OnDone(const ::grpc::Status& /*s*/) {}
+  void OnDone(const ::grpc::Status& /*s*/) override {}
   virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
   virtual void OnReadDone(bool /*ok*/) {}
 
@@ -354,7 +377,7 @@ class ClientReadReactor {
 /// \a ClientWriteReactor is the interface for a client-streaming RPC.
 /// All public methods behave as in ClientBidiReactor.
 template <class Request>
-class ClientWriteReactor {
+class ClientWriteReactor : public internal::ClientReactor {
  public:
   virtual ~ClientWriteReactor() {}
 
@@ -377,7 +400,7 @@ class ClientWriteReactor {
   }
   void RemoveHold() { writer_->RemoveHold(); }
 
-  virtual void OnDone(const ::grpc::Status& /*s*/) {}
+  void OnDone(const ::grpc::Status& /*s*/) override {}
   virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
   virtual void OnWriteDone(bool /*ok*/) {}
   virtual void OnWritesDoneDone(bool /*ok*/) {}
@@ -385,6 +408,7 @@ class ClientWriteReactor {
  private:
   friend class ClientCallbackWriter<Request>;
   void BindWriter(ClientCallbackWriter<Request>* writer) { writer_ = writer; }
+
   ClientCallbackWriter<Request>* writer_;
 };
 
@@ -399,12 +423,12 @@ class ClientWriteReactor {
 /// call (that is part of the unary call itself) and there is no reactor object
 /// being created as a result of this call, we keep a consistent 2-phase
 /// initiation API among all the reactor flavors.
-class ClientUnaryReactor {
+class ClientUnaryReactor : public internal::ClientReactor {
  public:
   virtual ~ClientUnaryReactor() {}
 
   void StartCall() { call_->StartCall(); }
-  virtual void OnDone(const ::grpc::Status& /*s*/) {}
+  void OnDone(const ::grpc::Status& /*s*/) override {}
   virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
 
  private:
@@ -444,93 +468,56 @@ class ClientCallbackReaderWriterImpl
   // there are no tests catching the compiler warning.
   static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
 
-  void MaybeFinish() {
-    if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
-                         1, std::memory_order_acq_rel) == 1)) {
-      ::grpc::Status s = std::move(finish_status_);
-      auto* reactor = reactor_;
-      auto* call = call_.call();
-      this->~ClientCallbackReaderWriterImpl();
-      ::grpc::g_core_codegen_interface->grpc_call_unref(call);
-      reactor->OnDone(s);
-    }
-  }
-
   void StartCall() override {
     // This call initiates two batches, plus any backlog, each with a callback
     // 1. Send initial metadata (unless corked) + recv initial metadata
     // 2. Any read backlog
     // 3. Any write backlog
-    // 4. Recv trailing metadata, on_completion callback
-    started_ = true;
-
-    start_tag_.Set(call_.call(),
-                   [this](bool ok) {
-                     reactor_->OnReadInitialMetadataDone(ok);
-                     MaybeFinish();
-                   },
-                   &start_ops_, /*can_inline=*/false);
+    // 4. Recv trailing metadata (unless corked)
     if (!start_corked_) {
       start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
                                      context_->initial_metadata_flags());
     }
-    start_ops_.RecvInitialMetadata(context_);
-    start_ops_.set_core_cq_tag(&start_tag_);
-    call_.PerformOps(&start_ops_);
-
-    // Also set up the read and write tags so that they don't have to be set up
-    // each time
-    write_tag_.Set(call_.call(),
-                   [this](bool ok) {
-                     reactor_->OnWriteDone(ok);
-                     MaybeFinish();
-                   },
-                   &write_ops_, /*can_inline=*/false);
-    write_ops_.set_core_cq_tag(&write_tag_);
-
-    read_tag_.Set(call_.call(),
-                  [this](bool ok) {
-                    reactor_->OnReadDone(ok);
-                    MaybeFinish();
-                  },
-                  &read_ops_, /*can_inline=*/false);
-    read_ops_.set_core_cq_tag(&read_tag_);
-    if (read_ops_at_start_) {
-      call_.PerformOps(&read_ops_);
-    }
 
-    if (write_ops_at_start_) {
-      call_.PerformOps(&write_ops_);
-    }
+    call_.PerformOps(&start_ops_);
 
-    if (writes_done_ops_at_start_) {
-      call_.PerformOps(&writes_done_ops_);
+    {
+      grpc::internal::MutexLock lock(&start_mu_);
+
+      if (backlog_.read_ops) {
+        call_.PerformOps(&read_ops_);
+      }
+      if (backlog_.write_ops) {
+        call_.PerformOps(&write_ops_);
+      }
+      if (backlog_.writes_done_ops) {
+        call_.PerformOps(&writes_done_ops_);
+      }
+      call_.PerformOps(&finish_ops_);
+      // The last thing in this critical section is to set started_ so that it
+      // can be used lock-free as well.
+      started_.store(true, std::memory_order_release);
     }
-
-    finish_tag_.Set(call_.call(), [this](bool /*ok*/) { MaybeFinish(); },
-                    &finish_ops_, /*can_inline=*/false);
-    finish_ops_.ClientRecvStatus(context_, &finish_status_);
-    finish_ops_.set_core_cq_tag(&finish_tag_);
-    call_.PerformOps(&finish_ops_);
+    // MaybeFinish outside the lock to make sure that destruction of this object
+    // doesn't take place while holding the lock (which would cause the lock to
+    // be released after destruction)
+    this->MaybeFinish(/*from_reaction=*/false);
   }
 
   void Read(Response* msg) override {
     read_ops_.RecvMessage(msg);
     callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
-    if (started_) {
-      call_.PerformOps(&read_ops_);
-    } else {
-      read_ops_at_start_ = true;
+    if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+      grpc::internal::MutexLock lock(&start_mu_);
+      if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+        backlog_.read_ops = true;
+        return;
+      }
     }
+    call_.PerformOps(&read_ops_);
   }
 
   void Write(const Request* msg, ::grpc::WriteOptions options) override {
-    if (start_corked_) {
-      write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
-                                     context_->initial_metadata_flags());
-      start_corked_ = false;
-    }
-
     if (options.is_last_message()) {
       options.set_buffer_hint();
       write_ops_.ClientSendClose();
@@ -538,38 +525,50 @@ class ClientCallbackReaderWriterImpl
     // TODO(vjpai): don't assert
     GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg, options).ok());
     callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
-    if (started_) {
-      call_.PerformOps(&write_ops_);
-    } else {
-      write_ops_at_start_ = true;
+    if (GPR_UNLIKELY(corked_write_needed_)) {
+      write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                     context_->initial_metadata_flags());
+      corked_write_needed_ = false;
+    }
+
+    if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+      grpc::internal::MutexLock lock(&start_mu_);
+      if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+        backlog_.write_ops = true;
+        return;
+      }
     }
+    call_.PerformOps(&write_ops_);
   }
   void WritesDone() override {
-    if (start_corked_) {
-      writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
-                                           context_->initial_metadata_flags());
-      start_corked_ = false;
-    }
     writes_done_ops_.ClientSendClose();
     writes_done_tag_.Set(call_.call(),
                          [this](bool ok) {
                            reactor_->OnWritesDoneDone(ok);
-                           MaybeFinish();
+                           MaybeFinish(/*from_reaction=*/true);
                          },
                          &writes_done_ops_, /*can_inline=*/false);
     writes_done_ops_.set_core_cq_tag(&writes_done_tag_);
     callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
-    if (started_) {
-      call_.PerformOps(&writes_done_ops_);
-    } else {
-      writes_done_ops_at_start_ = true;
+    if (GPR_UNLIKELY(corked_write_needed_)) {
+      writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                           context_->initial_metadata_flags());
+      corked_write_needed_ = false;
+    }
+    if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+      grpc::internal::MutexLock lock(&start_mu_);
+      if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+        backlog_.writes_done_ops = true;
+        return;
+      }
     }
+    call_.PerformOps(&writes_done_ops_);
   }
 
   void AddHold(int holds) override {
     callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
   }
-  void RemoveHold() override { MaybeFinish(); }
+  void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
 
  private:
   friend class ClientCallbackReaderWriterFactory<Request, Response>;
@@ -580,8 +579,66 @@ class ClientCallbackReaderWriterImpl
       : context_(context),
         call_(call),
         reactor_(reactor),
-        start_corked_(context_->initial_metadata_corked_) {
+        start_corked_(context_->initial_metadata_corked_),
+        corked_write_needed_(start_corked_) {
     this->BindReactor(reactor);
+
+    // Set up the unchanging parts of the start, read, and write tags and ops.
+    start_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnReadInitialMetadataDone(ok);
+                     MaybeFinish(/*from_reaction=*/true);
+                   },
+                   &start_ops_, /*can_inline=*/false);
+    start_ops_.RecvInitialMetadata(context_);
+    start_ops_.set_core_cq_tag(&start_tag_);
+
+    write_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnWriteDone(ok);
+                     MaybeFinish(/*from_reaction=*/true);
+                   },
+                   &write_ops_, /*can_inline=*/false);
+    write_ops_.set_core_cq_tag(&write_tag_);
+
+    read_tag_.Set(call_.call(),
+                  [this](bool ok) {
+                    reactor_->OnReadDone(ok);
+                    MaybeFinish(/*from_reaction=*/true);
+                  },
+                  &read_ops_, /*can_inline=*/false);
+    read_ops_.set_core_cq_tag(&read_tag_);
+
+    // Also set up the Finish tag and op set.
+    finish_tag_.Set(
+        call_.call(),
+        [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
+        &finish_ops_,
+        /*can_inline=*/false);
+    finish_ops_.ClientRecvStatus(context_, &finish_status_);
+    finish_ops_.set_core_cq_tag(&finish_tag_);
+  }
+
+  // MaybeFinish can be called from reactions or from user-initiated operations
+  // like StartCall or RemoveHold. If this is the last operation or hold on this
+  // object, it will invoke the OnDone reaction. If MaybeFinish was called from
+  // a reaction, it can call OnDone directly. If not, it would need to schedule
+  // OnDone onto an executor thread to avoid the possibility of deadlocking with
+  // any locks in the user code that invoked it.
+  void MaybeFinish(bool from_reaction) {
+    if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
+                         1, std::memory_order_acq_rel) == 1)) {
+      ::grpc::Status s = std::move(finish_status_);
+      auto* reactor = reactor_;
+      auto* call = call_.call();
+      this->~ClientCallbackReaderWriterImpl();
+      ::grpc::g_core_codegen_interface->grpc_call_unref(call);
+      if (GPR_LIKELY(from_reaction)) {
+        reactor->OnDone(s);
+      } else {
+        reactor->InternalScheduleOnDone(std::move(s));
+      }
+    }
   }
 
   ::grpc_impl::ClientContext* const context_;
@@ -592,7 +649,9 @@ class ClientCallbackReaderWriterImpl
                             grpc::internal::CallOpRecvInitialMetadata>
       start_ops_;
   grpc::internal::CallbackWithSuccessTag start_tag_;
-  bool start_corked_;
+  const bool start_corked_;
+  bool corked_write_needed_;  // no lock needed since only accessed in
+                              // Write/WritesDone which cannot be concurrent
 
   grpc::internal::CallOpSet<grpc::internal::CallOpClientRecvStatus> finish_ops_;
   grpc::internal::CallbackWithSuccessTag finish_tag_;
@@ -603,22 +662,27 @@ class ClientCallbackReaderWriterImpl
                             grpc::internal::CallOpClientSendClose>
       write_ops_;
   grpc::internal::CallbackWithSuccessTag write_tag_;
-  bool write_ops_at_start_{false};
 
   grpc::internal::CallOpSet<grpc::internal::CallOpSendInitialMetadata,
                             grpc::internal::CallOpClientSendClose>
       writes_done_ops_;
   grpc::internal::CallbackWithSuccessTag writes_done_tag_;
-  bool writes_done_ops_at_start_{false};
 
   grpc::internal::CallOpSet<grpc::internal::CallOpRecvMessage<Response>>
       read_ops_;
   grpc::internal::CallbackWithSuccessTag read_tag_;
-  bool read_ops_at_start_{false};
 
-  // Minimum of 2 callbacks to pre-register for start and finish
-  std::atomic<intptr_t> callbacks_outstanding_{2};
-  bool started_{false};
+  struct StartCallBacklog {
+    bool write_ops = false;
+    bool writes_done_ops = false;
+    bool read_ops = false;
+  };
+  StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */;
+
+  // Minimum of 3 callbacks to pre-register for start ops, StartCall, and finish
+  std::atomic<intptr_t> callbacks_outstanding_{3};
+  std::atomic_bool started_{false};
+  grpc::internal::Mutex start_mu_;
 };
 
 template <class Request, class Response>
@@ -654,29 +718,16 @@ class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
   // there are no tests catching the compiler warning.
   static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
 
-  void MaybeFinish() {
-    if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
-                         1, std::memory_order_acq_rel) == 1)) {
-      ::grpc::Status s = std::move(finish_status_);
-      auto* reactor = reactor_;
-      auto* call = call_.call();
-      this->~ClientCallbackReaderImpl();
-      ::grpc::g_core_codegen_interface->grpc_call_unref(call);
-      reactor->OnDone(s);
-    }
-  }
-
   void StartCall() override {
     // This call initiates two batches, plus any backlog, each with a callback
     // 1. Send initial metadata (unless corked) + recv initial metadata
     // 2. Any backlog
-    // 3. Recv trailing metadata, on_completion callback
-    started_ = true;
+    // 3. Recv trailing metadata
 
     start_tag_.Set(call_.call(),
                    [this](bool ok) {
                      reactor_->OnReadInitialMetadataDone(ok);
-                     MaybeFinish();
+                     MaybeFinish(/*from_reaction=*/true);
                    },
                    &start_ops_, /*can_inline=*/false);
     start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
@@ -689,16 +740,23 @@ class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
     read_tag_.Set(call_.call(),
                   [this](bool ok) {
                     reactor_->OnReadDone(ok);
-                    MaybeFinish();
+                    MaybeFinish(/*from_reaction=*/true);
                   },
                   &read_ops_, /*can_inline=*/false);
     read_ops_.set_core_cq_tag(&read_tag_);
-    if (read_ops_at_start_) {
-      call_.PerformOps(&read_ops_);
+
+    {
+      grpc::internal::MutexLock lock(&start_mu_);
+      if (backlog_.read_ops) {
+        call_.PerformOps(&read_ops_);
+      }
+      started_.store(true, std::memory_order_release);
     }
 
-    finish_tag_.Set(call_.call(), [this](bool /*ok*/) { MaybeFinish(); },
-                    &finish_ops_, /*can_inline=*/false);
+    finish_tag_.Set(
+        call_.call(),
+        [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
+        &finish_ops_, /*can_inline=*/false);
     finish_ops_.ClientRecvStatus(context_, &finish_status_);
     finish_ops_.set_core_cq_tag(&finish_tag_);
     call_.PerformOps(&finish_ops_);
@@ -707,17 +765,20 @@ class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
   void Read(Response* msg) override {
     read_ops_.RecvMessage(msg);
     callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
-    if (started_) {
-      call_.PerformOps(&read_ops_);
-    } else {
-      read_ops_at_start_ = true;
+    if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+      grpc::internal::MutexLock lock(&start_mu_);
+      if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+        backlog_.read_ops = true;
+        return;
+      }
     }
+    call_.PerformOps(&read_ops_);
   }
 
   void AddHold(int holds) override {
     callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
   }
-  void RemoveHold() override { MaybeFinish(); }
+  void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
 
  private:
   friend class ClientCallbackReaderFactory<Response>;
@@ -734,6 +795,23 @@ class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
     start_ops_.ClientSendClose();
   }
 
+  // MaybeFinish behaves as in ClientCallbackReaderWriterImpl.
+  void MaybeFinish(bool from_reaction) {
+    if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
+                         1, std::memory_order_acq_rel) == 1)) {
+      ::grpc::Status s = std::move(finish_status_);
+      auto* reactor = reactor_;
+      auto* call = call_.call();
+      this->~ClientCallbackReaderImpl();
+      ::grpc::g_core_codegen_interface->grpc_call_unref(call);
+      if (GPR_LIKELY(from_reaction)) {
+        reactor->OnDone(s);
+      } else {
+        reactor->InternalScheduleOnDone(std::move(s));
+      }
+    }
+  }
+
   ::grpc_impl::ClientContext* const context_;
   grpc::internal::Call call_;
   ClientReadReactor<Response>* const reactor_;
@@ -752,11 +830,16 @@ class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
   grpc::internal::CallOpSet<grpc::internal::CallOpRecvMessage<Response>>
       read_ops_;
   grpc::internal::CallbackWithSuccessTag read_tag_;
-  bool read_ops_at_start_{false};
+
+  struct StartCallBacklog {
+    bool read_ops = false;
+  };
+  StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */;
 
   // Minimum of 2 callbacks to pre-register for start and finish
   std::atomic<intptr_t> callbacks_outstanding_{2};
-  bool started_{false};
+  std::atomic_bool started_{false};
+  grpc::internal::Mutex start_mu_;
 };
 
 template <class Response>
@@ -793,110 +876,94 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter<Request> {
   // there are no tests catching the compiler warning.
   static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
 
-  void MaybeFinish() {
-    if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
-                         1, std::memory_order_acq_rel) == 1)) {
-      ::grpc::Status s = std::move(finish_status_);
-      auto* reactor = reactor_;
-      auto* call = call_.call();
-      this->~ClientCallbackWriterImpl();
-      ::grpc::g_core_codegen_interface->grpc_call_unref(call);
-      reactor->OnDone(s);
-    }
-  }
-
   void StartCall() override {
     // This call initiates two batches, plus any backlog, each with a callback
     // 1. Send initial metadata (unless corked) + recv initial metadata
     // 2. Any backlog
-    // 3. Recv trailing metadata, on_completion callback
-    started_ = true;
+    // 3. Recv trailing metadata
 
-    start_tag_.Set(call_.call(),
-                   [this](bool ok) {
-                     reactor_->OnReadInitialMetadataDone(ok);
-                     MaybeFinish();
-                   },
-                   &start_ops_, /*can_inline=*/false);
     if (!start_corked_) {
       start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
                                      context_->initial_metadata_flags());
     }
-    start_ops_.RecvInitialMetadata(context_);
-    start_ops_.set_core_cq_tag(&start_tag_);
     call_.PerformOps(&start_ops_);
 
-    // Also set up the read and write tags so that they don't have to be set up
-    // each time
-    write_tag_.Set(call_.call(),
-                   [this](bool ok) {
-                     reactor_->OnWriteDone(ok);
-                     MaybeFinish();
-                   },
-                   &write_ops_, /*can_inline=*/false);
-    write_ops_.set_core_cq_tag(&write_tag_);
-
-    if (write_ops_at_start_) {
-      call_.PerformOps(&write_ops_);
+    {
+      grpc::internal::MutexLock lock(&start_mu_);
+
+      if (backlog_.write_ops) {
+        call_.PerformOps(&write_ops_);
+      }
+      if (backlog_.writes_done_ops) {
+        call_.PerformOps(&writes_done_ops_);
+      }
+      call_.PerformOps(&finish_ops_);
+      // The last thing in this critical section is to set started_ so that it
+      // can be used lock-free as well.
+      started_.store(true, std::memory_order_release);
     }
-
-    if (writes_done_ops_at_start_) {
-      call_.PerformOps(&writes_done_ops_);
-    }
-
-    finish_tag_.Set(call_.call(), [this](bool /*ok*/) { MaybeFinish(); },
-                    &finish_ops_, /*can_inline=*/false);
-    finish_ops_.ClientRecvStatus(context_, &finish_status_);
-    finish_ops_.set_core_cq_tag(&finish_tag_);
-    call_.PerformOps(&finish_ops_);
+    // MaybeFinish outside the lock to make sure that destruction of this object
+    // doesn't take place while holding the lock (which would cause the lock to
+    // be released after destruction)
+    this->MaybeFinish(/*from_reaction=*/false);
   }
 
   void Write(const Request* msg, ::grpc::WriteOptions options) override {
-    if (start_corked_) {
-      write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
-                                     context_->initial_metadata_flags());
-      start_corked_ = false;
-    }
-
-    if (options.is_last_message()) {
+    if (GPR_UNLIKELY(options.is_last_message())) {
       options.set_buffer_hint();
       write_ops_.ClientSendClose();
     }
     // TODO(vjpai): don't assert
     GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg, options).ok());
     callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
-    if (started_) {
-      call_.PerformOps(&write_ops_);
-    } else {
-      write_ops_at_start_ = true;
+
+    if (GPR_UNLIKELY(corked_write_needed_)) {
+      write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                     context_->initial_metadata_flags());
+      corked_write_needed_ = false;
     }
+
+    if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+      grpc::internal::MutexLock lock(&start_mu_);
+      if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+        backlog_.write_ops = true;
+        return;
+      }
+    }
+    call_.PerformOps(&write_ops_);
   }
+
   void WritesDone() override {
-    if (start_corked_) {
-      writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
-                                           context_->initial_metadata_flags());
-      start_corked_ = false;
-    }
     writes_done_ops_.ClientSendClose();
     writes_done_tag_.Set(call_.call(),
                          [this](bool ok) {
                            reactor_->OnWritesDoneDone(ok);
-                           MaybeFinish();
+                           MaybeFinish(/*from_reaction=*/true);
                          },
                          &writes_done_ops_, /*can_inline=*/false);
     writes_done_ops_.set_core_cq_tag(&writes_done_tag_);
     callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
-    if (started_) {
-      call_.PerformOps(&writes_done_ops_);
-    } else {
-      writes_done_ops_at_start_ = true;
+
+    if (GPR_UNLIKELY(corked_write_needed_)) {
+      writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                           context_->initial_metadata_flags());
+      corked_write_needed_ = false;
+    }
+
+    if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+      grpc::internal::MutexLock lock(&start_mu_);
+      if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+        backlog_.writes_done_ops = true;
+        return;
+      }
     }
+    call_.PerformOps(&writes_done_ops_);
   }
 
   void AddHold(int holds) override {
     callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
   }
-  void RemoveHold() override { MaybeFinish(); }
+  void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
 
  private:
   friend class ClientCallbackWriterFactory<Request>;
@@ -909,10 +976,55 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter<Request> {
       : context_(context),
         call_(call),
         reactor_(reactor),
-        start_corked_(context_->initial_metadata_corked_) {
+        start_corked_(context_->initial_metadata_corked_),
+        corked_write_needed_(start_corked_) {
     this->BindReactor(reactor);
+
+    // Set up the unchanging parts of the start and write tags and ops.
+    start_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnReadInitialMetadataDone(ok);
+                     MaybeFinish(/*from_reaction=*/true);
+                   },
+                   &start_ops_, /*can_inline=*/false);
+    start_ops_.RecvInitialMetadata(context_);
+    start_ops_.set_core_cq_tag(&start_tag_);
+
+    write_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnWriteDone(ok);
+                     MaybeFinish(/*from_reaction=*/true);
+                   },
+                   &write_ops_, /*can_inline=*/false);
+    write_ops_.set_core_cq_tag(&write_tag_);
+
+    // Also set up the Finish tag and op set.
     finish_ops_.RecvMessage(response);
     finish_ops_.AllowNoMessage();
+    finish_tag_.Set(
+        call_.call(),
+        [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
+        &finish_ops_,
+        /*can_inline=*/false);
+    finish_ops_.ClientRecvStatus(context_, &finish_status_);
+    finish_ops_.set_core_cq_tag(&finish_tag_);
+  }
+
+  // MaybeFinish behaves as in ClientCallbackReaderWriterImpl.
+  void MaybeFinish(bool from_reaction) {
+    if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
+                         1, std::memory_order_acq_rel) == 1)) {
+      ::grpc::Status s = std::move(finish_status_);
+      auto* reactor = reactor_;
+      auto* call = call_.call();
+      this->~ClientCallbackWriterImpl();
+      ::grpc::g_core_codegen_interface->grpc_call_unref(call);
+      if (GPR_LIKELY(from_reaction)) {
+        reactor->OnDone(s);
+      } else {
+        reactor->InternalScheduleOnDone(std::move(s));
+      }
+    }
   }
 
   ::grpc_impl::ClientContext* const context_;
@@ -923,7 +1035,9 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter<Request> {
                             grpc::internal::CallOpRecvInitialMetadata>
       start_ops_;
   grpc::internal::CallbackWithSuccessTag start_tag_;
-  bool start_corked_;
+  const bool start_corked_;
+  bool corked_write_needed_;  // no lock needed since only accessed in
+                              // Write/WritesDone which cannot be concurrent
 
   grpc::internal::CallOpSet<grpc::internal::CallOpGenericRecvMessage,
                             grpc::internal::CallOpClientRecvStatus>
@@ -936,17 +1050,22 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter<Request> {
                             grpc::internal::CallOpClientSendClose>
       write_ops_;
   grpc::internal::CallbackWithSuccessTag write_tag_;
-  bool write_ops_at_start_{false};
 
   grpc::internal::CallOpSet<grpc::internal::CallOpSendInitialMetadata,
                             grpc::internal::CallOpClientSendClose>
       writes_done_ops_;
   grpc::internal::CallbackWithSuccessTag writes_done_tag_;
-  bool writes_done_ops_at_start_{false};
 
-  // Minimum of 2 callbacks to pre-register for start and finish
-  std::atomic<intptr_t> callbacks_outstanding_{2};
-  bool started_{false};
+  struct StartCallBacklog {
+    bool write_ops = false;
+    bool writes_done_ops = false;
+  };
+  StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */;
+
+  // Minimum of 3 callbacks to pre-register for start ops, StartCall, and finish
+  std::atomic<intptr_t> callbacks_outstanding_{3};
+  std::atomic_bool started_{false};
+  grpc::internal::Mutex start_mu_;
 };
 
 template <class Request>
@@ -985,7 +1104,6 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
     // This call initiates two batches, each with a callback
     // 1. Send initial metadata + write + writes done + recv initial metadata
     // 2. Read message, recv trailing metadata
-    started_ = true;
 
     start_tag_.Set(call_.call(),
                    [this](bool ok) {
@@ -1000,24 +1118,13 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
     call_.PerformOps(&start_ops_);
 
     finish_tag_.Set(call_.call(), [this](bool /*ok*/) { MaybeFinish(); },
-                    &finish_ops_, /*can_inline=*/false);
+                    &finish_ops_,
+                    /*can_inline=*/false);
     finish_ops_.ClientRecvStatus(context_, &finish_status_);
     finish_ops_.set_core_cq_tag(&finish_tag_);
     call_.PerformOps(&finish_ops_);
   }
 
-  void MaybeFinish() {
-    if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
-                         1, std::memory_order_acq_rel) == 1)) {
-      ::grpc::Status s = std::move(finish_status_);
-      auto* reactor = reactor_;
-      auto* call = call_.call();
-      this->~ClientCallbackUnaryImpl();
-      ::grpc::g_core_codegen_interface->grpc_call_unref(call);
-      reactor->OnDone(s);
-    }
-  }
-
  private:
   friend class ClientCallbackUnaryFactory;
 
@@ -1034,6 +1141,21 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
     finish_ops_.AllowNoMessage();
   }
 
+  // In the unary case, MaybeFinish is only ever invoked from a
+  // library-initiated reaction, so it will just directly call OnDone if this is
+  // the last reaction for this RPC.
+  void MaybeFinish() {
+    if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
+                         1, std::memory_order_acq_rel) == 1)) {
+      ::grpc::Status s = std::move(finish_status_);
+      auto* reactor = reactor_;
+      auto* call = call_.call();
+      this->~ClientCallbackUnaryImpl();
+      ::grpc::g_core_codegen_interface->grpc_call_unref(call);
+      reactor->OnDone(s);
+    }
+  }
+
   ::grpc_impl::ClientContext* const context_;
   grpc::internal::Call call_;
   ClientUnaryReactor* const reactor_;
@@ -1053,7 +1175,6 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
 
   // This call will have 2 callbacks: start and finish
   std::atomic<intptr_t> callbacks_outstanding_{2};
-  bool started_{false};
 };
 
 class ClientCallbackUnaryFactory {

+ 14 - 4
include/grpcpp/impl/codegen/server_context_impl.h

@@ -174,6 +174,14 @@ class ServerContextBase {
   /// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
   void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
 
+  /// Return whether this RPC failed before the server could provide its status
+  /// back to the client. This could be because of explicit API cancellation
+  /// from the client-side or server-side, because of deadline exceeded, network
+  /// connection reset, HTTP/2 parameter configuration (e.g., max message size,
+  /// max connection age), etc. It does NOT include failure due to a non-OK
+  /// status return from the server application's request handler, including
+  /// Status::CANCELLED.
+  ///
   /// IsCancelled is always safe to call when using sync or callback API.
   /// When using async API, it is only safe to call IsCancelled after
   /// the AsyncNotifyWhenDone tag has been delivered. Thread-safe.
@@ -181,10 +189,9 @@ class ServerContextBase {
 
   /// Cancel the Call from the server. This is a best-effort API and
   /// depending on when it is called, the RPC may still appear successful to
-  /// the client.
-  /// For example, if TryCancel() is called on a separate thread, it might race
-  /// with the server handler which might return success to the client before
-  /// TryCancel() was even started by the thread.
+  /// the client. For example, if TryCancel() is called on a separate thread, it
+  /// might race with the server handler which might return success to the
+  /// client before TryCancel() was even started by the thread.
   ///
   /// It is the caller's responsibility to prevent such races and ensure that if
   /// TryCancel() is called, the serverhandler must return Status::CANCELLED.
@@ -192,6 +199,9 @@ class ServerContextBase {
   /// error status code, it is ok to not return Status::CANCELLED even if
   /// TryCancel() was called.
   ///
+  /// For reasons such as the above, it is generally preferred to explicitly
+  /// finish an RPC by returning Status::CANCELLED rather than using TryCancel.
+  ///
   /// Note that TryCancel() does not change any of the tags that are pending
   /// on the completion queue. All pending tags will still be delivered
   /// (though their ok result may reflect the effect of cancellation).

+ 2 - 2
include/grpcpp/opencensus.h

@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2018 gRPC authors.
+ * Copyright 2019 gRPC authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
 
 namespace grpc_impl {
 class ServerContext;
-}
+}  // namespace grpc_impl
 
 namespace grpc {
 // These symbols in this file will not be included in the binary unless

+ 42 - 3
include/grpcpp/resource_quota.h

@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2019 gRPC authors.
+ * 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.
@@ -19,11 +19,50 @@
 #ifndef GRPCPP_RESOURCE_QUOTA_H
 #define GRPCPP_RESOURCE_QUOTA_H
 
-#include <grpcpp/resource_quota_impl.h>
+struct grpc_resource_quota;
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
 
 namespace grpc {
 
-typedef ::grpc_impl::ResourceQuota ResourceQuota;
+/// ResourceQuota represents a bound on memory and thread usage by the gRPC
+/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder),
+/// or a client channel (via \a ChannelArguments).
+/// gRPC will attempt to keep memory and threads used by all attached entities
+/// below the ResourceQuota bound.
+class ResourceQuota final : private ::grpc::GrpcLibraryCodegen {
+ public:
+  /// \param name - a unique name for this ResourceQuota.
+  explicit ResourceQuota(const grpc::string& name);
+  ResourceQuota();
+  ~ResourceQuota();
+
+  /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller
+  /// than the current size of the pool, memory usage will be monotonically
+  /// decreased until it falls under \a new_size.
+  /// No time bound is given for this to occur however.
+  ResourceQuota& Resize(size_t new_size);
+
+  /// Set the max number of threads that can be allocated from this
+  /// ResourceQuota object.
+  ///
+  /// If the new_max_threads value is smaller than the current value, no new
+  /// threads are allocated until the number of active threads fall below
+  /// new_max_threads. There is no time bound on when this may happen i.e none
+  /// of the current threads are forcefully destroyed and all threads run their
+  /// normal course.
+  ResourceQuota& SetMaxThreads(int new_max_threads);
+
+  grpc_resource_quota* c_resource_quota() const { return impl_; }
+
+ private:
+  ResourceQuota(const ResourceQuota& rhs);
+  ResourceQuota& operator=(const ResourceQuota& rhs);
+
+  grpc_resource_quota* const impl_;
+};
+
 }  // namespace grpc
 
 #endif  // GRPCPP_RESOURCE_QUOTA_H

+ 2 - 3
include/grpcpp/server_builder_impl.h

@@ -41,7 +41,6 @@ struct grpc_resource_quota;
 namespace grpc_impl {
 
 class CompletionQueue;
-class ResourceQuota;
 class Server;
 class ServerCompletionQueue;
 class ServerCredentials;
@@ -50,6 +49,7 @@ class ServerCredentials;
 namespace grpc {
 
 class AsyncGenericService;
+class ResourceQuota;
 class Service;
 namespace testing {
 class ServerBuilderPluginTest;
@@ -228,8 +228,7 @@ class ServerBuilder {
       grpc_compression_algorithm algorithm);
 
   /// Set the attached buffer pool for this server
-  ServerBuilder& SetResourceQuota(
-      const grpc_impl::ResourceQuota& resource_quota);
+  ServerBuilder& SetResourceQuota(const grpc::ResourceQuota& resource_quota);
 
   ServerBuilder& SetOption(std::unique_ptr<grpc::ServerBuilderOption> option);
 

+ 147 - 4
package.xml

@@ -13,8 +13,8 @@
  <date>2019-09-24</date>
  <time>16:06:07</time>
  <version>
-  <release>1.30.0dev</release>
-  <api>1.30.0dev</api>
+  <release>1.31.0dev</release>
+  <api>1.31.0dev</api>
  </version>
  <stability>
   <release>beta</release>
@@ -22,7 +22,7 @@
  </stability>
  <license>Apache 2.0</license>
  <notes>
-- gRPC Core 1.30.0 update
+- gRPC Core 1.31.0 update
  </notes>
  <contents>
   <dir baseinstalldir="/" name="/">
@@ -97,6 +97,8 @@
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_factory.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_plugin.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/config_selector.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/config_selector.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/connector.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/global_subchannel_pool.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/global_subchannel_pool.h" role="src" />
@@ -179,6 +181,7 @@
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_call_data.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_parser.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_parser.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.cc" role="src" />
@@ -282,130 +285,256 @@
     <file baseinstalldir="/" name="src/core/ext/transport/inproc/inproc_transport.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/deprecation.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/resource.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/resource.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/annotations/resource.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/cert.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/common.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/secret.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/auth/tls.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cds.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cds.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cds.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/address.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/backoff.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/base.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/config_source.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/health_check.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/protocol.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/discovery.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/eds.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/eds.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/eds.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/lds.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/lds.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/lds.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/listener.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/rds.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/rds.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/rds.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route/route.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/route/route_components.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/scoped_route.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/srds.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/srds.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/api/v2/srds.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/http.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/http.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/http.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/http.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/matcher/regex.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/matcher/string.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/matcher/string.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/matcher/string.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/percent.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/percent.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/percent.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/percent.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/range.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/range.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/range.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/range.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/semantic_version.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/semantic_version.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/semantic_version.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/gogoproto/gogo.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/gogoproto/gogo.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/gogoproto/gogo.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/gogoproto/gogo.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/api/annotations.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/api/annotations.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/api/annotations.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/api/annotations.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/api/http.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/api/http.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/api/http.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/api/http.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/any.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/any.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/any.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/any.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/descriptor.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/descriptor.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/descriptor.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/duration.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/duration.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/duration.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/duration.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/empty.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/empty.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/empty.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/empty.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/struct.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/struct.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/struct.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/struct.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/timestamp.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/timestamp.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/timestamp.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/wrappers.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/wrappers.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/protobuf/wrappers.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/rpc/status.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/google/rpc/status.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/rpc/status.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/google/rpc/status.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c" role="src" />
@@ -418,14 +547,22 @@
     <file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/migrate.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/migrate.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/migrate.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/sensitive.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/sensitive.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/sensitive.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/status.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/status.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/status.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/annotations/status.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upb.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upbdefs.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/upb-generated/validate/validate.upbdefs.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/avl/avl.cc" role="src" />
     <file baseinstalldir="/" name="src/core/lib/avl/avl.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/backoff/backoff.cc" role="src" />
@@ -1579,18 +1716,24 @@
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/third_party/fiat/p256_64.h" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/decode.c" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/decode.h" role="src" />
+    <file baseinstalldir="/" name="third_party/upb/upb/def.c" role="src" />
+    <file baseinstalldir="/" name="third_party/upb/upb/def.h" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/encode.c" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/encode.h" role="src" />
-    <file baseinstalldir="/" name="third_party/upb/upb/generated_util.h" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/msg.c" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/msg.h" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/port.c" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/port_def.inc" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/port_undef.inc" role="src" />
+    <file baseinstalldir="/" name="third_party/upb/upb/reflection.c" role="src" />
+    <file baseinstalldir="/" name="third_party/upb/upb/reflection.h" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/table.c" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/table.int.h" role="src" />
+    <file baseinstalldir="/" name="third_party/upb/upb/text_encode.c" role="src" />
+    <file baseinstalldir="/" name="third_party/upb/upb/text_encode.h" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/upb.c" role="src" />
     <file baseinstalldir="/" name="third_party/upb/upb/upb.h" role="src" />
+    <file baseinstalldir="/" name="third_party/upb/upb/upb.hpp" role="src" />
     <file baseinstalldir="/" name="third_party/zlib/adler32.c" role="src" />
     <file baseinstalldir="/" name="third_party/zlib/compress.c" role="src" />
     <file baseinstalldir="/" name="third_party/zlib/crc32.c" role="src" />

+ 2 - 2
requirements.bazel.txt

@@ -2,11 +2,11 @@
 coverage>=4.0
 cython>=0.29.8
 enum34>=1.0.4
-protobuf>=3.5.0.post1
+protobuf>=3.5.0.post1, < 4.0dev
 six>=1.10
 wheel>=0.29
 futures>=2.2.0
-google-auth>=1.0.0
+google-auth>=1.17.2
 oauth2client==4.1.0
 requests>=2.14.2
 urllib3>=1.23

+ 1 - 1
requirements.txt

@@ -2,6 +2,6 @@
 coverage>=4.0
 cython>=0.29.8
 enum34>=1.0.4
-protobuf>=3.5.0.post1
+protobuf>=3.5.0.post1, < 4.0dev
 six>=1.10
 wheel>=0.29

+ 5 - 0
setup.py

@@ -355,6 +355,9 @@ INSTALL_REQUIRES = (
     "futures>=2.2.0; python_version<'3.2'",
     "enum34>=1.0.4; python_version<'3.4'",
 )
+EXTRAS_REQUIRES = {
+    'protobuf': 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),
+}
 
 SETUP_REQUIRES = INSTALL_REQUIRES + (
     'Sphinx~=1.8.1',
@@ -380,6 +383,7 @@ COMMAND_CLASS = {
     'build_py': commands.BuildPy,
     'build_ext': commands.BuildExt,
     'gather': commands.Gather,
+    'clean': commands.Clean,
 }
 
 # Ensure that package data is copied over before any commands have been run:
@@ -417,6 +421,7 @@ setuptools.setup(
     package_dir=PACKAGE_DIRECTORIES,
     package_data=PACKAGE_DATA,
     install_requires=INSTALL_REQUIRES,
+    extras_require=EXTRAS_REQUIRES,
     setup_requires=SETUP_REQUIRES,
     cmdclass=COMMAND_CLASS,
 )

+ 5 - 2
src/abseil-cpp/preprocessed_builds.yaml.gen.py

@@ -69,8 +69,11 @@ def parse_bazel_rule(elem, package):
 
 def read_bazel_build(package):
   """Runs bazel query on given package file and returns all cc rules."""
+  # Use a wrapper version of bazel in gRPC not to use system-wide bazel
+  # to avoid bazel conflict when running on Kokoro.
+  BAZEL_BIN = "../../tools/bazel"
   result = subprocess.check_output(
-      ["bazel", "query", package + ":all", "--output", "xml"])
+      [BAZEL_BIN, "query", package + ":all", "--output", "xml"])
   root = ET.fromstring(result)
   return [
       parse_bazel_rule(elem, package)
@@ -203,7 +206,7 @@ def main():
   builds = generate_builds("absl")
   os.chdir(previous_dir)
   with open(OUTPUT_PATH, 'w') as outfile:
-    outfile.write(yaml.dump(builds, indent=2, sort_keys=True))
+    outfile.write(yaml.dump(builds, indent=2))
 
 
 if __name__ == "__main__":

+ 3 - 2
src/compiler/objective_c_plugin.cc

@@ -52,15 +52,16 @@ inline ::grpc::string ImportProtoHeaders(
 
   ::grpc::string base_name = header;
   grpc_generator::StripPrefix(&base_name, "google/protobuf/");
+  ::grpc::string file_name = "GPB" + base_name;
   // create the import code snippet
   ::grpc::string framework_header =
-      ::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name;
+      ::grpc::string(ProtobufLibraryFrameworkName) + "/" + file_name;
 
   static const ::grpc::string kFrameworkImportsCondition =
       "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS";
   return PreprocIfElse(kFrameworkImportsCondition,
                        indent + SystemImport(framework_header),
-                       indent + LocalImport(header));
+                       indent + LocalImport(file_name));
 }
 
 }  // namespace

+ 3 - 2
src/compiler/python_generator.cc

@@ -627,6 +627,7 @@ bool PrivateGenerator::PrintServiceClass(
         out->Print("options=(),\n");
         out->Print("channel_credentials=None,\n");
         out->Print("call_credentials=None,\n");
+        out->Print("insecure=False,\n");
         out->Print("compression=None,\n");
         out->Print("wait_for_ready=None,\n");
         out->Print("timeout=None,\n");
@@ -654,8 +655,8 @@ bool PrivateGenerator::PrintServiceClass(
           out->Print(serializer_dict, "$ResponseModuleAndClass$.FromString,\n");
           out->Print("options, channel_credentials,\n");
           out->Print(
-              "call_credentials, compression, wait_for_ready, timeout, "
-              "metadata)\n");
+              "insecure, call_credentials, compression, wait_for_ready, "
+              "timeout, metadata)\n");
         }
       }
     }

+ 12 - 9
src/core/ext/filters/client_channel/backend_metric.cc

@@ -21,6 +21,7 @@
 #include "absl/strings/string_view.h"
 
 #include "udpa/data/orca/v1/orca_load_report.upb.h"
+#include "upb/upb.hpp"
 
 #include "src/core/lib/gprpp/map.h"
 
@@ -31,17 +32,19 @@ namespace {
 template <typename EntryType>
 std::map<absl::string_view, double, StringLess> ParseMap(
     udpa_data_orca_v1_OrcaLoadReport* msg,
-    EntryType** (*entry_func)(udpa_data_orca_v1_OrcaLoadReport*, size_t*),
+    const EntryType* (*entry_func)(const udpa_data_orca_v1_OrcaLoadReport*,
+                                   size_t*),
     upb_strview (*key_func)(const EntryType*),
     double (*value_func)(const EntryType*), Arena* arena) {
   std::map<absl::string_view, double, StringLess> result;
-  size_t size;
-  const auto* const* entries = entry_func(msg, &size);
-  for (size_t i = 0; i < size; ++i) {
-    upb_strview key_view = key_func(entries[i]);
-    char* key = static_cast<char*>(arena->Alloc(key_view.size + 1));
+  size_t i = UPB_MAP_BEGIN;
+  while (true) {
+    const auto* entry = entry_func(msg, &i);
+    if (entry == nullptr) break;
+    upb_strview key_view = key_func(entry);
+    char* key = static_cast<char*>(arena->Alloc(key_view.size));
     memcpy(key, key_view.data, key_view.size);
-    result[absl::string_view(key, key_view.size)] = value_func(entries[i]);
+    result[absl::string_view(key, key_view.size)] = value_func(entry);
   }
   return result;
 }
@@ -67,12 +70,12 @@ const LoadBalancingPolicy::BackendMetricData* ParseBackendMetricData(
       udpa_data_orca_v1_OrcaLoadReport_rps(msg);
   backend_metric_data->request_cost =
       ParseMap<udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry>(
-          msg, udpa_data_orca_v1_OrcaLoadReport_mutable_request_cost,
+          msg, udpa_data_orca_v1_OrcaLoadReport_request_cost_next,
           udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_key,
           udpa_data_orca_v1_OrcaLoadReport_RequestCostEntry_value, arena);
   backend_metric_data->utilization =
       ParseMap<udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry>(
-          msg, udpa_data_orca_v1_OrcaLoadReport_mutable_utilization,
+          msg, udpa_data_orca_v1_OrcaLoadReport_utilization_next,
           udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_key,
           udpa_data_orca_v1_OrcaLoadReport_UtilizationEntry_value, arena);
   return backend_metric_data;

+ 350 - 238
src/core/ext/filters/client_channel/client_channel.cc

@@ -40,6 +40,7 @@
 
 #include "src/core/ext/filters/client_channel/backend_metric.h"
 #include "src/core/ext/filters/client_channel/backup_poller.h"
+#include "src/core/ext/filters/client_channel/config_selector.h"
 #include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
 #include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
@@ -149,12 +150,16 @@ class ChannelData {
   bool received_service_config_data() const {
     return received_service_config_data_;
   }
+  grpc_error* resolver_transient_failure_error() const {
+    return resolver_transient_failure_error_;
+  }
   RefCountedPtr<ServerRetryThrottleData> retry_throttle_data() const {
     return retry_throttle_data_;
   }
   RefCountedPtr<ServiceConfig> service_config() const {
     return service_config_;
   }
+  ConfigSelector* config_selector() const { return config_selector_.get(); }
   WorkSerializer* work_serializer() const { return work_serializer_.get(); }
 
   RefCountedPtr<ConnectedSubchannel> GetConnectedSubchannelInDataPlane(
@@ -234,6 +239,29 @@ class ChannelData {
     Atomic<bool> done_{false};
   };
 
+  class ChannelConfigHelper
+      : public ResolvingLoadBalancingPolicy::ChannelConfigHelper {
+   public:
+    explicit ChannelConfigHelper(ChannelData* chand) : chand_(chand) {}
+
+    ApplyServiceConfigResult ApplyServiceConfig(
+        const Resolver::Result& result) override;
+
+    void ApplyConfigSelector(
+        bool service_config_changed,
+        RefCountedPtr<ConfigSelector> config_selector) override;
+
+    void ResolverTransientFailure(grpc_error* error) override;
+
+   private:
+    static void ProcessLbPolicy(
+        const Resolver::Result& resolver_result,
+        const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
+        RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config);
+
+    ChannelData* chand_;
+  };
+
   ChannelData(grpc_channel_element_args* args, grpc_error** error);
   ~ChannelData();
 
@@ -241,30 +269,20 @@ class ChannelData {
       grpc_connectivity_state state, const char* reason,
       std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker);
 
-  void UpdateServiceConfigLocked(
-      RefCountedPtr<ServerRetryThrottleData> retry_throttle_data,
-      RefCountedPtr<ServiceConfig> service_config);
+  void UpdateServiceConfigInDataPlaneLocked(
+      bool service_config_changed,
+      RefCountedPtr<ConfigSelector> config_selector);
 
   void CreateResolvingLoadBalancingPolicyLocked();
 
   void DestroyResolvingLoadBalancingPolicyLocked();
 
-  static bool ProcessResolverResultLocked(
-      void* arg, const Resolver::Result& result,
-      RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config,
-      grpc_error** service_config_error, bool* no_valid_service_config);
-
   grpc_error* DoPingLocked(grpc_transport_op* op);
 
   void StartTransportOpLocked(grpc_transport_op* op);
 
   void TryToConnectLocked();
 
-  void ProcessLbPolicy(
-      const Resolver::Result& resolver_result,
-      const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
-      RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config);
-
   //
   // Fields set at construction and never modified.
   //
@@ -278,6 +296,7 @@ class ChannelData {
   grpc_core::UniquePtr<char> server_name_;
   grpc_core::UniquePtr<char> target_uri_;
   channelz::ChannelNode* channelz_node_;
+  ChannelConfigHelper channel_config_helper_;
 
   //
   // Fields used in the data plane.  Guarded by data_plane_mu.
@@ -286,9 +305,11 @@ class ChannelData {
   std::unique_ptr<LoadBalancingPolicy::SubchannelPicker> picker_;
   QueuedPick* queued_picks_ = nullptr;  // Linked list of queued picks.
   // Data from service config.
+  grpc_error* resolver_transient_failure_error_ = GRPC_ERROR_NONE;
   bool received_service_config_data_ = false;
   RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_;
   RefCountedPtr<ServiceConfig> service_config_;
+  RefCountedPtr<ConfigSelector> config_selector_;
 
   //
   // Fields used in the control plane.  Guarded by work_serializer.
@@ -300,6 +321,7 @@ class ChannelData {
   ConnectivityStateTracker state_tracker_;
   grpc_core::UniquePtr<char> health_check_service_name_;
   RefCountedPtr<ServiceConfig> saved_service_config_;
+  RefCountedPtr<ConfigSelector> saved_config_selector_;
   bool received_first_resolver_result_ = false;
   // The number of SubchannelWrapper instances referencing a given Subchannel.
   std::map<Subchannel*, int> subchannel_refcount_map_;
@@ -352,9 +374,6 @@ class CallData {
 
   RefCountedPtr<SubchannelCall> subchannel_call() { return subchannel_call_; }
 
-  // Invoked by channel for queued picks once resolver results are available.
-  void MaybeApplyServiceConfigToCallLocked(grpc_call_element* elem);
-
   // Invoked by channel for queued picks when the picker is updated.
   static void PickSubchannel(void* arg, grpc_error* error);
 
@@ -742,13 +761,17 @@ class CallData {
   void CreateSubchannelCall(grpc_call_element* elem);
   // Invoked when a pick is completed, on both success or failure.
   static void PickDone(void* arg, grpc_error* error);
-  // Removes the call from the channel's list of queued picks.
-  void RemoveCallFromQueuedPicksLocked(grpc_call_element* elem);
-  // Adds the call to the channel's list of queued picks.
-  void AddCallToQueuedPicksLocked(grpc_call_element* elem);
+  // Removes the call from the channel's list of queued picks if present.
+  void MaybeRemoveCallFromQueuedPicksLocked(grpc_call_element* elem);
+  // Adds the call to the channel's list of queued picks if not already present.
+  void MaybeAddCallToQueuedPicksLocked(grpc_call_element* elem);
   // Applies service config to the call.  Must be invoked once we know
   // that the resolver has returned results to the channel.
-  void ApplyServiceConfigToCallLocked(grpc_call_element* elem);
+  // If an error is returned, the error indicates the status with which
+  // the call should be failed.
+  grpc_error* ApplyServiceConfigToCallLocked(
+      grpc_call_element* elem, grpc_metadata_batch* initial_metadata);
+  void MaybeInvokeConfigSelectorCommitCallback();
 
   // State for handling deadlines.
   // The code in deadline_filter.c requires this to be the first field.
@@ -769,6 +792,7 @@ class CallData {
   RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_;
   const ClientChannelMethodParsedConfig* method_params_ = nullptr;
   std::map<const char*, absl::string_view> call_attributes_;
+  std::function<void()> on_call_committed_;
 
   RefCountedPtr<SubchannelCall> subchannel_call_;
 
@@ -1335,6 +1359,180 @@ class ChannelData::ClientChannelControlHelper
   ChannelData* chand_;
 };
 
+//
+// ChannelData::ChannelConfigHelper
+//
+
+// Synchronous callback from ResolvingLoadBalancingPolicy to process a
+// resolver result update.
+ChannelData::ChannelConfigHelper::ApplyServiceConfigResult
+ChannelData::ChannelConfigHelper::ApplyServiceConfig(
+    const Resolver::Result& result) {
+  ApplyServiceConfigResult service_config_result;
+  RefCountedPtr<ServiceConfig> service_config;
+  // If resolver did not return a service config or returned an invalid service
+  // config, we need a fallback service config.
+  if (result.service_config_error != GRPC_ERROR_NONE) {
+    // If the service config was invalid, then fallback to the saved service
+    // config. If there is no saved config either, use the default service
+    // config.
+    if (chand_->saved_service_config_ != nullptr) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+        gpr_log(GPR_INFO,
+                "chand=%p: resolver returned invalid service config. "
+                "Continuing to use previous service config.",
+                chand_);
+      }
+      service_config = chand_->saved_service_config_;
+    } else if (chand_->default_service_config_ != nullptr) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+        gpr_log(GPR_INFO,
+                "chand=%p: resolver returned invalid service config. Using "
+                "default service config provided by client API.",
+                chand_);
+      }
+      service_config = chand_->default_service_config_;
+    }
+  } else if (result.service_config == nullptr) {
+    if (chand_->default_service_config_ != nullptr) {
+      if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+        gpr_log(GPR_INFO,
+                "chand=%p: resolver returned no service config. Using default "
+                "service config provided by client API.",
+                chand_);
+      }
+      service_config = chand_->default_service_config_;
+    }
+  } else {
+    service_config = result.service_config;
+  }
+  service_config_result.service_config_error =
+      GRPC_ERROR_REF(result.service_config_error);
+  if (service_config == nullptr &&
+      result.service_config_error != GRPC_ERROR_NONE) {
+    service_config_result.no_valid_service_config = true;
+    return service_config_result;
+  }
+  // Process service config.
+  grpc_core::UniquePtr<char> service_config_json;
+  const internal::ClientChannelGlobalParsedConfig* parsed_service_config =
+      nullptr;
+  if (service_config != nullptr) {
+    parsed_service_config =
+        static_cast<const internal::ClientChannelGlobalParsedConfig*>(
+            service_config->GetGlobalParsedConfig(
+                internal::ClientChannelServiceConfigParser::ParserIndex()));
+  }
+  // Check if the config has changed.
+  service_config_result.service_config_changed =
+      ((service_config == nullptr) !=
+       (chand_->saved_service_config_ == nullptr)) ||
+      (service_config != nullptr &&
+       service_config->json_string() !=
+           chand_->saved_service_config_->json_string());
+  if (service_config_result.service_config_changed) {
+    service_config_json.reset(gpr_strdup(
+        service_config != nullptr ? service_config->json_string().c_str()
+                                  : ""));
+    if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+      gpr_log(GPR_INFO,
+              "chand=%p: resolver returned updated service config: \"%s\"",
+              chand_, service_config_json.get());
+    }
+    // Save health check service name.
+    if (service_config != nullptr) {
+      chand_->health_check_service_name_.reset(
+          gpr_strdup(parsed_service_config->health_check_service_name()));
+    } else {
+      chand_->health_check_service_name_.reset();
+    }
+    // Update health check service name used by existing subchannel wrappers.
+    for (auto* subchannel_wrapper : chand_->subchannel_wrappers_) {
+      subchannel_wrapper->UpdateHealthCheckServiceName(
+          grpc_core::UniquePtr<char>(
+              gpr_strdup(chand_->health_check_service_name_.get())));
+    }
+    // Save service config.
+    chand_->saved_service_config_ = std::move(service_config);
+  }
+  // Find LB policy config.
+  ProcessLbPolicy(result, parsed_service_config,
+                  &service_config_result.lb_policy_config);
+  grpc_core::UniquePtr<char> lb_policy_name(
+      gpr_strdup((service_config_result.lb_policy_config)->name()));
+  // Swap out the data used by GetChannelInfo().
+  {
+    MutexLock lock(&chand_->info_mu_);
+    chand_->info_lb_policy_name_ = std::move(lb_policy_name);
+    if (service_config_json != nullptr) {
+      chand_->info_service_config_json_ = std::move(service_config_json);
+    }
+  }
+  // Return results.
+  return service_config_result;
+}
+
+void ChannelData::ChannelConfigHelper::ApplyConfigSelector(
+    bool service_config_changed,
+    RefCountedPtr<ConfigSelector> config_selector) {
+  chand_->UpdateServiceConfigInDataPlaneLocked(service_config_changed,
+                                               std::move(config_selector));
+}
+
+void ChannelData::ChannelConfigHelper::ResolverTransientFailure(
+    grpc_error* error) {
+  MutexLock lock(&chand_->data_plane_mu_);
+  GRPC_ERROR_UNREF(chand_->resolver_transient_failure_error_);
+  chand_->resolver_transient_failure_error_ = error;
+}
+
+void ChannelData::ChannelConfigHelper::ProcessLbPolicy(
+    const Resolver::Result& resolver_result,
+    const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
+    RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config) {
+  // Prefer the LB policy config found in the service config.
+  if (parsed_service_config != nullptr &&
+      parsed_service_config->parsed_lb_config() != nullptr) {
+    *lb_policy_config = parsed_service_config->parsed_lb_config();
+    return;
+  }
+  // Try the deprecated LB policy name from the service config.
+  // If not, try the setting from channel args.
+  const char* policy_name = nullptr;
+  if (parsed_service_config != nullptr &&
+      !parsed_service_config->parsed_deprecated_lb_policy().empty()) {
+    policy_name = parsed_service_config->parsed_deprecated_lb_policy().c_str();
+  } else {
+    const grpc_arg* channel_arg =
+        grpc_channel_args_find(resolver_result.args, GRPC_ARG_LB_POLICY_NAME);
+    policy_name = grpc_channel_arg_get_string(channel_arg);
+  }
+  // Use pick_first if nothing was specified and we didn't select grpclb
+  // above.
+  if (policy_name == nullptr) policy_name = "pick_first";
+  // Now that we have the policy name, construct an empty config for it.
+  Json config_json = Json::Array{Json::Object{
+      {policy_name, Json::Object{}},
+  }};
+  grpc_error* parse_error = GRPC_ERROR_NONE;
+  *lb_policy_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
+      config_json, &parse_error);
+  // The policy name came from one of three places:
+  // - The deprecated loadBalancingPolicy field in the service config,
+  //   in which case the code in ClientChannelServiceConfigParser
+  //   already verified that the policy does not require a config.
+  // - One of the hard-coded values here, all of which are known to not
+  //   require a config.
+  // - A channel arg, in which case the application did something that
+  //   is a misuse of our API.
+  // In the first two cases, these assertions will always be true.  In
+  // the last case, this is probably fine for now.
+  // TODO(roth): If the last case becomes a problem, add better error
+  // handling here.
+  GPR_ASSERT(*lb_policy_config != nullptr);
+  GPR_ASSERT(parse_error == GRPC_ERROR_NONE);
+}
+
 //
 // ChannelData implementation
 //
@@ -1393,6 +1591,7 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error)
       client_channel_factory_(
           ClientChannelFactory::GetFromChannelArgs(args->channel_args)),
       channelz_node_(GetChannelzNode(args->channel_args)),
+      channel_config_helper_(this),
       work_serializer_(std::make_shared<WorkSerializer>()),
       interested_parties_(grpc_pollset_set_create()),
       subchannel_pool_(GetSubchannelPool(args->channel_args)),
@@ -1461,6 +1660,7 @@ ChannelData::~ChannelData() {
   }
   DestroyResolvingLoadBalancingPolicyLocked();
   grpc_channel_args_destroy(channel_args_);
+  GRPC_ERROR_UNREF(resolver_transient_failure_error_);
   // Stop backup polling.
   grpc_client_channel_stop_backup_polling(interested_parties_);
   grpc_pollset_set_destroy(interested_parties_);
@@ -1475,6 +1675,7 @@ void ChannelData::UpdateStateAndPickerLocked(
   if (picker_ == nullptr) {
     health_check_service_name_.reset();
     saved_service_config_.reset();
+    saved_config_selector_.reset();
     received_first_resolver_result_ = false;
   }
   // Update connectivity state.
@@ -1497,9 +1698,11 @@ void ChannelData::UpdateStateAndPickerLocked(
   // - refs to subchannel wrappers in the keys of pending_subchannel_updates_
   // - ref stored in retry_throttle_data_
   // - ref stored in service_config_
+  // - ref stored in config_selector_
   // - ownership of the existing picker in picker_
   RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_to_unref;
   RefCountedPtr<ServiceConfig> service_config_to_unref;
+  RefCountedPtr<ConfigSelector> config_selector_to_unref;
   {
     MutexLock lock(&data_plane_mu_);
     // Handle subchannel updates.
@@ -1524,6 +1727,7 @@ void ChannelData::UpdateStateAndPickerLocked(
       // Note: We save the objects to unref until after the lock is released.
       retry_throttle_data_to_unref = std::move(retry_throttle_data_);
       service_config_to_unref = std::move(service_config_);
+      config_selector_to_unref = std::move(config_selector_);
     }
     // Re-process queued picks.
     for (QueuedPick* pick = queued_picks_; pick != nullptr; pick = pick->next) {
@@ -1540,24 +1744,72 @@ void ChannelData::UpdateStateAndPickerLocked(
   pending_subchannel_updates_.clear();
 }
 
-void ChannelData::UpdateServiceConfigLocked(
-    RefCountedPtr<ServerRetryThrottleData> retry_throttle_data,
-    RefCountedPtr<ServiceConfig> service_config) {
+void ChannelData::UpdateServiceConfigInDataPlaneLocked(
+    bool service_config_changed,
+    RefCountedPtr<ConfigSelector> config_selector) {
+  // Check if ConfigSelector has changed.
+  const bool config_selector_changed =
+      saved_config_selector_ != config_selector;
+  saved_config_selector_ = config_selector;
+  // We want to set the service config at least once, even if the
+  // resolver does not return a config, because that ensures that we
+  // disable retries if they are not enabled in the service config.
+  // TODO(roth): Consider removing the received_first_resolver_result_ check
+  // when we implement transparent retries.
+  if (!service_config_changed && !config_selector_changed &&
+      received_first_resolver_result_) {
+    return;
+  }
+  received_first_resolver_result_ = true;
+  // Get retry throttle data from service config.
+  RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
+  if (saved_service_config_ != nullptr) {
+    const internal::ClientChannelGlobalParsedConfig* parsed_service_config =
+        static_cast<const internal::ClientChannelGlobalParsedConfig*>(
+            saved_service_config_->GetGlobalParsedConfig(
+                internal::ClientChannelServiceConfigParser::ParserIndex()));
+    if (parsed_service_config != nullptr) {
+      absl::optional<internal::ClientChannelGlobalParsedConfig::RetryThrottling>
+          retry_throttle_config = parsed_service_config->retry_throttling();
+      if (retry_throttle_config.has_value()) {
+        retry_throttle_data =
+            internal::ServerRetryThrottleMap::GetDataForServer(
+                server_name_.get(),
+                retry_throttle_config.value().max_milli_tokens,
+                retry_throttle_config.value().milli_token_ratio);
+      }
+    }
+  }
+  // Create default config selector if not provided by resolver.
+  if (config_selector == nullptr) {
+    config_selector =
+        MakeRefCounted<DefaultConfigSelector>(saved_service_config_);
+  }
   // Grab data plane lock to update service config.
   //
   // We defer unreffing the old values (and deallocating memory) until
   // after releasing the lock to keep the critical section small.
+  RefCountedPtr<ServiceConfig> service_config_to_unref = saved_service_config_;
+  RefCountedPtr<ConfigSelector> config_selector_to_unref =
+      std::move(config_selector);
   {
     MutexLock lock(&data_plane_mu_);
+    GRPC_ERROR_UNREF(resolver_transient_failure_error_);
+    resolver_transient_failure_error_ = GRPC_ERROR_NONE;
     // Update service config.
     received_service_config_data_ = true;
     // Old values will be unreffed after lock is released.
     retry_throttle_data_.swap(retry_throttle_data);
-    service_config_.swap(service_config);
-    // Apply service config to queued picks.
+    service_config_.swap(service_config_to_unref);
+    config_selector_.swap(config_selector_to_unref);
+    // Re-process queued picks.
     for (QueuedPick* pick = queued_picks_; pick != nullptr; pick = pick->next) {
-      CallData* calld = static_cast<CallData*>(pick->elem->call_data);
-      calld->MaybeApplyServiceConfigToCallLocked(pick->elem);
+      grpc_call_element* elem = pick->elem;
+      CallData* calld = static_cast<CallData*>(elem->call_data);
+      grpc_error* error = GRPC_ERROR_NONE;
+      if (calld->PickSubchannelLocked(elem, &error)) {
+        calld->AsyncPickDone(elem, error);
+      }
     }
   }
   // Old values will be unreffed after lock is released when they go out
@@ -1574,7 +1826,7 @@ void ChannelData::CreateResolvingLoadBalancingPolicyLocked() {
   grpc_core::UniquePtr<char> target_uri(gpr_strdup(target_uri_.get()));
   resolving_lb_policy_.reset(new ResolvingLoadBalancingPolicy(
       std::move(lb_args), &grpc_client_channel_routing_trace,
-      std::move(target_uri), ProcessResolverResultLocked, this));
+      std::move(target_uri), &channel_config_helper_));
   grpc_pollset_set_add_pollset_set(resolving_lb_policy_->interested_parties(),
                                    interested_parties_);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
@@ -1591,180 +1843,6 @@ void ChannelData::DestroyResolvingLoadBalancingPolicyLocked() {
   }
 }
 
-void ChannelData::ProcessLbPolicy(
-    const Resolver::Result& resolver_result,
-    const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
-    RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config) {
-  // Prefer the LB policy config found in the service config.
-  if (parsed_service_config != nullptr &&
-      parsed_service_config->parsed_lb_config() != nullptr) {
-    *lb_policy_config = parsed_service_config->parsed_lb_config();
-    return;
-  }
-  // Try the deprecated LB policy name from the service config.
-  // If not, try the setting from channel args.
-  const char* policy_name = nullptr;
-  if (parsed_service_config != nullptr &&
-      !parsed_service_config->parsed_deprecated_lb_policy().empty()) {
-    policy_name = parsed_service_config->parsed_deprecated_lb_policy().c_str();
-  } else {
-    const grpc_arg* channel_arg =
-        grpc_channel_args_find(resolver_result.args, GRPC_ARG_LB_POLICY_NAME);
-    policy_name = grpc_channel_arg_get_string(channel_arg);
-  }
-  // Use pick_first if nothing was specified and we didn't select grpclb
-  // above.
-  if (policy_name == nullptr) policy_name = "pick_first";
-  // Now that we have the policy name, construct an empty config for it.
-  Json config_json = Json::Array{Json::Object{
-      {policy_name, Json::Object{}},
-  }};
-  grpc_error* parse_error = GRPC_ERROR_NONE;
-  *lb_policy_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
-      config_json, &parse_error);
-  // The policy name came from one of three places:
-  // - The deprecated loadBalancingPolicy field in the service config,
-  //   in which case the code in ClientChannelServiceConfigParser
-  //   already verified that the policy does not require a config.
-  // - One of the hard-coded values here, all of which are known to not
-  //   require a config.
-  // - A channel arg, in which case the application did something that
-  //   is a misuse of our API.
-  // In the first two cases, these assertions will always be true.  In
-  // the last case, this is probably fine for now.
-  // TODO(roth): If the last case becomes a problem, add better error
-  // handling here.
-  GPR_ASSERT(*lb_policy_config != nullptr);
-  GPR_ASSERT(parse_error == GRPC_ERROR_NONE);
-}
-
-// Synchronous callback from ResolvingLoadBalancingPolicy to process a
-// resolver result update.
-bool ChannelData::ProcessResolverResultLocked(
-    void* arg, const Resolver::Result& result,
-    RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config,
-    grpc_error** service_config_error, bool* no_valid_service_config) {
-  ChannelData* chand = static_cast<ChannelData*>(arg);
-  RefCountedPtr<ServiceConfig> service_config;
-  // If resolver did not return a service config or returned an invalid service
-  // config, we need a fallback service config.
-  if (result.service_config_error != GRPC_ERROR_NONE) {
-    // If the service config was invalid, then fallback to the saved service
-    // config. If there is no saved config either, use the default service
-    // config.
-    if (chand->saved_service_config_ != nullptr) {
-      if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
-        gpr_log(GPR_INFO,
-                "chand=%p: resolver returned invalid service config. "
-                "Continuing to use previous service config.",
-                chand);
-      }
-      service_config = chand->saved_service_config_;
-    } else if (chand->default_service_config_ != nullptr) {
-      if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
-        gpr_log(GPR_INFO,
-                "chand=%p: resolver returned invalid service config. Using "
-                "default service config provided by client API.",
-                chand);
-      }
-      service_config = chand->default_service_config_;
-    }
-  } else if (result.service_config == nullptr) {
-    if (chand->default_service_config_ != nullptr) {
-      if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
-        gpr_log(GPR_INFO,
-                "chand=%p: resolver returned no service config. Using default "
-                "service config provided by client API.",
-                chand);
-      }
-      service_config = chand->default_service_config_;
-    }
-  } else {
-    service_config = result.service_config;
-  }
-  *service_config_error = GRPC_ERROR_REF(result.service_config_error);
-  if (service_config == nullptr &&
-      result.service_config_error != GRPC_ERROR_NONE) {
-    *no_valid_service_config = true;
-    return false;
-  }
-  // Process service config.
-  grpc_core::UniquePtr<char> service_config_json;
-  const internal::ClientChannelGlobalParsedConfig* parsed_service_config =
-      nullptr;
-  if (service_config != nullptr) {
-    parsed_service_config =
-        static_cast<const internal::ClientChannelGlobalParsedConfig*>(
-            service_config->GetGlobalParsedConfig(
-                internal::ClientChannelServiceConfigParser::ParserIndex()));
-  }
-  // Check if the config has changed.
-  const bool service_config_changed =
-      ((service_config == nullptr) !=
-       (chand->saved_service_config_ == nullptr)) ||
-      (service_config != nullptr &&
-       service_config->json_string() !=
-           chand->saved_service_config_->json_string());
-  if (service_config_changed) {
-    service_config_json.reset(gpr_strdup(
-        service_config != nullptr ? service_config->json_string().c_str()
-                                  : ""));
-    if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
-      gpr_log(GPR_INFO,
-              "chand=%p: resolver returned updated service config: \"%s\"",
-              chand, service_config_json.get());
-    }
-    // Save health check service name.
-    if (service_config != nullptr) {
-      chand->health_check_service_name_.reset(
-          gpr_strdup(parsed_service_config->health_check_service_name()));
-    } else {
-      chand->health_check_service_name_.reset();
-    }
-    // Update health check service name used by existing subchannel wrappers.
-    for (auto* subchannel_wrapper : chand->subchannel_wrappers_) {
-      subchannel_wrapper->UpdateHealthCheckServiceName(
-          grpc_core::UniquePtr<char>(
-              gpr_strdup(chand->health_check_service_name_.get())));
-    }
-    // Save service config.
-    chand->saved_service_config_ = std::move(service_config);
-  }
-  // We want to set the service config at least once. This should not really be
-  // needed, but we are doing it as a defensive approach. This can be removed,
-  // if we feel it is unnecessary.
-  if (service_config_changed || !chand->received_first_resolver_result_) {
-    chand->received_first_resolver_result_ = true;
-    RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
-    if (parsed_service_config != nullptr) {
-      absl::optional<internal::ClientChannelGlobalParsedConfig::RetryThrottling>
-          retry_throttle_config = parsed_service_config->retry_throttling();
-      if (retry_throttle_config.has_value()) {
-        retry_throttle_data =
-            internal::ServerRetryThrottleMap::GetDataForServer(
-                chand->server_name_.get(),
-                retry_throttle_config.value().max_milli_tokens,
-                retry_throttle_config.value().milli_token_ratio);
-      }
-    }
-    chand->UpdateServiceConfigLocked(std::move(retry_throttle_data),
-                                     chand->saved_service_config_);
-  }
-  chand->ProcessLbPolicy(result, parsed_service_config, lb_policy_config);
-  grpc_core::UniquePtr<char> lb_policy_name(
-      gpr_strdup((*lb_policy_config)->name()));
-  // Swap out the data used by GetChannelInfo().
-  {
-    MutexLock lock(&chand->info_mu_);
-    chand->info_lb_policy_name_ = std::move(lb_policy_name);
-    if (service_config_json != nullptr) {
-      chand->info_service_config_json_ = std::move(service_config_json);
-    }
-  }
-  // Return results.
-  return service_config_changed;
-}
-
 grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) {
   if (state_tracker_.state() != GRPC_CHANNEL_READY) {
     return GRPC_ERROR_CREATE_FROM_STATIC_STRING("channel not connected");
@@ -2807,6 +2885,7 @@ void CallData::RecvInitialMetadataReady(void* arg, grpc_error* error) {
   }
   // Received valid initial metadata, so commit the call.
   calld->RetryCommit(elem, retry_state);
+  calld->MaybeInvokeConfigSelectorCommitCallback();
   // Invoke the callback to return the result to the surface.
   // Manually invoking a callback function; it does not take ownership of error.
   calld->InvokeRecvInitialMetadataCallback(batch_data, error);
@@ -2893,6 +2972,7 @@ void CallData::RecvMessageReady(void* arg, grpc_error* error) {
   }
   // Received a valid message, so commit the call.
   calld->RetryCommit(elem, retry_state);
+  calld->MaybeInvokeConfigSelectorCommitCallback();
   // Invoke the callback to return the result to the surface.
   // Manually invoking a callback function; it does not take ownership of error.
   calld->InvokeRecvMessageCallback(batch_data, error);
@@ -3094,6 +3174,7 @@ void CallData::RecvTrailingMetadataReady(void* arg, grpc_error* error) {
   }
   // Not retrying, so commit the call.
   calld->RetryCommit(elem, retry_state);
+  calld->MaybeInvokeConfigSelectorCommitCallback();
   // Run any necessary closures.
   calld->RunClosuresForCompletedCall(batch_data, GRPC_ERROR_REF(error));
 }
@@ -3716,7 +3797,7 @@ class CallData::QueuedPickCanceller {
     }
     if (calld->pick_canceller_ == self && error != GRPC_ERROR_NONE) {
       // Remove pick from list of queued picks.
-      calld->RemoveCallFromQueuedPicksLocked(self->elem_);
+      calld->MaybeRemoveCallFromQueuedPicksLocked(self->elem_);
       // Fail pending batches on the call.
       calld->PendingBatchesFail(self->elem_, GRPC_ERROR_REF(error),
                                 YieldCallCombinerIfPendingBatchesFound);
@@ -3729,7 +3810,8 @@ class CallData::QueuedPickCanceller {
   grpc_closure closure_;
 };
 
-void CallData::RemoveCallFromQueuedPicksLocked(grpc_call_element* elem) {
+void CallData::MaybeRemoveCallFromQueuedPicksLocked(grpc_call_element* elem) {
+  if (!pick_queued_) return;
   auto* chand = static_cast<ChannelData*>(elem->channel_data);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
     gpr_log(GPR_INFO, "chand=%p calld=%p: removing from queued picks list",
@@ -3741,7 +3823,8 @@ void CallData::RemoveCallFromQueuedPicksLocked(grpc_call_element* elem) {
   pick_canceller_ = nullptr;
 }
 
-void CallData::AddCallToQueuedPicksLocked(grpc_call_element* elem) {
+void CallData::MaybeAddCallToQueuedPicksLocked(grpc_call_element* elem) {
+  if (pick_queued_) return;
   auto* chand = static_cast<ChannelData*>(elem->channel_data);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
     gpr_log(GPR_INFO, "chand=%p calld=%p: adding to queued picks list", chand,
@@ -3754,23 +3837,29 @@ void CallData::AddCallToQueuedPicksLocked(grpc_call_element* elem) {
   pick_canceller_ = new QueuedPickCanceller(elem);
 }
 
-void CallData::ApplyServiceConfigToCallLocked(grpc_call_element* elem) {
+grpc_error* CallData::ApplyServiceConfigToCallLocked(
+    grpc_call_element* elem, grpc_metadata_batch* initial_metadata) {
   ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
     gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
             chand, this);
   }
+  ConfigSelector* config_selector = chand->config_selector();
   auto service_config = chand->service_config();
   if (service_config != nullptr) {
+    // Use the ConfigSelector to determine the config for the call.
+    ConfigSelector::CallConfig call_config =
+        config_selector->GetCallConfig({&path_, initial_metadata});
+    if (call_config.error != GRPC_ERROR_NONE) return call_config.error;
+    call_attributes_ = std::move(call_config.call_attributes);
+    on_call_committed_ = std::move(call_config.on_call_committed);
     // Create a ServiceConfigCallData for the call.  This stores a ref to the
     // ServiceConfig and caches the right set of parsed configs to use for
     // the call.  The MethodConfig will store itself in the call context,
     // so that it can be accessed by filters in the subchannel, and it
     // will be cleaned up when the call ends.
-    const auto* method_params_vector =
-        service_config->GetMethodParsedConfigVector(path_);
     auto* service_config_call_data = arena_->New<ServiceConfigCallData>(
-        std::move(service_config), method_params_vector, call_context_);
+        std::move(service_config), call_config.method_configs, call_context_);
     // Apply our own method params to the call.
     method_params_ = static_cast<ClientChannelMethodParsedConfig*>(
         service_config_call_data->GetMethodParsedConfig(
@@ -3812,16 +3901,13 @@ void CallData::ApplyServiceConfigToCallLocked(grpc_call_element* elem) {
   if (method_params_ == nullptr || method_params_->retry_policy() == nullptr) {
     enable_retries_ = false;
   }
+  return GRPC_ERROR_NONE;
 }
 
-void CallData::MaybeApplyServiceConfigToCallLocked(grpc_call_element* elem) {
-  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
-  // Apply service config data to the call only once, and only if the
-  // channel has the data available.
-  if (GPR_LIKELY(chand->received_service_config_data() &&
-                 !service_config_applied_)) {
-    service_config_applied_ = true;
-    ApplyServiceConfigToCallLocked(elem);
+void CallData::MaybeInvokeConfigSelectorCommitCallback() {
+  if (on_call_committed_ != nullptr) {
+    on_call_committed_();
+    on_call_committed_ = nullptr;
   }
 }
 
@@ -3882,11 +3968,45 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
         GRPC_ERROR_NONE);
     // Queue the pick, so that it will be attempted once the channel
     // becomes connected.
-    AddCallToQueuedPicksLocked(elem);
+    MaybeAddCallToQueuedPicksLocked(elem);
+    return false;
+  }
+  grpc_metadata_batch* initial_metadata_batch =
+      seen_send_initial_metadata_
+          ? &send_initial_metadata_
+          : pending_batches_[0]
+                .batch->payload->send_initial_metadata.send_initial_metadata;
+  // Grab initial metadata flags so that we can check later if the call has
+  // wait_for_ready enabled.
+  const uint32_t send_initial_metadata_flags =
+      seen_send_initial_metadata_ ? send_initial_metadata_flags_
+                                  : pending_batches_[0]
+                                        .batch->payload->send_initial_metadata
+                                        .send_initial_metadata_flags;
+  // Avoid picking if we haven't yet received service config data.
+  if (GPR_UNLIKELY(!chand->received_service_config_data())) {
+    // If the resolver returned transient failure before returning the
+    // first service config, fail any non-wait_for_ready calls.
+    grpc_error* resolver_error = chand->resolver_transient_failure_error();
+    if (resolver_error != GRPC_ERROR_NONE &&
+        (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) ==
+            0) {
+      MaybeRemoveCallFromQueuedPicksLocked(elem);
+      *error = GRPC_ERROR_REF(resolver_error);
+      return true;
+    }
+    // Either the resolver has not yet returned a result, or it has
+    // returned transient failure but the call is wait_for_ready.  In
+    // either case, queue the call.
+    MaybeAddCallToQueuedPicksLocked(elem);
     return false;
   }
-  // Apply service config to call if needed.
-  MaybeApplyServiceConfigToCallLocked(elem);
+  // Apply service config to call if not yet applied.
+  if (GPR_LIKELY(!service_config_applied_)) {
+    service_config_applied_ = true;
+    *error = ApplyServiceConfigToCallLocked(elem, initial_metadata_batch);
+    if (*error != GRPC_ERROR_NONE) return true;
+  }
   // If this is a retry, use the send_initial_metadata payload that
   // we've cached; otherwise, use the pending batch.  The
   // send_initial_metadata batch will be the first pending batch in the
@@ -3899,20 +4019,8 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
   // attempt) to the LB policy instead the one from the parent channel.
   LoadBalancingPolicy::PickArgs pick_args;
   pick_args.call_state = &lb_call_state_;
-  Metadata initial_metadata(
-      this,
-      seen_send_initial_metadata_
-          ? &send_initial_metadata_
-          : pending_batches_[0]
-                .batch->payload->send_initial_metadata.send_initial_metadata);
+  Metadata initial_metadata(this, initial_metadata_batch);
   pick_args.initial_metadata = &initial_metadata;
-  // Grab initial metadata flags so that we can check later if the call has
-  // wait_for_ready enabled.
-  const uint32_t send_initial_metadata_flags =
-      seen_send_initial_metadata_ ? send_initial_metadata_flags_
-                                  : pending_batches_[0]
-                                        .batch->payload->send_initial_metadata
-                                        .send_initial_metadata_flags;
   // Attempt pick.
   auto result = chand->picker()->Pick(pick_args);
   if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
@@ -3927,7 +4035,8 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
       grpc_error* disconnect_error = chand->disconnect_error();
       if (disconnect_error != GRPC_ERROR_NONE) {
         GRPC_ERROR_UNREF(result.error);
-        if (pick_queued_) RemoveCallFromQueuedPicksLocked(elem);
+        MaybeRemoveCallFromQueuedPicksLocked(elem);
+        MaybeInvokeConfigSelectorCommitCallback();
         *error = GRPC_ERROR_REF(disconnect_error);
         return true;
       }
@@ -3948,8 +4057,9 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
                   "Failed to pick subchannel", &result.error, 1);
           GRPC_ERROR_UNREF(result.error);
           *error = new_error;
+          MaybeInvokeConfigSelectorCommitCallback();
         }
-        if (pick_queued_) RemoveCallFromQueuedPicksLocked(elem);
+        MaybeRemoveCallFromQueuedPicksLocked(elem);
         return !retried;
       }
       // If wait_for_ready is true, then queue to retry when we get a new
@@ -3958,22 +4068,24 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
     }
     // Fallthrough
     case LoadBalancingPolicy::PickResult::PICK_QUEUE:
-      if (!pick_queued_) AddCallToQueuedPicksLocked(elem);
+      MaybeAddCallToQueuedPicksLocked(elem);
       return false;
     default:  // PICK_COMPLETE
-      if (pick_queued_) RemoveCallFromQueuedPicksLocked(elem);
+      MaybeRemoveCallFromQueuedPicksLocked(elem);
       // Handle drops.
       if (GPR_UNLIKELY(result.subchannel == nullptr)) {
         result.error = grpc_error_set_int(
             GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                 "Call dropped by load balancing policy"),
             GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+        MaybeInvokeConfigSelectorCommitCallback();
       } else {
         // Grab a ref to the connected subchannel while we're still
         // holding the data plane mutex.
         connected_subchannel_ =
             chand->GetConnectedSubchannelInDataPlane(result.subchannel.get());
         GPR_ASSERT(connected_subchannel_ != nullptr);
+        if (retry_committed_) MaybeInvokeConfigSelectorCommitCallback();
       }
       lb_recv_trailing_metadata_ready_ = result.recv_trailing_metadata_ready;
       *error = result.error;

+ 62 - 0
src/core/ext/filters/client_channel/config_selector.cc

@@ -0,0 +1,62 @@
+//
+// Copyright 2020 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/filters/client_channel/config_selector.h"
+
+#include "src/core/lib/channel/channel_args.h"
+
+// Channel arg key for ConfigSelector.
+#define GRPC_ARG_CONFIG_SELECTOR "grpc.internal.config_selector"
+
+namespace grpc_core {
+
+namespace {
+
+void* ConfigSelectorArgCopy(void* p) {
+  ConfigSelector* config_selector = static_cast<ConfigSelector*>(p);
+  config_selector->Ref().release();
+  return p;
+}
+
+void ConfigSelectorArgDestroy(void* p) {
+  ConfigSelector* config_selector = static_cast<ConfigSelector*>(p);
+  config_selector->Unref();
+}
+
+int ConfigSelectorArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+
+const grpc_arg_pointer_vtable kChannelArgVtable = {
+    ConfigSelectorArgCopy, ConfigSelectorArgDestroy, ConfigSelectorArgCmp};
+
+}  // namespace
+
+grpc_arg ConfigSelector::MakeChannelArg() const {
+  return grpc_channel_arg_pointer_create(
+      const_cast<char*>(GRPC_ARG_CONFIG_SELECTOR),
+      const_cast<ConfigSelector*>(this), &kChannelArgVtable);
+}
+
+RefCountedPtr<ConfigSelector> ConfigSelector::GetFromChannelArgs(
+    const grpc_channel_args& args) {
+  ConfigSelector* config_selector =
+      grpc_channel_args_find_pointer<ConfigSelector>(&args,
+                                                     GRPC_ARG_CONFIG_SELECTOR);
+  return config_selector != nullptr ? config_selector->Ref() : nullptr;
+}
+
+}  // namespace grpc_core

+ 91 - 0
src/core/ext/filters/client_channel/config_selector.h

@@ -0,0 +1,91 @@
+//
+// Copyright 2020 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_CLIENT_CHANNEL_CONFIG_SELECTOR_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONFIG_SELECTOR_H
+
+#include <grpc/support/port_platform.h>
+
+#include <functional>
+#include <map>
+
+#include "absl/strings/string_view.h"
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/slice.h>
+
+#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/filters/client_channel/service_config_parser.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/transport/metadata_batch.h"
+
+namespace grpc_core {
+
+// Internal API used to allow resolver implementations to override
+// MethodConfig and provide input to LB policies on a per-call basis.
+class ConfigSelector : public RefCounted<ConfigSelector> {
+ public:
+  struct GetCallConfigArgs {
+    grpc_slice* path;
+    grpc_metadata_batch* initial_metadata;
+  };
+
+  struct CallConfig {
+    // Can be set to indicate the call should be failed.
+    grpc_error* error = GRPC_ERROR_NONE;
+    // The per-method parsed configs that will be passed to
+    // ServiceConfigCallData.
+    const ServiceConfigParser::ParsedConfigVector* method_configs = nullptr;
+    // Call attributes that will be accessible to LB policy implementations.
+    std::map<const char*, absl::string_view> call_attributes;
+    // A callback that, if set, will be invoked when the call is
+    // committed (i.e., when we know that we will never again need to
+    // ask the picker for a subchannel for this call).
+    std::function<void()> on_call_committed;
+  };
+
+  virtual ~ConfigSelector() = default;
+
+  virtual CallConfig GetCallConfig(GetCallConfigArgs args) = 0;
+
+  grpc_arg MakeChannelArg() const;
+  static RefCountedPtr<ConfigSelector> GetFromChannelArgs(
+      const grpc_channel_args& args);
+};
+
+// Default ConfigSelector that gets the MethodConfig from the service config.
+class DefaultConfigSelector : public ConfigSelector {
+ public:
+  explicit DefaultConfigSelector(RefCountedPtr<ServiceConfig> service_config)
+      : service_config_(std::move(service_config)) {}
+
+  CallConfig GetCallConfig(GetCallConfigArgs args) override {
+    CallConfig call_config;
+    if (service_config_ != nullptr) {
+      call_config.method_configs =
+          service_config_->GetMethodParsedConfigVector(*args.path);
+    }
+    return call_config;
+  }
+
+ private:
+  RefCountedPtr<ServiceConfig> service_config_;
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONFIG_SELECTOR_H */

+ 2 - 0
src/core/ext/filters/client_channel/health/health_check_client.cc

@@ -23,6 +23,8 @@
 
 #include "src/core/ext/filters/client_channel/health/health_check_client.h"
 
+#include "upb/upb.hpp"
+
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/gprpp/sync.h"
 #include "src/core/lib/slice/slice_internal.h"

+ 2 - 0
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc

@@ -68,6 +68,8 @@
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
 
+#include "upb/upb.hpp"
+
 #include <grpc/byte_buffer_reader.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>

+ 33 - 28
src/core/ext/filters/client_channel/resolving_lb_policy.cc

@@ -145,14 +145,12 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
 
 ResolvingLoadBalancingPolicy::ResolvingLoadBalancingPolicy(
     Args args, TraceFlag* tracer, grpc_core::UniquePtr<char> target_uri,
-    ProcessResolverResultCallback process_resolver_result,
-    void* process_resolver_result_user_data)
+    ChannelConfigHelper* helper)
     : LoadBalancingPolicy(std::move(args)),
       tracer_(tracer),
       target_uri_(std::move(target_uri)),
-      process_resolver_result_(process_resolver_result),
-      process_resolver_result_user_data_(process_resolver_result_user_data) {
-  GPR_ASSERT(process_resolver_result != nullptr);
+      helper_(helper) {
+  GPR_ASSERT(helper_ != nullptr);
   resolver_ = ResolverRegistry::CreateResolver(
       target_uri_.get(), args.args, interested_parties(), work_serializer(),
       absl::make_unique<ResolverResultHandler>(Ref()));
@@ -214,6 +212,7 @@ void ResolvingLoadBalancingPolicy::OnResolverError(grpc_error* error) {
   if (lb_policy_ == nullptr) {
     grpc_error* state_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
         "Resolver transient failure", &error, 1);
+    helper_->ResolverTransientFailure(GRPC_ERROR_REF(state_error));
     channel_control_helper()->UpdateState(
         GRPC_CHANNEL_TRANSIENT_FAILURE,
         absl::make_unique<TransientFailurePicker>(state_error));
@@ -304,45 +303,51 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
   TraceStringVector trace_strings;
   const bool resolution_contains_addresses = result.addresses.size() > 0;
   // Process the resolver result.
-  RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config;
-  bool service_config_changed = false;
-  std::string service_config_error_string;
-  if (process_resolver_result_ != nullptr) {
-    grpc_error* service_config_error = GRPC_ERROR_NONE;
-    bool no_valid_service_config = false;
-    service_config_changed = process_resolver_result_(
-        process_resolver_result_user_data_, result, &lb_policy_config,
-        &service_config_error, &no_valid_service_config);
-    if (service_config_error != GRPC_ERROR_NONE) {
-      service_config_error_string = grpc_error_string(service_config_error);
-      if (no_valid_service_config) {
+  ChannelConfigHelper::ApplyServiceConfigResult service_config_result;
+  if (helper_ != nullptr) {
+    service_config_result = helper_->ApplyServiceConfig(result);
+    if (service_config_result.service_config_error != GRPC_ERROR_NONE) {
+      if (service_config_result.no_valid_service_config) {
         // We received an invalid service config and we don't have a
         // fallback service config.
-        OnResolverError(service_config_error);
-      } else {
-        GRPC_ERROR_UNREF(service_config_error);
+        OnResolverError(service_config_result.service_config_error);
+        service_config_result.service_config_error = GRPC_ERROR_NONE;
       }
     }
   } else {
-    lb_policy_config = child_lb_config_;
+    service_config_result.lb_policy_config = child_lb_config_;
   }
-  if (lb_policy_config != nullptr) {
-    // Create or update LB policy, as needed.
-    CreateOrUpdateLbPolicyLocked(std::move(lb_policy_config),
-                                 std::move(result));
+  // Before we send the args to the LB policy, grab the ConfigSelector for
+  // later use.
+  RefCountedPtr<ConfigSelector> config_selector =
+      ConfigSelector::GetFromChannelArgs(*result.args);
+  // Create or update LB policy, as needed.
+  if (service_config_result.lb_policy_config != nullptr) {
+    CreateOrUpdateLbPolicyLocked(
+        std::move(service_config_result.lb_policy_config), std::move(result));
+  }
+  // Apply ConfigSelector to channel.
+  // This needs to happen after the LB policy has been updated, since
+  // the ConfigSelector may need the LB policy to know about new
+  // destinations before it can send RPCs to those destinations.
+  if (helper_ != nullptr) {
+    helper_->ApplyConfigSelector(service_config_result.service_config_changed,
+                                 std::move(config_selector));
   }
   // Add channel trace event.
-  if (service_config_changed) {
+  if (service_config_result.service_config_changed) {
     // TODO(ncteisen): might be worth somehow including a snippet of the
     // config in the trace, at the risk of bloating the trace logs.
     trace_strings.push_back("Service config changed");
   }
-  if (!service_config_error_string.empty()) {
-    trace_strings.push_back(service_config_error_string.c_str());
+  if (service_config_result.service_config_error != GRPC_ERROR_NONE) {
+    trace_strings.push_back(
+        grpc_error_string(service_config_result.service_config_error));
   }
   MaybeAddTraceMessagesForAddressChangesLocked(resolution_contains_addresses,
                                                &trace_strings);
   ConcatenateAndAddChannelTraceLocked(trace_strings);
+  GRPC_ERROR_UNREF(service_config_result.service_config_error);
 }
 
 }  // namespace grpc_core

+ 39 - 20
src/core/ext/filters/client_channel/resolving_lb_policy.h

@@ -23,6 +23,7 @@
 
 #include "absl/container/inlined_vector.h"
 
+#include "src/core/ext/filters/client_channel/config_selector.h"
 #include "src/core/ext/filters/client_channel/lb_policy.h"
 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
 #include "src/core/ext/filters/client_channel/resolver.h"
@@ -52,22 +53,39 @@ namespace grpc_core {
 // child LB policy and config to use.
 class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
  public:
-  // Synchronous callback that takes the resolver result and sets
-  // lb_policy_config to point to the right data.
-  // Returns true if the service config has changed since the last result.
-  // If the returned no_valid_service_config is true, that means that we
-  // don't have a valid service config to use, and we should set the channel
-  // to be in TRANSIENT_FAILURE.
-  typedef bool (*ProcessResolverResultCallback)(
-      void* user_data, const Resolver::Result& result,
-      RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config,
-      grpc_error** service_config_error, bool* no_valid_service_config);
-  // If error is set when this returns, then construction failed, and
-  // the caller may not use the new object.
-  ResolvingLoadBalancingPolicy(
-      Args args, TraceFlag* tracer, grpc_core::UniquePtr<char> target_uri,
-      ProcessResolverResultCallback process_resolver_result,
-      void* process_resolver_result_user_data);
+  class ChannelConfigHelper {
+   public:
+    struct ApplyServiceConfigResult {
+      // Set to true if the service config has changed since the last result.
+      bool service_config_changed = false;
+      // Set to true if we don't have a valid service config to use.
+      // This tells the ResolvingLoadBalancingPolicy to put the channel
+      // into TRANSIENT_FAILURE.
+      bool no_valid_service_config = false;
+      // A service config parsing error occurred.
+      grpc_error* service_config_error = GRPC_ERROR_NONE;
+      // The LB policy config to use.
+      RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config;
+    };
+
+    virtual ~ChannelConfigHelper() = default;
+
+    // Applies the service config to the channel.
+    virtual ApplyServiceConfigResult ApplyServiceConfig(
+        const Resolver::Result& result) = 0;
+
+    // Applies the ConfigSelector to the channel.
+    virtual void ApplyConfigSelector(
+        bool service_config_changed,
+        RefCountedPtr<ConfigSelector> config_selector) = 0;
+
+    // Indicates a resolver transient failure.
+    virtual void ResolverTransientFailure(grpc_error* error) = 0;
+  };
+
+  ResolvingLoadBalancingPolicy(Args args, TraceFlag* tracer,
+                               grpc_core::UniquePtr<char> target_uri,
+                               ChannelConfigHelper* helper);
 
   virtual const char* name() const override { return "resolving_lb"; }
 
@@ -105,15 +123,16 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
   // Passed in from caller at construction time.
   TraceFlag* tracer_;
   grpc_core::UniquePtr<char> target_uri_;
-  ProcessResolverResultCallback process_resolver_result_ = nullptr;
-  void* process_resolver_result_user_data_ = nullptr;
-  grpc_core::UniquePtr<char> child_policy_name_;
-  RefCountedPtr<LoadBalancingPolicy::Config> child_lb_config_;
+  ChannelConfigHelper* helper_;
 
   // Resolver and associated state.
   OrphanablePtr<Resolver> resolver_;
   bool previous_resolution_contained_addresses_ = false;
 
+  // Determined by resolver results.
+  grpc_core::UniquePtr<char> child_policy_name_;
+  RefCountedPtr<LoadBalancingPolicy::Config> child_lb_config_;
+
   // Child LB policy.
   OrphanablePtr<LoadBalancingPolicy> lb_policy_;
 };

+ 142 - 0
src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc

@@ -0,0 +1,142 @@
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// This filter reads GRPC_ARG_SERVICE_CONFIG and populates ServiceConfigCallData
+// in the call context per call for direct channels.
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/client_channel/service_config_call_data.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/surface/channel_init.h"
+
+namespace grpc_core {
+
+namespace {
+
+class ServiceConfigChannelArgChannelData {
+ public:
+  explicit ServiceConfigChannelArgChannelData(
+      const grpc_channel_element_args* args) {
+    const char* service_config_str = grpc_channel_args_find_string(
+        args->channel_args, GRPC_ARG_SERVICE_CONFIG);
+    if (service_config_str != nullptr) {
+      grpc_error* service_config_error = GRPC_ERROR_NONE;
+      auto service_config =
+          ServiceConfig::Create(service_config_str, &service_config_error);
+      if (service_config_error == GRPC_ERROR_NONE) {
+        service_config_ = std::move(service_config);
+      } else {
+        gpr_log(GPR_ERROR, "%s", grpc_error_string(service_config_error));
+      }
+      GRPC_ERROR_UNREF(service_config_error);
+    }
+  }
+
+  RefCountedPtr<ServiceConfig> service_config() const {
+    return service_config_;
+  }
+
+ private:
+  RefCountedPtr<ServiceConfig> service_config_;
+};
+
+class ServiceConfigChannelArgCallData {
+ public:
+  ServiceConfigChannelArgCallData(grpc_call_element* elem,
+                                  const grpc_call_element_args* args) {
+    ServiceConfigChannelArgChannelData* chand =
+        static_cast<ServiceConfigChannelArgChannelData*>(elem->channel_data);
+    RefCountedPtr<ServiceConfig> service_config = chand->service_config();
+    if (service_config != nullptr) {
+      GPR_DEBUG_ASSERT(args->context != nullptr);
+      const auto* method_params_vector =
+          service_config->GetMethodParsedConfigVector(args->path);
+      args->arena->New<ServiceConfigCallData>(
+          std::move(service_config), method_params_vector, args->context);
+    }
+  }
+};
+
+grpc_error* ServiceConfigChannelArgInitCallElem(
+    grpc_call_element* elem, const grpc_call_element_args* args) {
+  ServiceConfigChannelArgCallData* calld =
+      static_cast<ServiceConfigChannelArgCallData*>(elem->call_data);
+  new (calld) ServiceConfigChannelArgCallData(elem, args);
+  return GRPC_ERROR_NONE;
+}
+
+void ServiceConfigChannelArgDestroyCallElem(
+    grpc_call_element* elem, const grpc_call_final_info* /* final_info */,
+    grpc_closure* /* then_schedule_closure */) {
+  ServiceConfigChannelArgCallData* calld =
+      static_cast<ServiceConfigChannelArgCallData*>(elem->call_data);
+  calld->~ServiceConfigChannelArgCallData();
+}
+
+grpc_error* ServiceConfigChannelArgInitChannelElem(
+    grpc_channel_element* elem, grpc_channel_element_args* args) {
+  ServiceConfigChannelArgChannelData* chand =
+      static_cast<ServiceConfigChannelArgChannelData*>(elem->channel_data);
+  new (chand) ServiceConfigChannelArgChannelData(args);
+  return GRPC_ERROR_NONE;
+}
+
+void ServiceConfigChannelArgDestroyChannelElem(grpc_channel_element* elem) {
+  ServiceConfigChannelArgChannelData* chand =
+      static_cast<ServiceConfigChannelArgChannelData*>(elem->channel_data);
+  chand->~ServiceConfigChannelArgChannelData();
+}
+
+const grpc_channel_filter ServiceConfigChannelArgFilter = {
+    grpc_call_next_op,
+    grpc_channel_next_op,
+    sizeof(ServiceConfigChannelArgCallData),
+    ServiceConfigChannelArgInitCallElem,
+    grpc_call_stack_ignore_set_pollset_or_pollset_set,
+    ServiceConfigChannelArgDestroyCallElem,
+    sizeof(ServiceConfigChannelArgChannelData),
+    ServiceConfigChannelArgInitChannelElem,
+    ServiceConfigChannelArgDestroyChannelElem,
+    grpc_channel_next_get_info,
+    "service_config_channel_arg"};
+
+bool maybe_add_service_config_channel_arg_filter(
+    grpc_channel_stack_builder* builder, void* /* arg */) {
+  const grpc_channel_args* channel_args =
+      grpc_channel_stack_builder_get_channel_arguments(builder);
+  if (grpc_channel_args_want_minimal_stack(channel_args) ||
+      grpc_channel_args_find_string(channel_args, GRPC_ARG_SERVICE_CONFIG) ==
+          nullptr) {
+    return true;
+  }
+  return grpc_channel_stack_builder_prepend_filter(
+      builder, &ServiceConfigChannelArgFilter, nullptr, nullptr);
+}
+
+}  // namespace
+
+}  // namespace grpc_core
+
+void grpc_service_config_channel_arg_filter_init(void) {
+  grpc_channel_init_register_stage(
+      GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+      grpc_core::maybe_add_service_config_channel_arg_filter, nullptr);
+}
+
+void grpc_service_config_channel_arg_filter_shutdown(void) {}

+ 88 - 630
src/core/ext/filters/client_channel/xds/xds_api.cc

@@ -26,6 +26,8 @@
 #include "absl/strings/str_join.h"
 #include "absl/strings/str_split.h"
 
+#include "upb/upb.hpp"
+
 #include <grpc/impl/codegen/log.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
@@ -38,26 +40,35 @@
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 
 #include "envoy/api/v2/cds.upb.h"
+#include "envoy/api/v2/cds.upbdefs.h"
+#include "envoy/api/v2/cluster.upbdefs.h"
 #include "envoy/api/v2/core/address.upb.h"
 #include "envoy/api/v2/core/base.upb.h"
 #include "envoy/api/v2/core/config_source.upb.h"
 #include "envoy/api/v2/core/health_check.upb.h"
 #include "envoy/api/v2/discovery.upb.h"
+#include "envoy/api/v2/discovery.upbdefs.h"
 #include "envoy/api/v2/eds.upb.h"
+#include "envoy/api/v2/eds.upbdefs.h"
+#include "envoy/api/v2/endpoint.upbdefs.h"
 #include "envoy/api/v2/endpoint/endpoint.upb.h"
 #include "envoy/api/v2/endpoint/load_report.upb.h"
 #include "envoy/api/v2/lds.upb.h"
 #include "envoy/api/v2/rds.upb.h"
+#include "envoy/api/v2/rds.upbdefs.h"
+#include "envoy/api/v2/route.upbdefs.h"
 #include "envoy/api/v2/route/route.upb.h"
 #include "envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h"
 #include "envoy/config/listener/v2/api_listener.upb.h"
 #include "envoy/service/load_stats/v2/lrs.upb.h"
+#include "envoy/service/load_stats/v2/lrs.upbdefs.h"
 #include "envoy/type/percent.upb.h"
 #include "google/protobuf/any.upb.h"
 #include "google/protobuf/duration.upb.h"
 #include "google/protobuf/struct.upb.h"
 #include "google/protobuf/wrappers.upb.h"
 #include "google/rpc/status.upb.h"
+#include "upb/text_encode.h"
 #include "upb/upb.h"
 
 namespace grpc_core {
@@ -167,13 +178,10 @@ void PopulateListValue(upb_arena* arena, google_protobuf_ListValue* list_value,
 void PopulateMetadata(upb_arena* arena, google_protobuf_Struct* metadata_pb,
                       const Json::Object& metadata) {
   for (const auto& p : metadata) {
-    google_protobuf_Struct_FieldsEntry* field =
-        google_protobuf_Struct_add_fields(metadata_pb, arena);
-    google_protobuf_Struct_FieldsEntry_set_key(
-        field, upb_strview_makez(p.first.c_str()));
-    google_protobuf_Value* value =
-        google_protobuf_Struct_FieldsEntry_mutable_value(field, arena);
+    google_protobuf_Value* value = google_protobuf_Value_new(arena);
     PopulateMetadataValue(arena, value, p.second);
+    google_protobuf_Struct_fields_set(
+        metadata_pb, upb_strview_makez(p.first.c_str()), value, arena);
   }
 }
 
@@ -234,14 +242,12 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node,
     if (!server_name.empty()) {
       google_protobuf_Struct* metadata =
           envoy_api_v2_core_Node_mutable_metadata(node_msg, arena);
-      google_protobuf_Struct_FieldsEntry* field =
-          google_protobuf_Struct_add_fields(metadata, arena);
-      google_protobuf_Struct_FieldsEntry_set_key(
-          field, upb_strview_makez("PROXYLESS_CLIENT_HOSTNAME"));
-      google_protobuf_Value* value =
-          google_protobuf_Struct_FieldsEntry_mutable_value(field, arena);
+      google_protobuf_Value* value = google_protobuf_Value_new(arena);
       google_protobuf_Value_set_string_value(
           value, upb_strview_make(server_name.data(), server_name.size()));
+      google_protobuf_Struct_fields_set(
+          metadata, upb_strview_makez("PROXYLESS_CLIENT_HOSTNAME"), value,
+          arena);
     }
     if (!node->locality_region.empty() || !node->locality_zone.empty() ||
         !node->locality_subzone.empty()) {
@@ -273,172 +279,21 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node,
       arena);
 }
 
-inline absl::string_view UpbStringToAbsl(const upb_strview& str) {
-  return absl::string_view(str.data, str.size);
-}
-
 inline std::string UpbStringToStdString(const upb_strview& str) {
   return std::string(str.data, str.size);
 }
 
-inline void AddStringField(const char* name, const upb_strview& value,
-                           std::vector<std::string>* fields,
-                           bool add_if_empty = false) {
-  if (value.size > 0 || add_if_empty) {
-    fields->emplace_back(
-        absl::StrCat(name, ": \"", UpbStringToAbsl(value), "\""));
-  }
-}
-
-inline void AddUInt32ValueField(const char* name,
-                                const google_protobuf_UInt32Value* value,
-                                std::vector<std::string>* fields) {
-  if (value != nullptr) {
-    fields->emplace_back(absl::StrCat(
-        name, " { value: ", google_protobuf_UInt32Value_value(value), " }"));
-  }
-}
-
-inline void AddLocalityField(int indent_level,
-                             const envoy_api_v2_core_Locality* locality,
-                             std::vector<std::string>* fields) {
-  std::string indent =
-      absl::StrJoin(std::vector<std::string>(indent_level, "  "), "");
-  // region
-  std::string field = absl::StrCat(indent, "region");
-  AddStringField(field.c_str(), envoy_api_v2_core_Locality_region(locality),
-                 fields);
-  // zone
-  field = absl::StrCat(indent, "zone");
-  AddStringField(field.c_str(), envoy_api_v2_core_Locality_zone(locality),
-                 fields);
-  // sub_zone
-  field = absl::StrCat(indent, "sub_zone");
-  AddStringField(field.c_str(), envoy_api_v2_core_Locality_sub_zone(locality),
-                 fields);
-}
-
-void AddNodeLogFields(const envoy_api_v2_core_Node* node,
-                      std::vector<std::string>* fields) {
-  fields->emplace_back("node {");
-  // id
-  AddStringField("  id", envoy_api_v2_core_Node_id(node), fields);
-  // metadata
-  const google_protobuf_Struct* metadata =
-      envoy_api_v2_core_Node_metadata(node);
-  if (metadata != nullptr) {
-    fields->emplace_back("  metadata {");
-    size_t num_entries;
-    const google_protobuf_Struct_FieldsEntry* const* entries =
-        google_protobuf_Struct_fields(metadata, &num_entries);
-    for (size_t i = 0; i < num_entries; ++i) {
-      fields->emplace_back("    field {");
-      // key
-      AddStringField("      key",
-                     google_protobuf_Struct_FieldsEntry_key(entries[i]),
-                     fields);
-      // value
-      const google_protobuf_Value* value =
-          google_protobuf_Struct_FieldsEntry_value(entries[i]);
-      if (value != nullptr) {
-        std::string value_str;
-        if (google_protobuf_Value_has_string_value(value)) {
-          value_str = absl::StrCat(
-              "string_value: \"",
-              UpbStringToAbsl(google_protobuf_Value_string_value(value)), "\"");
-        } else if (google_protobuf_Value_has_null_value(value)) {
-          value_str = "null_value: NULL_VALUE";
-        } else if (google_protobuf_Value_has_number_value(value)) {
-          value_str = absl::StrCat("double_value: ",
-                                   google_protobuf_Value_number_value(value));
-        } else if (google_protobuf_Value_has_bool_value(value)) {
-          value_str = absl::StrCat("bool_value: ",
-                                   google_protobuf_Value_bool_value(value));
-        } else if (google_protobuf_Value_has_struct_value(value)) {
-          value_str = "struct_value: <not printed>";
-        } else if (google_protobuf_Value_has_list_value(value)) {
-          value_str = "list_value: <not printed>";
-        } else {
-          value_str = "<unknown>";
-        }
-        fields->emplace_back(absl::StrCat("      value { ", value_str, " }"));
-      }
-      fields->emplace_back("    }");
-    }
-    fields->emplace_back("  }");
-  }
-  // locality
-  const envoy_api_v2_core_Locality* locality =
-      envoy_api_v2_core_Node_locality(node);
-  if (locality != nullptr) {
-    fields->emplace_back("  locality {");
-    AddLocalityField(2, locality, fields);
-    fields->emplace_back("  }");
-  }
-  // build_version
-  AddStringField("  build_version", envoy_api_v2_core_Node_build_version(node),
-                 fields);
-  // user_agent_name
-  AddStringField("  user_agent_name",
-                 envoy_api_v2_core_Node_user_agent_name(node), fields);
-  // user_agent_version
-  AddStringField("  user_agent_version",
-                 envoy_api_v2_core_Node_user_agent_version(node), fields);
-  // client_features
-  size_t num_client_features;
-  const upb_strview* client_features =
-      envoy_api_v2_core_Node_client_features(node, &num_client_features);
-  for (size_t i = 0; i < num_client_features; ++i) {
-    AddStringField("  client_features", client_features[i], fields);
-  }
-  fields->emplace_back("}");
-}
-
 void MaybeLogDiscoveryRequest(XdsClient* client, TraceFlag* tracer,
+                              upb_symtab* symtab,
                               const envoy_api_v2_DiscoveryRequest* request) {
   if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
       gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
-    // TODO(roth): When we can upgrade upb, use upb textformat code to dump
-    // the raw proto instead of doing this manually.
-    std::vector<std::string> fields;
-    // version_info
-    AddStringField("version_info",
-                   envoy_api_v2_DiscoveryRequest_version_info(request),
-                   &fields);
-    // node
-    const envoy_api_v2_core_Node* node =
-        envoy_api_v2_DiscoveryRequest_node(request);
-    if (node != nullptr) AddNodeLogFields(node, &fields);
-    // resource_names
-    size_t num_resource_names;
-    const upb_strview* resource_names =
-        envoy_api_v2_DiscoveryRequest_resource_names(request,
-                                                     &num_resource_names);
-    for (size_t i = 0; i < num_resource_names; ++i) {
-      AddStringField("resource_names", resource_names[i], &fields);
-    }
-    // type_url
-    AddStringField("type_url", envoy_api_v2_DiscoveryRequest_type_url(request),
-                   &fields);
-    // response_nonce
-    AddStringField("response_nonce",
-                   envoy_api_v2_DiscoveryRequest_response_nonce(request),
-                   &fields);
-    // error_detail
-    const struct google_rpc_Status* error_detail =
-        envoy_api_v2_DiscoveryRequest_error_detail(request);
-    if (error_detail != nullptr) {
-      fields.emplace_back("error_detail {");
-      // code
-      int32_t code = google_rpc_Status_code(error_detail);
-      if (code != 0) fields.emplace_back(absl::StrCat("  code: ", code));
-      // message
-      AddStringField("  message", google_rpc_Status_message(error_detail),
-                     &fields);
-      fields.emplace_back("}");
-    }
+    const upb_msgdef* msg_type =
+        envoy_api_v2_DiscoveryRequest_getmsgdef(symtab);
+    char buf[10240];
+    upb_text_encode(request, msg_type, nullptr, 0, buf, sizeof(buf));
     gpr_log(GPR_DEBUG, "[xds_client %p] constructed ADS request: %s", client,
-            absl::StrJoin(fields, "\n").c_str());
+            buf);
   }
 }
 
@@ -502,368 +357,60 @@ grpc_slice XdsApi::CreateAdsRequest(
         request, upb_strview_make(resource_name.data(), resource_name.size()),
         arena.ptr());
   }
-  MaybeLogDiscoveryRequest(client_, tracer_, request);
+  MaybeLogDiscoveryRequest(client_, tracer_, symtab_.ptr(), request);
   return SerializeDiscoveryRequest(arena.ptr(), request);
 }
 
 namespace {
 
 void MaybeLogDiscoveryResponse(XdsClient* client, TraceFlag* tracer,
+                               upb_symtab* symtab,
                                const envoy_api_v2_DiscoveryResponse* response) {
   if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
       gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
-    // TODO(roth): When we can upgrade upb, use upb textformat code to dump
-    // the raw proto instead of doing this manually.
-    std::vector<std::string> fields;
-    // version_info
-    AddStringField("version_info",
-                   envoy_api_v2_DiscoveryResponse_version_info(response),
-                   &fields);
-    // resources
-    size_t num_resources;
-    envoy_api_v2_DiscoveryResponse_resources(response, &num_resources);
-    fields.emplace_back(
-        absl::StrCat("resources: <", num_resources, " element(s)>"));
-    // type_url
-    AddStringField("type_url",
-                   envoy_api_v2_DiscoveryResponse_type_url(response), &fields);
-    // nonce
-    AddStringField("nonce", envoy_api_v2_DiscoveryResponse_nonce(response),
-                   &fields);
-    gpr_log(GPR_DEBUG, "[xds_client %p] received response: %s", client,
-            absl::StrJoin(fields, "\n").c_str());
+    const upb_msgdef* msg_type =
+        envoy_api_v2_DiscoveryResponse_getmsgdef(symtab);
+    char buf[10240];
+    upb_text_encode(response, msg_type, nullptr, 0, buf, sizeof(buf));
+    gpr_log(GPR_DEBUG, "[xds_client %p] received response: %s", client, buf);
   }
 }
 
 void MaybeLogRouteConfiguration(
-    XdsClient* client, TraceFlag* tracer,
+    XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
     const envoy_api_v2_RouteConfiguration* route_config) {
   if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
       gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
-    // TODO(roth): When we can upgrade upb, use upb textformat code to dump
-    // the raw proto instead of doing this manually.
-    std::vector<std::string> fields;
-    // name
-    AddStringField("name", envoy_api_v2_RouteConfiguration_name(route_config),
-                   &fields);
-    // virtual_hosts
-    size_t num_virtual_hosts;
-    const envoy_api_v2_route_VirtualHost* const* virtual_hosts =
-        envoy_api_v2_RouteConfiguration_virtual_hosts(route_config,
-                                                      &num_virtual_hosts);
-    for (size_t i = 0; i < num_virtual_hosts; ++i) {
-      const auto* virtual_host = virtual_hosts[i];
-      fields.push_back("virtual_hosts {");
-      // name
-      AddStringField(
-          "  name", envoy_api_v2_route_VirtualHost_name(virtual_host), &fields);
-      // domains
-      size_t num_domains;
-      const upb_strview* const domains =
-          envoy_api_v2_route_VirtualHost_domains(virtual_host, &num_domains);
-      for (size_t j = 0; j < num_domains; ++j) {
-        AddStringField("  domains", domains[j], &fields);
-      }
-      // routes
-      size_t num_routes;
-      const envoy_api_v2_route_Route* const* routes =
-          envoy_api_v2_route_VirtualHost_routes(virtual_host, &num_routes);
-      for (size_t j = 0; j < num_routes; ++j) {
-        const auto* route = routes[j];
-        fields.push_back("  route {");
-        // name
-        AddStringField("    name", envoy_api_v2_route_Route_name(route),
-                       &fields);
-        // match
-        const envoy_api_v2_route_RouteMatch* match =
-            envoy_api_v2_route_Route_match(route);
-        if (match != nullptr) {
-          fields.emplace_back("    match {");
-          // path matching
-          if (envoy_api_v2_route_RouteMatch_has_prefix(match)) {
-            AddStringField("      prefix",
-                           envoy_api_v2_route_RouteMatch_prefix(match), &fields,
-                           /*add_if_empty=*/true);
-          } else if (envoy_api_v2_route_RouteMatch_has_path(match)) {
-            AddStringField("      path",
-                           envoy_api_v2_route_RouteMatch_path(match), &fields,
-                           /*add_if_empty=*/true);
-          } else if (envoy_api_v2_route_RouteMatch_has_regex(match)) {
-            AddStringField("      regex",
-                           envoy_api_v2_route_RouteMatch_regex(match), &fields,
-                           /*add_if_empty=*/true);
-          } else if (envoy_api_v2_route_RouteMatch_has_safe_regex(match)) {
-            fields.emplace_back("      safe_regex: <not printed>");
-          } else {
-            fields.emplace_back("      <unknown path matching type>");
-          }
-          // header matching
-          size_t num_headers;
-          envoy_api_v2_route_RouteMatch_headers(match, &num_headers);
-          if (num_headers > 0) {
-            fields.emplace_back(
-                absl::StrCat("      headers: <", num_headers, " element(s)>"));
-          }
-          fields.emplace_back("    }");
-        }
-        // action
-        if (envoy_api_v2_route_Route_has_route(route)) {
-          const envoy_api_v2_route_RouteAction* action =
-              envoy_api_v2_route_Route_route(route);
-          fields.emplace_back("    route {");
-          if (envoy_api_v2_route_RouteAction_has_cluster(action)) {
-            AddStringField("      cluster",
-                           envoy_api_v2_route_RouteAction_cluster(action),
-                           &fields);
-          } else if (envoy_api_v2_route_RouteAction_has_cluster_header(
-                         action)) {
-            AddStringField(
-                "      cluster_header",
-                envoy_api_v2_route_RouteAction_cluster_header(action), &fields);
-          } else if (envoy_api_v2_route_RouteAction_has_weighted_clusters(
-                         action)) {
-            const envoy_api_v2_route_WeightedCluster* weighted_clusters =
-                envoy_api_v2_route_RouteAction_weighted_clusters(action);
-            fields.emplace_back("      weighted_clusters {");
-            size_t num_cluster_weights;
-            const envoy_api_v2_route_WeightedCluster_ClusterWeight* const*
-                cluster_weights = envoy_api_v2_route_WeightedCluster_clusters(
-                    weighted_clusters, &num_cluster_weights);
-            for (size_t i = 0; i < num_cluster_weights; ++i) {
-              const envoy_api_v2_route_WeightedCluster_ClusterWeight*
-                  cluster_weight = cluster_weights[i];
-              fields.emplace_back("        clusters {");
-              AddStringField(
-                  "          name",
-                  envoy_api_v2_route_WeightedCluster_ClusterWeight_name(
-                      cluster_weight),
-                  &fields);
-              AddUInt32ValueField(
-                  "          weight",
-                  envoy_api_v2_route_WeightedCluster_ClusterWeight_weight(
-                      cluster_weight),
-                  &fields);
-              fields.emplace_back("        }");
-            }
-            AddUInt32ValueField("        total_weight",
-                                envoy_api_v2_route_WeightedCluster_total_weight(
-                                    weighted_clusters),
-                                &fields);
-            fields.emplace_back("      }");
-          }
-          fields.emplace_back("    }");
-        } else if (envoy_api_v2_route_Route_has_redirect(route)) {
-          fields.emplace_back("    redirect: <not printed>");
-        } else if (envoy_api_v2_route_Route_has_direct_response(route)) {
-          fields.emplace_back("    direct_response: <not printed>");
-        } else if (envoy_api_v2_route_Route_has_filter_action(route)) {
-          fields.emplace_back("    filter_action: <not printed>");
-        }
-        fields.push_back("  }");
-      }
-      fields.push_back("}");
-    }
-    gpr_log(GPR_DEBUG, "[xds_client %p] RouteConfiguration: %s", client,
-            absl::StrJoin(fields, "\n").c_str());
+    const upb_msgdef* msg_type =
+        envoy_api_v2_RouteConfiguration_getmsgdef(symtab);
+    char buf[10240];
+    upb_text_encode(route_config, msg_type, nullptr, 0, buf, sizeof(buf));
+    gpr_log(GPR_DEBUG, "[xds_client %p] RouteConfiguration: %s", client, buf);
   }
 }
 
-void MaybeLogCluster(XdsClient* client, TraceFlag* tracer,
+void MaybeLogCluster(XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
                      const envoy_api_v2_Cluster* cluster) {
   if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
       gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
-    // TODO(roth): When we can upgrade upb, use upb textformat code to dump
-    // the raw proto instead of doing this manually.
-    std::vector<std::string> fields;
-    // name
-    AddStringField("name", envoy_api_v2_Cluster_name(cluster), &fields);
-    // type
-    if (envoy_api_v2_Cluster_has_type(cluster)) {
-      fields.emplace_back(
-          absl::StrCat("type: ", envoy_api_v2_Cluster_type(cluster)));
-    } else if (envoy_api_v2_Cluster_has_cluster_type(cluster)) {
-      fields.emplace_back("cluster_type: <not printed>");
-    } else {
-      fields.emplace_back("<unknown type>");
-    }
-    // eds_cluster_config
-    const envoy_api_v2_Cluster_EdsClusterConfig* eds_cluster_config =
-        envoy_api_v2_Cluster_eds_cluster_config(cluster);
-    if (eds_cluster_config != nullptr) {
-      fields.emplace_back("eds_cluster_config {");
-      // eds_config
-      const struct envoy_api_v2_core_ConfigSource* eds_config =
-          envoy_api_v2_Cluster_EdsClusterConfig_eds_config(eds_cluster_config);
-      if (eds_config != nullptr) {
-        if (envoy_api_v2_core_ConfigSource_has_ads(eds_config)) {
-          fields.emplace_back("  eds_config { ads {} }");
-        } else {
-          fields.emplace_back("  eds_config: <non-ADS type>");
-        }
-      }
-      // service_name
-      AddStringField("  service_name",
-                     envoy_api_v2_Cluster_EdsClusterConfig_service_name(
-                         eds_cluster_config),
-                     &fields);
-      fields.emplace_back("}");
-    }
-    // lb_policy
-    fields.emplace_back(
-        absl::StrCat("lb_policy: ", envoy_api_v2_Cluster_lb_policy(cluster)));
-    // lrs_server
-    const envoy_api_v2_core_ConfigSource* lrs_server =
-        envoy_api_v2_Cluster_lrs_server(cluster);
-    if (lrs_server != nullptr) {
-      if (envoy_api_v2_core_ConfigSource_has_self(lrs_server)) {
-        fields.emplace_back("lrs_server { self {} }");
-      } else {
-        fields.emplace_back("lrs_server: <non-self type>");
-      }
-    }
-    gpr_log(GPR_DEBUG, "[xds_client %p] Cluster: %s", client,
-            absl::StrJoin(fields, "\n").c_str());
+    const upb_msgdef* msg_type = envoy_api_v2_Cluster_getmsgdef(symtab);
+    char buf[10240];
+    upb_text_encode(cluster, msg_type, nullptr, 0, buf, sizeof(buf));
+    gpr_log(GPR_DEBUG, "[xds_client %p] Cluster: %s", client, buf);
   }
 }
 
 void MaybeLogClusterLoadAssignment(
-    XdsClient* client, TraceFlag* tracer,
+    XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
     const envoy_api_v2_ClusterLoadAssignment* cla) {
   if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
       gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
-    // TODO(roth): When we can upgrade upb, use upb textformat code to dump
-    // the raw proto instead of doing this manually.
-    std::vector<std::string> fields;
-    // cluster_name
-    AddStringField("cluster_name",
-                   envoy_api_v2_ClusterLoadAssignment_cluster_name(cla),
-                   &fields);
-    // endpoints
-    size_t num_localities;
-    const struct envoy_api_v2_endpoint_LocalityLbEndpoints* const*
-        locality_endpoints =
-            envoy_api_v2_ClusterLoadAssignment_endpoints(cla, &num_localities);
-    for (size_t i = 0; i < num_localities; ++i) {
-      const auto* locality_endpoint = locality_endpoints[i];
-      fields.emplace_back("endpoints {");
-      // locality
-      const auto* locality =
-          envoy_api_v2_endpoint_LocalityLbEndpoints_locality(locality_endpoint);
-      if (locality != nullptr) {
-        fields.emplace_back("  locality {");
-        AddLocalityField(2, locality, &fields);
-        fields.emplace_back("  }");
-      }
-      // lb_endpoints
-      size_t num_lb_endpoints;
-      const envoy_api_v2_endpoint_LbEndpoint* const* lb_endpoints =
-          envoy_api_v2_endpoint_LocalityLbEndpoints_lb_endpoints(
-              locality_endpoint, &num_lb_endpoints);
-      for (size_t j = 0; j < num_lb_endpoints; ++j) {
-        const auto* lb_endpoint = lb_endpoints[j];
-        fields.emplace_back("  lb_endpoints {");
-        // health_status
-        uint32_t health_status =
-            envoy_api_v2_endpoint_LbEndpoint_health_status(lb_endpoint);
-        if (health_status > 0) {
-          fields.emplace_back(
-              absl::StrCat("    health_status: ", health_status));
-        }
-        // endpoint
-        const envoy_api_v2_endpoint_Endpoint* endpoint =
-            envoy_api_v2_endpoint_LbEndpoint_endpoint(lb_endpoint);
-        if (endpoint != nullptr) {
-          fields.emplace_back("    endpoint {");
-          // address
-          const auto* address =
-              envoy_api_v2_endpoint_Endpoint_address(endpoint);
-          if (address != nullptr) {
-            fields.emplace_back("      address {");
-            // socket_address
-            const auto* socket_address =
-                envoy_api_v2_core_Address_socket_address(address);
-            if (socket_address != nullptr) {
-              fields.emplace_back("        socket_address {");
-              // address
-              AddStringField(
-                  "          address",
-                  envoy_api_v2_core_SocketAddress_address(socket_address),
-                  &fields);
-              // port_value
-              if (envoy_api_v2_core_SocketAddress_has_port_value(
-                      socket_address)) {
-                fields.emplace_back(
-                    absl::StrCat("          port_value: ",
-                                 envoy_api_v2_core_SocketAddress_port_value(
-                                     socket_address)));
-              } else {
-                fields.emplace_back("        <non-numeric port>");
-              }
-              fields.emplace_back("        }");
-            } else {
-              fields.emplace_back("        <non-socket address>");
-            }
-            fields.emplace_back("      }");
-          }
-          fields.emplace_back("    }");
-        }
-        fields.emplace_back("  }");
-      }
-      // load_balancing_weight
-      AddUInt32ValueField(
-          "  load_balancing_weight",
-          envoy_api_v2_endpoint_LocalityLbEndpoints_load_balancing_weight(
-              locality_endpoint),
-          &fields);
-      // priority
-      uint32_t priority =
-          envoy_api_v2_endpoint_LocalityLbEndpoints_priority(locality_endpoint);
-      if (priority > 0) {
-        fields.emplace_back(absl::StrCat("  priority: ", priority));
-      }
-      fields.emplace_back("}");
-    }
-    // policy
-    const envoy_api_v2_ClusterLoadAssignment_Policy* policy =
-        envoy_api_v2_ClusterLoadAssignment_policy(cla);
-    if (policy != nullptr) {
-      fields.emplace_back("policy {");
-      // drop_overloads
-      size_t num_drop_overloads;
-      const envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload* const*
-          drop_overloads =
-              envoy_api_v2_ClusterLoadAssignment_Policy_drop_overloads(
-                  policy, &num_drop_overloads);
-      for (size_t i = 0; i < num_drop_overloads; ++i) {
-        auto* drop_overload = drop_overloads[i];
-        fields.emplace_back("  drop_overloads {");
-        // category
-        AddStringField(
-            "    category",
-            envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload_category(
-                drop_overload),
-            &fields);
-        // drop_percentage
-        const auto* drop_percentage =
-            envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload_drop_percentage(
-                drop_overload);
-        if (drop_percentage != nullptr) {
-          fields.emplace_back("    drop_percentage {");
-          fields.emplace_back(absl::StrCat(
-              "      numerator: ",
-              envoy_type_FractionalPercent_numerator(drop_percentage)));
-          fields.emplace_back(absl::StrCat(
-              "      denominator: ",
-              envoy_type_FractionalPercent_denominator(drop_percentage)));
-          fields.emplace_back("    }");
-        }
-        fields.emplace_back("  }");
-      }
-      // overprovisioning_factor
-      fields.emplace_back("}");
-    }
+    const upb_msgdef* msg_type =
+        envoy_api_v2_ClusterLoadAssignment_getmsgdef(symtab);
+    char buf[10240];
+    upb_text_encode(cla, msg_type, nullptr, 0, buf, sizeof(buf));
     gpr_log(GPR_DEBUG, "[xds_client %p] ClusterLoadAssignment: %s", client,
-            absl::StrJoin(fields, "\n").c_str());
+            buf);
   }
 }
 
@@ -989,11 +536,11 @@ grpc_error* RouteActionParse(const envoy_api_v2_route_Route* route,
 }
 
 grpc_error* RouteConfigParse(
-    XdsClient* client, TraceFlag* tracer,
+    XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
     const envoy_api_v2_RouteConfiguration* route_config,
     const std::string& expected_server_name, const bool xds_routing_enabled,
     XdsApi::RdsUpdate* rds_update) {
-  MaybeLogRouteConfiguration(client, tracer, route_config);
+  MaybeLogRouteConfiguration(client, tracer, symtab, route_config);
   // Get the virtual hosts.
   size_t size;
   const envoy_api_v2_route_VirtualHost* const* virtual_hosts =
@@ -1081,6 +628,13 @@ grpc_error* RouteConfigParse(
     const envoy_api_v2_route_Route* route = routes[i];
     const envoy_api_v2_route_RouteMatch* match =
         envoy_api_v2_route_Route_match(route);
+    const google_protobuf_BoolValue* case_sensitive =
+        envoy_api_v2_route_RouteMatch_case_sensitive(match);
+    if (case_sensitive != nullptr &&
+        !google_protobuf_BoolValue_value(case_sensitive)) {
+      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+          "case_sensitive if set must be set to true.");
+    }
     XdsApi::RdsUpdate::RdsRoute rds_route;
     if (envoy_api_v2_route_RouteMatch_has_prefix(match)) {
       upb_strview prefix = envoy_api_v2_route_RouteMatch_prefix(match);
@@ -1148,6 +702,7 @@ grpc_error* RouteConfigParse(
 }
 
 grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
+                             upb_symtab* symtab,
                              const envoy_api_v2_DiscoveryResponse* response,
                              const std::string& expected_server_name,
                              const bool xds_routing_enabled,
@@ -1196,9 +751,9 @@ grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
           envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_config(
               http_connection_manager);
       XdsApi::RdsUpdate rds_update;
-      grpc_error* error =
-          RouteConfigParse(client, tracer, route_config, expected_server_name,
-                           xds_routing_enabled, &rds_update);
+      grpc_error* error = RouteConfigParse(client, tracer, symtab, route_config,
+                                           expected_server_name,
+                                           xds_routing_enabled, &rds_update);
       if (error != GRPC_ERROR_NONE) return error;
       lds_update->emplace();
       (*lds_update)->rds_update.emplace(std::move(rds_update));
@@ -1236,7 +791,7 @@ grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
 }
 
 grpc_error* RdsResponseParse(
-    XdsClient* client, TraceFlag* tracer,
+    XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
     const envoy_api_v2_DiscoveryResponse* response,
     const std::string& expected_server_name,
     const std::set<absl::string_view>& expected_route_configuration_names,
@@ -1272,9 +827,9 @@ grpc_error* RdsResponseParse(
     }
     // Parse the route_config.
     XdsApi::RdsUpdate local_rds_update;
-    grpc_error* error =
-        RouteConfigParse(client, tracer, route_config, expected_server_name,
-                         xds_routing_enabled, &local_rds_update);
+    grpc_error* error = RouteConfigParse(
+        client, tracer, symtab, route_config, expected_server_name,
+        xds_routing_enabled, &local_rds_update);
     if (error != GRPC_ERROR_NONE) return error;
     rds_update->emplace(std::move(local_rds_update));
     return GRPC_ERROR_NONE;
@@ -1283,7 +838,7 @@ grpc_error* RdsResponseParse(
 }
 
 grpc_error* CdsResponseParse(
-    XdsClient* client, TraceFlag* tracer,
+    XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
     const envoy_api_v2_DiscoveryResponse* response,
     const std::set<absl::string_view>& expected_cluster_names,
     XdsApi::CdsUpdateMap* cds_update_map, upb_arena* arena) {
@@ -1306,7 +861,7 @@ grpc_error* CdsResponseParse(
     if (cluster == nullptr) {
       return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode cluster.");
     }
-    MaybeLogCluster(client, tracer, cluster);
+    MaybeLogCluster(client, tracer, symtab, cluster);
     // Ignore unexpected cluster names.
     upb_strview cluster_name = envoy_api_v2_Cluster_name(cluster);
     absl::string_view cluster_name_strview(cluster_name.data,
@@ -1470,7 +1025,7 @@ grpc_error* DropParseAndAppend(
 }
 
 grpc_error* EdsResponseParse(
-    XdsClient* client, TraceFlag* tracer,
+    XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
     const envoy_api_v2_DiscoveryResponse* response,
     const std::set<absl::string_view>& expected_eds_service_names,
     XdsApi::EdsUpdateMap* eds_update_map, upb_arena* arena) {
@@ -1496,7 +1051,8 @@ grpc_error* EdsResponseParse(
       return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
           "Can't parse cluster_load_assignment.");
     }
-    MaybeLogClusterLoadAssignment(client, tracer, cluster_load_assignment);
+    MaybeLogClusterLoadAssignment(client, tracer, symtab,
+                                  cluster_load_assignment);
     // Check the cluster name (which actually means eds_service_name). Ignore
     // unexpected names.
     upb_strview cluster_name = envoy_api_v2_ClusterLoadAssignment_cluster_name(
@@ -1573,7 +1129,7 @@ grpc_error* XdsApi::ParseAdsResponse(
     return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
         "Can't decode the whole response.");
   }
-  MaybeLogDiscoveryResponse(client_, tracer_, response);
+  MaybeLogDiscoveryResponse(client_, tracer_, symtab_.ptr(), response);
   // Record the type_url, the version_info, and the nonce of the response.
   upb_strview type_url_strview =
       envoy_api_v2_DiscoveryResponse_type_url(response);
@@ -1585,17 +1141,20 @@ grpc_error* XdsApi::ParseAdsResponse(
   *nonce = UpbStringToStdString(nonce_strview);
   // Parse the response according to the resource type.
   if (*type_url == kLdsTypeUrl) {
-    return LdsResponseParse(client_, tracer_, response, expected_server_name,
-                            xds_routing_enabled_, lds_update, arena.ptr());
+    return LdsResponseParse(client_, tracer_, symtab_.ptr(), response,
+                            expected_server_name, xds_routing_enabled_,
+                            lds_update, arena.ptr());
   } else if (*type_url == kRdsTypeUrl) {
-    return RdsResponseParse(client_, tracer_, response, expected_server_name,
+    return RdsResponseParse(client_, tracer_, symtab_.ptr(), response,
+                            expected_server_name,
                             expected_route_configuration_names,
                             xds_routing_enabled_, rds_update, arena.ptr());
   } else if (*type_url == kCdsTypeUrl) {
-    return CdsResponseParse(client_, tracer_, response, expected_cluster_names,
-                            cds_update_map, arena.ptr());
+    return CdsResponseParse(client_, tracer_, symtab_.ptr(), response,
+                            expected_cluster_names, cds_update_map,
+                            arena.ptr());
   } else if (*type_url == kEdsTypeUrl) {
-    return EdsResponseParse(client_, tracer_, response,
+    return EdsResponseParse(client_, tracer_, symtab_.ptr(), response,
                             expected_eds_service_names, eds_update_map,
                             arena.ptr());
   } else {
@@ -1607,117 +1166,16 @@ grpc_error* XdsApi::ParseAdsResponse(
 namespace {
 
 void MaybeLogLrsRequest(
-    XdsClient* client, TraceFlag* tracer,
+    XdsClient* client, TraceFlag* tracer, upb_symtab* symtab,
     const envoy_service_load_stats_v2_LoadStatsRequest* request) {
   if (GRPC_TRACE_FLAG_ENABLED(*tracer) &&
       gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
-    // TODO(roth): When we can upgrade upb, use upb textformat code to dump
-    // the raw proto instead of doing this manually.
-    std::vector<std::string> fields;
-    // node
-    const auto* node =
-        envoy_service_load_stats_v2_LoadStatsRequest_node(request);
-    if (node != nullptr) {
-      AddNodeLogFields(node, &fields);
-    }
-    // cluster_stats
-    size_t num_cluster_stats;
-    const struct envoy_api_v2_endpoint_ClusterStats* const* cluster_stats =
-        envoy_service_load_stats_v2_LoadStatsRequest_cluster_stats(
-            request, &num_cluster_stats);
-    for (size_t i = 0; i < num_cluster_stats; ++i) {
-      const auto* cluster_stat = cluster_stats[i];
-      fields.emplace_back("cluster_stats {");
-      // cluster_name
-      AddStringField(
-          "  cluster_name",
-          envoy_api_v2_endpoint_ClusterStats_cluster_name(cluster_stat),
-          &fields);
-      // cluster_service_name
-      AddStringField(
-          "  cluster_service_name",
-          envoy_api_v2_endpoint_ClusterStats_cluster_service_name(cluster_stat),
-          &fields);
-      // upstream_locality_stats
-      size_t num_stats;
-      const envoy_api_v2_endpoint_UpstreamLocalityStats* const* stats =
-          envoy_api_v2_endpoint_ClusterStats_upstream_locality_stats(
-              cluster_stat, &num_stats);
-      for (size_t j = 0; j < num_stats; ++j) {
-        const auto* stat = stats[j];
-        fields.emplace_back("  upstream_locality_stats {");
-        // locality
-        const auto* locality =
-            envoy_api_v2_endpoint_UpstreamLocalityStats_locality(stat);
-        if (locality != nullptr) {
-          fields.emplace_back("    locality {");
-          AddLocalityField(3, locality, &fields);
-          fields.emplace_back("    }");
-        }
-        // total_successful_requests
-        fields.emplace_back(absl::StrCat(
-            "    total_successful_requests: ",
-            envoy_api_v2_endpoint_UpstreamLocalityStats_total_successful_requests(
-                stat)));
-        // total_requests_in_progress
-        fields.emplace_back(absl::StrCat(
-            "    total_requests_in_progress: ",
-            envoy_api_v2_endpoint_UpstreamLocalityStats_total_requests_in_progress(
-                stat)));
-        // total_error_requests
-        fields.emplace_back(absl::StrCat(
-            "    total_error_requests: ",
-            envoy_api_v2_endpoint_UpstreamLocalityStats_total_error_requests(
-                stat)));
-        // total_issued_requests
-        fields.emplace_back(absl::StrCat(
-            "    total_issued_requests: ",
-            envoy_api_v2_endpoint_UpstreamLocalityStats_total_issued_requests(
-                stat)));
-        fields.emplace_back("  }");
-      }
-      // total_dropped_requests
-      fields.emplace_back(absl::StrCat(
-          "  total_dropped_requests: ",
-          envoy_api_v2_endpoint_ClusterStats_total_dropped_requests(
-              cluster_stat)));
-      // dropped_requests
-      size_t num_drops;
-      const envoy_api_v2_endpoint_ClusterStats_DroppedRequests* const* drops =
-          envoy_api_v2_endpoint_ClusterStats_dropped_requests(cluster_stat,
-                                                              &num_drops);
-      for (size_t j = 0; j < num_drops; ++j) {
-        const auto* drop = drops[j];
-        fields.emplace_back("  dropped_requests {");
-        // category
-        AddStringField(
-            "    category",
-            envoy_api_v2_endpoint_ClusterStats_DroppedRequests_category(drop),
-            &fields);
-        // dropped_count
-        fields.emplace_back(absl::StrCat(
-            "    dropped_count: ",
-            envoy_api_v2_endpoint_ClusterStats_DroppedRequests_dropped_count(
-                drop)));
-        fields.emplace_back("  }");
-      }
-      // load_report_interval
-      const auto* load_report_interval =
-          envoy_api_v2_endpoint_ClusterStats_load_report_interval(cluster_stat);
-      if (load_report_interval != nullptr) {
-        fields.emplace_back("  load_report_interval {");
-        fields.emplace_back(absl::StrCat(
-            "    seconds: ",
-            google_protobuf_Duration_seconds(load_report_interval)));
-        fields.emplace_back(
-            absl::StrCat("    nanos: ",
-                         google_protobuf_Duration_nanos(load_report_interval)));
-        fields.emplace_back("  }");
-      }
-      fields.emplace_back("}");
-    }
+    const upb_msgdef* msg_type =
+        envoy_service_load_stats_v2_LoadStatsRequest_getmsgdef(symtab);
+    char buf[10240];
+    upb_text_encode(request, msg_type, nullptr, 0, buf, sizeof(buf));
     gpr_log(GPR_DEBUG, "[xds_client %p] constructed LRS request: %s", client,
-            absl::StrJoin(fields, "\n").c_str());
+            buf);
   }
 }
 
@@ -1746,7 +1204,7 @@ grpc_slice XdsApi::CreateLrsInitialRequest(const std::string& server_name) {
   envoy_api_v2_core_Node_add_client_features(
       node_msg, upb_strview_makez("envoy.lrs.supports_send_all_clusters"),
       arena.ptr());
-  MaybeLogLrsRequest(client_, tracer_, request);
+  MaybeLogLrsRequest(client_, tracer_, symtab_.ptr(), request);
   return SerializeLrsRequest(request, arena.ptr());
 }
 
@@ -1859,7 +1317,7 @@ grpc_slice XdsApi::CreateLrsRequest(
     google_protobuf_Duration_set_seconds(load_report_interval, timespec.tv_sec);
     google_protobuf_Duration_set_nanos(load_report_interval, timespec.tv_nsec);
   }
-  MaybeLogLrsRequest(client_, tracer_, request);
+  MaybeLogLrsRequest(client_, tracer_, symtab_.ptr(), request);
   return SerializeLrsRequest(request, arena.ptr());
 }
 

+ 3 - 0
src/core/ext/filters/client_channel/xds/xds_api.h

@@ -28,6 +28,8 @@
 #include "absl/container/inlined_vector.h"
 #include "absl/types/optional.h"
 
+#include "upb/def.hpp"
+
 #include <grpc/slice_buffer.h>
 
 #include "src/core/ext/filters/client_channel/server_address.h"
@@ -271,6 +273,7 @@ class XdsApi {
   TraceFlag* tracer_;
   const bool xds_routing_enabled_;
   const XdsBootstrap::Node* node_;
+  upb::SymbolTable symtab_;
   const std::string build_version_;
   const std::string user_agent_name_;
 };

+ 2 - 1
src/core/ext/filters/http/http_filters_plugin.cc

@@ -38,7 +38,8 @@ static optional_filter compress_filter = {
     &grpc_message_compress_filter, GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION};
 
 static optional_filter decompress_filter = {
-    &grpc_message_decompress_filter, GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION};
+    &grpc_core::MessageDecompressFilter,
+    GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION};
 
 static bool is_building_http_like_transport(
     grpc_channel_stack_builder* builder) {

+ 67 - 25
src/core/ext/filters/http/message_compress/message_decompress_filter.cc

@@ -18,6 +18,8 @@
 
 #include <grpc/support/port_platform.h>
 
+#include "src/core/ext/filters/http/message_compress/message_decompress_filter.h"
+
 #include <assert.h>
 #include <string.h>
 
@@ -27,7 +29,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/ext/filters/http/message_compress/message_decompress_filter.h"
+#include "absl/strings/str_format.h"
+#include "src/core/ext/filters/message_size/message_size_filter.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/compression/algorithm_metadata.h"
 #include "src/core/lib/compression/compression_args.h"
@@ -37,14 +40,25 @@
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/slice/slice_string_helpers.h"
 
+namespace grpc_core {
 namespace {
 
-class ChannelData {};
+class ChannelData {
+ public:
+  explicit ChannelData(const grpc_channel_element_args* args)
+      : max_recv_size_(GetMaxRecvSizeFromChannelArgs(args->channel_args)) {}
+
+  int max_recv_size() const { return max_recv_size_; }
+
+ private:
+  int max_recv_size_;
+};
 
 class CallData {
  public:
-  explicit CallData(const grpc_call_element_args& args)
-      : call_combiner_(args.call_combiner) {
+  CallData(const grpc_call_element_args& args, const ChannelData* chand)
+      : call_combiner_(args.call_combiner),
+        max_recv_message_length_(chand->max_recv_size()) {
     // Initialize state for recv_initial_metadata_ready callback
     GRPC_CLOSURE_INIT(&on_recv_initial_metadata_ready_,
                       OnRecvInitialMetadataReady, this,
@@ -59,6 +73,13 @@ class CallData {
     GRPC_CLOSURE_INIT(&on_recv_trailing_metadata_ready_,
                       OnRecvTrailingMetadataReady, this,
                       grpc_schedule_on_exec_ctx);
+    const MessageSizeParsedConfig* limits =
+        MessageSizeParsedConfig::GetFromCallContext(args.context);
+    if (limits != nullptr && limits->limits().max_recv_size >= 0 &&
+        (limits->limits().max_recv_size < max_recv_message_length_ ||
+         max_recv_message_length_ < 0)) {
+      max_recv_message_length_ = limits->limits().max_recv_size;
+    }
   }
 
   ~CallData() { grpc_slice_buffer_destroy_internal(&recv_slices_); }
@@ -82,7 +103,7 @@ class CallData {
   void MaybeResumeOnRecvTrailingMetadataReady();
   static void OnRecvTrailingMetadataReady(void* arg, grpc_error* error);
 
-  grpc_core::CallCombiner* call_combiner_;
+  CallCombiner* call_combiner_;
   // Overall error for the call
   grpc_error* error_ = GRPC_ERROR_NONE;
   // Fields for handling recv_initial_metadata_ready callback
@@ -91,17 +112,18 @@ class CallData {
   grpc_metadata_batch* recv_initial_metadata_ = nullptr;
   // Fields for handling recv_message_ready callback
   bool seen_recv_message_ready_ = false;
+  int max_recv_message_length_;
   grpc_message_compression_algorithm algorithm_ = GRPC_MESSAGE_COMPRESS_NONE;
   grpc_closure on_recv_message_ready_;
   grpc_closure* original_recv_message_ready_ = nullptr;
   grpc_closure on_recv_message_next_done_;
-  grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_ = nullptr;
+  OrphanablePtr<ByteStream>* recv_message_ = nullptr;
   // recv_slices_ holds the slices read from the original recv_message stream.
   // It is initialized during construction and reset when a new stream is
   // created using it.
   grpc_slice_buffer recv_slices_;
-  std::aligned_storage<sizeof(grpc_core::SliceBufferByteStream),
-                       alignof(grpc_core::SliceBufferByteStream)>::type
+  std::aligned_storage<sizeof(SliceBufferByteStream),
+                       alignof(SliceBufferByteStream)>::type
       recv_replacement_stream_;
   // Fields for handling recv_trailing_metadata_ready callback
   bool seen_recv_trailing_metadata_ready_ = false;
@@ -139,7 +161,7 @@ void CallData::OnRecvInitialMetadataReady(void* arg, grpc_error* error) {
   calld->MaybeResumeOnRecvTrailingMetadataReady();
   grpc_closure* closure = calld->original_recv_initial_metadata_ready_;
   calld->original_recv_initial_metadata_ready_ = nullptr;
-  grpc_core::Closure::Run(DEBUG_LOCATION, closure, GRPC_ERROR_REF(error));
+  Closure::Run(DEBUG_LOCATION, closure, GRPC_ERROR_REF(error));
 }
 
 void CallData::MaybeResumeOnRecvMessageReady() {
@@ -170,6 +192,19 @@ void CallData::OnRecvMessageReady(void* arg, grpc_error* error) {
               0) {
         return calld->ContinueRecvMessageReadyCallback(GRPC_ERROR_NONE);
       }
+      if (calld->max_recv_message_length_ >= 0 &&
+          (*calld->recv_message_)->length() >
+              static_cast<uint32_t>(calld->max_recv_message_length_)) {
+        std::string message_string = absl::StrFormat(
+            "Received message larger than max (%u vs. %d)",
+            (*calld->recv_message_)->length(), calld->max_recv_message_length_);
+        GPR_DEBUG_ASSERT(calld->error_ == GRPC_ERROR_NONE);
+        calld->error_ = grpc_error_set_int(
+            GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string.c_str()),
+            GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED);
+        return calld->ContinueRecvMessageReadyCallback(
+            GRPC_ERROR_REF(calld->error_));
+      }
       grpc_slice_buffer_destroy_internal(&calld->recv_slices_);
       grpc_slice_buffer_init(&calld->recv_slices_);
       return calld->ContinueReadingRecvMessage();
@@ -241,9 +276,9 @@ void CallData::FinishRecvMessage() {
     // Initializing recv_replacement_stream_ with decompressed_slices removes
     // all the slices from decompressed_slices leaving it empty.
     new (&recv_replacement_stream_)
-        grpc_core::SliceBufferByteStream(&decompressed_slices, recv_flags);
-    recv_message_->reset(reinterpret_cast<grpc_core::SliceBufferByteStream*>(
-        &recv_replacement_stream_));
+        SliceBufferByteStream(&decompressed_slices, recv_flags);
+    recv_message_->reset(
+        reinterpret_cast<SliceBufferByteStream*>(&recv_replacement_stream_));
     recv_message_ = nullptr;
   }
   ContinueRecvMessageReadyCallback(GRPC_ERROR_REF(error_));
@@ -254,7 +289,7 @@ void CallData::ContinueRecvMessageReadyCallback(grpc_error* error) {
   // The surface will clean up the receiving stream if there is an error.
   grpc_closure* closure = original_recv_message_ready_;
   original_recv_message_ready_ = nullptr;
-  grpc_core::Closure::Run(DEBUG_LOCATION, closure, error);
+  Closure::Run(DEBUG_LOCATION, closure, error);
 }
 
 void CallData::MaybeResumeOnRecvTrailingMetadataReady() {
@@ -283,7 +318,7 @@ void CallData::OnRecvTrailingMetadataReady(void* arg, grpc_error* error) {
   calld->error_ = GRPC_ERROR_NONE;
   grpc_closure* closure = calld->original_recv_trailing_metadata_ready_;
   calld->original_recv_trailing_metadata_ready_ = nullptr;
-  grpc_core::Closure::Run(DEBUG_LOCATION, closure, error);
+  Closure::Run(DEBUG_LOCATION, closure, error);
 }
 
 void CallData::DecompressStartTransportStreamOpBatch(
@@ -322,37 +357,44 @@ void DecompressStartTransportStreamOpBatch(
   calld->DecompressStartTransportStreamOpBatch(elem, batch);
 }
 
-static grpc_error* DecompressInitCallElem(grpc_call_element* elem,
-                                          const grpc_call_element_args* args) {
-  new (elem->call_data) CallData(*args);
+grpc_error* DecompressInitCallElem(grpc_call_element* elem,
+                                   const grpc_call_element_args* args) {
+  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
+  new (elem->call_data) CallData(*args, chand);
   return GRPC_ERROR_NONE;
 }
 
-static void DecompressDestroyCallElem(
-    grpc_call_element* elem, const grpc_call_final_info* /*final_info*/,
-    grpc_closure* /*ignored*/) {
+void DecompressDestroyCallElem(grpc_call_element* elem,
+                               const grpc_call_final_info* /*final_info*/,
+                               grpc_closure* /*ignored*/) {
   CallData* calld = static_cast<CallData*>(elem->call_data);
   calld->~CallData();
 }
 
-static grpc_error* DecompressInitChannelElem(
-    grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) {
+grpc_error* DecompressInitChannelElem(grpc_channel_element* elem,
+                                      grpc_channel_element_args* args) {
+  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
+  new (chand) ChannelData(args);
   return GRPC_ERROR_NONE;
 }
 
-void DecompressDestroyChannelElem(grpc_channel_element* /*elem*/) {}
+void DecompressDestroyChannelElem(grpc_channel_element* elem) {
+  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
+  chand->~ChannelData();
+}
 
 }  // namespace
 
-const grpc_channel_filter grpc_message_decompress_filter = {
+const grpc_channel_filter MessageDecompressFilter = {
     DecompressStartTransportStreamOpBatch,
     grpc_channel_next_op,
     sizeof(CallData),
     DecompressInitCallElem,
     grpc_call_stack_ignore_set_pollset_or_pollset_set,
     DecompressDestroyCallElem,
-    0,  // sizeof(ChannelData)
+    sizeof(ChannelData),
     DecompressInitChannelElem,
     DecompressDestroyChannelElem,
     grpc_channel_next_get_info,
     "message_decompress"};
+}  // namespace grpc_core

+ 3 - 1
src/core/ext/filters/http/message_compress/message_decompress_filter.h

@@ -23,7 +23,9 @@
 
 #include "src/core/lib/channel/channel_stack.h"
 
-extern const grpc_channel_filter grpc_message_decompress_filter;
+namespace grpc_core {
+extern const grpc_channel_filter MessageDecompressFilter;
+}  // namespace grpc_core
 
 #endif /* GRPC_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_MESSAGE_DECOMPRESS_FILTER_H \
         */

+ 41 - 65
src/core/ext/filters/message_size/message_size_filter.cc

@@ -45,6 +45,25 @@ namespace {
 size_t g_message_size_parser_index;
 }  // namespace
 
+//
+// MessageSizeParsedConfig
+//
+
+const MessageSizeParsedConfig* MessageSizeParsedConfig::GetFromCallContext(
+    const grpc_call_context_element* context) {
+  if (context == nullptr) return nullptr;
+  auto* svc_cfg_call_data = static_cast<ServiceConfigCallData*>(
+      context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
+  if (svc_cfg_call_data == nullptr) return nullptr;
+  return static_cast<const MessageSizeParsedConfig*>(
+      svc_cfg_call_data->GetMethodParsedConfig(
+          MessageSizeParser::ParserIndex()));
+}
+
+//
+// MessageSizeParser
+//
+
 std::unique_ptr<ServiceConfigParser::ParsedConfig>
 MessageSizeParser::ParsePerMethodParams(const Json& json, grpc_error** error) {
   GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
@@ -97,12 +116,26 @@ void MessageSizeParser::Register() {
 }
 
 size_t MessageSizeParser::ParserIndex() { return g_message_size_parser_index; }
+
+int GetMaxRecvSizeFromChannelArgs(const grpc_channel_args* args) {
+  if (grpc_channel_args_want_minimal_stack(args)) return -1;
+  return grpc_channel_args_find_integer(
+      args, GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH,
+      {GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH, -1, INT_MAX});
+}
+
+int GetMaxSendSizeFromChannelArgs(const grpc_channel_args* args) {
+  if (grpc_channel_args_want_minimal_stack(args)) return -1;
+  return grpc_channel_args_find_integer(
+      args, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH,
+      {GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH, -1, INT_MAX});
+}
+
 }  // namespace grpc_core
 
 namespace {
 struct channel_data {
   grpc_core::MessageSizeParsedConfig::message_size_limits limits;
-  grpc_core::RefCountedPtr<grpc_core::ServiceConfig> svc_cfg;
 };
 
 struct call_data {
@@ -118,24 +151,8 @@ struct call_data {
     // Note: Per-method config is only available on the client, so we
     // apply the max request size to the send limit and the max response
     // size to the receive limit.
-    const grpc_core::MessageSizeParsedConfig* limits = nullptr;
-    grpc_core::ServiceConfigCallData* svc_cfg_call_data = nullptr;
-    if (args.context != nullptr) {
-      svc_cfg_call_data = static_cast<grpc_core::ServiceConfigCallData*>(
-          args.context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
-    }
-    if (svc_cfg_call_data != nullptr) {
-      limits = static_cast<const grpc_core::MessageSizeParsedConfig*>(
-          svc_cfg_call_data->GetMethodParsedConfig(
-              grpc_core::MessageSizeParser::ParserIndex()));
-    } else if (chand.svc_cfg != nullptr) {
-      const auto* objs_vector =
-          chand.svc_cfg->GetMethodParsedConfigVector(args.path);
-      if (objs_vector != nullptr) {
-        limits = static_cast<const grpc_core::MessageSizeParsedConfig*>(
-            (*objs_vector)[grpc_core::MessageSizeParser::ParserIndex()].get());
-      }
-    }
+    const grpc_core::MessageSizeParsedConfig* limits =
+        grpc_core::MessageSizeParsedConfig::GetFromCallContext(args.context);
     if (limits != nullptr) {
       if (limits->limits().max_send_size >= 0 &&
           (limits->limits().max_send_size < this->limits.max_send_size ||
@@ -288,35 +305,11 @@ static void message_size_destroy_call_elem(
   calld->~call_data();
 }
 
-static int default_size(const grpc_channel_args* args,
-                        int without_minimal_stack) {
-  if (grpc_channel_args_want_minimal_stack(args)) {
-    return -1;
-  }
-  return without_minimal_stack;
-}
-
 grpc_core::MessageSizeParsedConfig::message_size_limits get_message_size_limits(
     const grpc_channel_args* channel_args) {
   grpc_core::MessageSizeParsedConfig::message_size_limits lim;
-  lim.max_send_size =
-      default_size(channel_args, GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH);
-  lim.max_recv_size =
-      default_size(channel_args, GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH);
-  for (size_t i = 0; i < channel_args->num_args; ++i) {
-    if (strcmp(channel_args->args[i].key, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) ==
-        0) {
-      const grpc_integer_options options = {lim.max_send_size, -1, INT_MAX};
-      lim.max_send_size =
-          grpc_channel_arg_get_integer(&channel_args->args[i], options);
-    }
-    if (strcmp(channel_args->args[i].key,
-               GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) {
-      const grpc_integer_options options = {lim.max_recv_size, -1, INT_MAX};
-      lim.max_recv_size =
-          grpc_channel_arg_get_integer(&channel_args->args[i], options);
-    }
-  }
+  lim.max_send_size = grpc_core::GetMaxSendSizeFromChannelArgs(channel_args);
+  lim.max_recv_size = grpc_core::GetMaxRecvSizeFromChannelArgs(channel_args);
   return lim;
 }
 
@@ -327,26 +320,6 @@ static grpc_error* message_size_init_channel_elem(
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   new (chand) channel_data();
   chand->limits = get_message_size_limits(args->channel_args);
-  // TODO(yashykt): We only need to read GRPC_ARG_SERVICE_CONFIG in the case of
-  // direct channels. (Service config is otherwise stored in the call_context by
-  // client_channel filter.) If we ever need a second filter that also needs to
-  // parse GRPC_ARG_SERVICE_CONFIG, we should refactor this code and add a
-  // separate filter that reads GRPC_ARG_SERVICE_CONFIG and saves the parsed
-  // config in the call_context.
-  const grpc_arg* channel_arg =
-      grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG);
-  const char* service_config_str = grpc_channel_arg_get_string(channel_arg);
-  if (service_config_str != nullptr) {
-    grpc_error* service_config_error = GRPC_ERROR_NONE;
-    auto svc_cfg = grpc_core::ServiceConfig::Create(service_config_str,
-                                                    &service_config_error);
-    if (service_config_error == GRPC_ERROR_NONE) {
-      chand->svc_cfg = std::move(svc_cfg);
-    } else {
-      gpr_log(GPR_ERROR, "%s", grpc_error_string(service_config_error));
-    }
-    GRPC_ERROR_UNREF(service_config_error);
-  }
   return GRPC_ERROR_NONE;
 }
 
@@ -387,6 +360,9 @@ static bool maybe_add_message_size_filter(grpc_channel_stack_builder* builder,
                                           void* /*arg*/) {
   const grpc_channel_args* channel_args =
       grpc_channel_stack_builder_get_channel_arguments(builder);
+  if (grpc_channel_args_want_minimal_stack(channel_args)) {
+    return true;
+  }
   bool enable = false;
   grpc_core::MessageSizeParsedConfig::message_size_limits lim =
       get_message_size_limits(channel_args);

+ 6 - 0
src/core/ext/filters/message_size/message_size_filter.h

@@ -40,6 +40,9 @@ class MessageSizeParsedConfig : public ServiceConfigParser::ParsedConfig {
 
   const message_size_limits& limits() const { return limits_; }
 
+  static const MessageSizeParsedConfig* GetFromCallContext(
+      const grpc_call_context_element* context);
+
  private:
   message_size_limits limits_;
 };
@@ -54,6 +57,9 @@ class MessageSizeParser : public ServiceConfigParser::Parser {
   static size_t ParserIndex();
 };
 
+int GetMaxRecvSizeFromChannelArgs(const grpc_channel_args* args);
+int GetMaxSendSizeFromChannelArgs(const grpc_channel_args* args);
+
 }  // namespace grpc_core
 
 #endif /* GRPC_CORE_EXT_FILTERS_MESSAGE_SIZE_MESSAGE_SIZE_FILTER_H */

+ 380 - 344
src/core/ext/transport/chttp2/server/chttp2_server.cc

@@ -39,6 +39,8 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/handshaker.h"
 #include "src/core/lib/channel/handshaker_registry.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/resource_quota.h"
@@ -47,405 +49,439 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/server.h"
 
-struct server_state {
-  grpc_server* server;
-  grpc_tcp_server* tcp_server;
-  grpc_channel_args* args;
-  gpr_mu mu;
-  bool shutdown;
-  grpc_closure tcp_server_shutdown_complete;
-  grpc_closure* server_destroy_listener_done;
-  grpc_core::HandshakeManager* pending_handshake_mgrs;
-  grpc_core::RefCountedPtr<grpc_core::channelz::ListenSocketNode>
-      channelz_listen_socket;
-};
+namespace grpc_core {
+namespace {
+
+class Chttp2ServerListener : public ServerListenerInterface {
+ public:
+  static grpc_error* Create(grpc_server* server, const char* addr,
+                            grpc_channel_args* args, int* port_num);
+
+  static grpc_error* CreateWithAcceptor(grpc_server* server, const char* name,
+                                        grpc_channel_args* args);
+
+  // Do not instantiate directly.  Use one of the factory methods above.
+  Chttp2ServerListener(grpc_server* server, grpc_channel_args* args);
+  ~Chttp2ServerListener();
+
+  void Start(grpc_server* server, grpc_pollset** pollsets,
+             size_t npollsets) override;
+
+  channelz::ListenSocketNode* channelz_listen_socket_node() const override {
+    return channelz_listen_socket_.get();
+  }
+
+  void SetOnDestroyDone(grpc_closure* on_destroy_done) override;
+
+  void Orphan() override;
+
+ private:
+  class ConnectionState : public RefCounted<ConnectionState> {
+   public:
+    ConnectionState(Chttp2ServerListener* listener,
+                    grpc_pollset* accepting_pollset,
+                    grpc_tcp_server_acceptor* acceptor,
+                    RefCountedPtr<HandshakeManager> handshake_mgr,
+                    grpc_channel_args* args, grpc_endpoint* endpoint);
+
+    ~ConnectionState();
+
+   private:
+    static void OnTimeout(void* arg, grpc_error* error);
+    static void OnReceiveSettings(void* arg, grpc_error* error);
+    static void OnHandshakeDone(void* arg, grpc_error* error);
 
-struct server_connection_state {
-  gpr_refcount refs;
-  server_state* svr_state;
-  grpc_pollset* accepting_pollset;
-  grpc_tcp_server_acceptor* acceptor;
-  grpc_core::RefCountedPtr<grpc_core::HandshakeManager> handshake_mgr;
-  // State for enforcing handshake timeout on receiving HTTP/2 settings.
-  grpc_chttp2_transport* transport;
-  grpc_millis deadline;
-  grpc_timer timer;
-  grpc_closure on_timeout;
-  grpc_closure on_receive_settings;
-  grpc_pollset_set* interested_parties;
+    Chttp2ServerListener* const listener_;
+    grpc_pollset* const accepting_pollset_;
+    grpc_tcp_server_acceptor* const acceptor_;
+    RefCountedPtr<HandshakeManager> handshake_mgr_;
+    // State for enforcing handshake timeout on receiving HTTP/2 settings.
+    grpc_chttp2_transport* transport_ = nullptr;
+    grpc_millis deadline_;
+    grpc_timer timer_;
+    grpc_closure on_timeout_;
+    grpc_closure on_receive_settings_;
+    grpc_pollset_set* const interested_parties_;
+  };
+
+  static void OnAccept(void* arg, grpc_endpoint* tcp,
+                       grpc_pollset* accepting_pollset,
+                       grpc_tcp_server_acceptor* acceptor);
+
+  RefCountedPtr<HandshakeManager> CreateHandshakeManager();
+
+  static void TcpServerShutdownComplete(void* arg, grpc_error* error);
+
+  static void DestroyListener(grpc_server* /*server*/, void* arg,
+                              grpc_closure* destroy_done);
+
+  grpc_server* const server_;
+  grpc_channel_args* const args_;
+  grpc_tcp_server* tcp_server_;
+  Mutex mu_;
+  bool shutdown_ = true;
+  grpc_closure tcp_server_shutdown_complete_;
+  grpc_closure* on_destroy_done_ = nullptr;
+  HandshakeManager* pending_handshake_mgrs_ = nullptr;
+  RefCountedPtr<channelz::ListenSocketNode> channelz_listen_socket_;
 };
 
-static void server_connection_state_unref(
-    server_connection_state* connection_state) {
-  if (gpr_unref(&connection_state->refs)) {
-    if (connection_state->transport != nullptr) {
-      GRPC_CHTTP2_UNREF_TRANSPORT(connection_state->transport,
-                                  "receive settings timeout");
-    }
-    grpc_pollset_set_del_pollset(connection_state->interested_parties,
-                                 connection_state->accepting_pollset);
-    grpc_pollset_set_destroy(connection_state->interested_parties);
-    gpr_free(connection_state);
+//
+// Chttp2ServerListener::ConnectionState
+//
+
+grpc_millis GetConnectionDeadline(const grpc_channel_args* args) {
+  int timeout_ms =
+      grpc_channel_args_find_integer(args, GRPC_ARG_SERVER_HANDSHAKE_TIMEOUT_MS,
+                                     {120 * GPR_MS_PER_SEC, 1, INT_MAX});
+  return ExecCtx::Get()->Now() + timeout_ms;
+}
+
+Chttp2ServerListener::ConnectionState::ConnectionState(
+    Chttp2ServerListener* listener, grpc_pollset* accepting_pollset,
+    grpc_tcp_server_acceptor* acceptor,
+    RefCountedPtr<HandshakeManager> handshake_mgr, grpc_channel_args* args,
+    grpc_endpoint* endpoint)
+    : listener_(listener),
+      accepting_pollset_(accepting_pollset),
+      acceptor_(acceptor),
+      handshake_mgr_(std::move(handshake_mgr)),
+      deadline_(GetConnectionDeadline(args)),
+      interested_parties_(grpc_pollset_set_create()) {
+  grpc_pollset_set_add_pollset(interested_parties_, accepting_pollset_);
+  HandshakerRegistry::AddHandshakers(HANDSHAKER_SERVER, args,
+                                     interested_parties_, handshake_mgr_.get());
+  handshake_mgr_->DoHandshake(endpoint, args, deadline_, acceptor_,
+                              OnHandshakeDone, this);
+}
+
+Chttp2ServerListener::ConnectionState::~ConnectionState() {
+  if (transport_ != nullptr) {
+    GRPC_CHTTP2_UNREF_TRANSPORT(transport_, "receive settings timeout");
   }
+  grpc_pollset_set_del_pollset(interested_parties_, accepting_pollset_);
+  grpc_pollset_set_destroy(interested_parties_);
 }
 
-static void on_timeout(void* arg, grpc_error* error) {
-  server_connection_state* connection_state =
-      static_cast<server_connection_state*>(arg);
+void Chttp2ServerListener::ConnectionState::OnTimeout(void* arg,
+                                                      grpc_error* error) {
+  ConnectionState* self = static_cast<ConnectionState*>(arg);
   // Note that we may be called with GRPC_ERROR_NONE when the timer fires
   // or with an error indicating that the timer system is being shut down.
   if (error != GRPC_ERROR_CANCELLED) {
     grpc_transport_op* op = grpc_make_transport_op(nullptr);
     op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
         "Did not receive HTTP/2 settings before handshake timeout");
-    grpc_transport_perform_op(&connection_state->transport->base, op);
+    grpc_transport_perform_op(&self->transport_->base, op);
   }
-  server_connection_state_unref(connection_state);
+  self->Unref();
 }
 
-static void on_receive_settings(void* arg, grpc_error* error) {
-  server_connection_state* connection_state =
-      static_cast<server_connection_state*>(arg);
+void Chttp2ServerListener::ConnectionState::OnReceiveSettings(
+    void* arg, grpc_error* error) {
+  ConnectionState* self = static_cast<ConnectionState*>(arg);
   if (error == GRPC_ERROR_NONE) {
-    grpc_timer_cancel(&connection_state->timer);
+    grpc_timer_cancel(&self->timer_);
   }
-  server_connection_state_unref(connection_state);
+  self->Unref();
 }
 
-static void on_handshake_done(void* arg, grpc_error* error) {
-  auto* args = static_cast<grpc_core::HandshakerArgs*>(arg);
-  server_connection_state* connection_state =
-      static_cast<server_connection_state*>(args->user_data);
-  gpr_mu_lock(&connection_state->svr_state->mu);
-  grpc_resource_user* resource_user = grpc_server_get_default_resource_user(
-      connection_state->svr_state->server);
-  if (error != GRPC_ERROR_NONE || connection_state->svr_state->shutdown) {
-    const char* error_str = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str);
-    grpc_resource_user* resource_user = grpc_server_get_default_resource_user(
-        connection_state->svr_state->server);
-    if (resource_user != nullptr) {
-      grpc_resource_user_free(resource_user, GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
-    }
-    if (error == GRPC_ERROR_NONE && args->endpoint != nullptr) {
-      // We were shut down after handshaking completed successfully, so
-      // destroy the endpoint here.
-      // TODO(ctiller): It is currently necessary to shutdown endpoints
-      // before destroying them, even if we know that there are no
-      // pending read/write callbacks.  This should be fixed, at which
-      // point this can be removed.
-      grpc_endpoint_shutdown(args->endpoint, GRPC_ERROR_NONE);
-      grpc_endpoint_destroy(args->endpoint);
-      grpc_channel_args_destroy(args->args);
-      grpc_slice_buffer_destroy_internal(args->read_buffer);
-      gpr_free(args->read_buffer);
-    }
-  } else {
-    // If the handshaking succeeded but there is no endpoint, then the
-    // handshaker may have handed off the connection to some external
-    // code, so we can just clean up here without creating a transport.
-    if (args->endpoint != nullptr) {
-      grpc_transport* transport = grpc_create_chttp2_transport(
-          args->args, args->endpoint, false, resource_user);
-      grpc_server_setup_transport(
-          connection_state->svr_state->server, transport,
-          connection_state->accepting_pollset, args->args,
-          grpc_chttp2_transport_get_socket_node(transport), resource_user);
-      // Use notify_on_receive_settings callback to enforce the
-      // handshake deadline.
-      connection_state->transport =
-          reinterpret_cast<grpc_chttp2_transport*>(transport);
-      gpr_ref(&connection_state->refs);
-      GRPC_CLOSURE_INIT(&connection_state->on_receive_settings,
-                        on_receive_settings, connection_state,
-                        grpc_schedule_on_exec_ctx);
-      grpc_chttp2_transport_start_reading(
-          transport, args->read_buffer, &connection_state->on_receive_settings);
-      grpc_channel_args_destroy(args->args);
-      gpr_ref(&connection_state->refs);
-      GRPC_CHTTP2_REF_TRANSPORT((grpc_chttp2_transport*)transport,
-                                "receive settings timeout");
-      GRPC_CLOSURE_INIT(&connection_state->on_timeout, on_timeout,
-                        connection_state, grpc_schedule_on_exec_ctx);
-      grpc_timer_init(&connection_state->timer, connection_state->deadline,
-                      &connection_state->on_timeout);
-    } else {
+void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg,
+                                                            grpc_error* error) {
+  auto* args = static_cast<HandshakerArgs*>(arg);
+  ConnectionState* self = static_cast<ConnectionState*>(args->user_data);
+  {
+    MutexLock lock(&self->listener_->mu_);
+    grpc_resource_user* resource_user =
+        grpc_server_get_default_resource_user(self->listener_->server_);
+    if (error != GRPC_ERROR_NONE || self->listener_->shutdown_) {
+      const char* error_str = grpc_error_string(error);
+      gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str);
+      grpc_resource_user* resource_user =
+          grpc_server_get_default_resource_user(self->listener_->server_);
       if (resource_user != nullptr) {
         grpc_resource_user_free(resource_user,
                                 GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
       }
+      if (error == GRPC_ERROR_NONE && args->endpoint != nullptr) {
+        // We were shut down after handshaking completed successfully, so
+        // destroy the endpoint here.
+        // TODO(ctiller): It is currently necessary to shutdown endpoints
+        // before destroying them, even if we know that there are no
+        // pending read/write callbacks.  This should be fixed, at which
+        // point this can be removed.
+        grpc_endpoint_shutdown(args->endpoint, GRPC_ERROR_NONE);
+        grpc_endpoint_destroy(args->endpoint);
+        grpc_channel_args_destroy(args->args);
+        grpc_slice_buffer_destroy_internal(args->read_buffer);
+        gpr_free(args->read_buffer);
+      }
+    } else {
+      // If the handshaking succeeded but there is no endpoint, then the
+      // handshaker may have handed off the connection to some external
+      // code, so we can just clean up here without creating a transport.
+      if (args->endpoint != nullptr) {
+        grpc_transport* transport = grpc_create_chttp2_transport(
+            args->args, args->endpoint, false, resource_user);
+        grpc_server_setup_transport(
+            self->listener_->server_, transport, self->accepting_pollset_,
+            args->args, grpc_chttp2_transport_get_socket_node(transport),
+            resource_user);
+        // Use notify_on_receive_settings callback to enforce the
+        // handshake deadline.
+        // Note: The reinterpret_cast<>s here are safe, because
+        // grpc_chttp2_transport is a C-style extension of
+        // grpc_transport, so this is morally equivalent of a
+        // static_cast<> to a derived class.
+        // TODO(roth): Change to static_cast<> when we C++-ify the
+        // transport API.
+        self->transport_ = reinterpret_cast<grpc_chttp2_transport*>(transport);
+        self->Ref().release();  // Held by OnReceiveSettings().
+        GRPC_CLOSURE_INIT(&self->on_receive_settings_, OnReceiveSettings, self,
+                          grpc_schedule_on_exec_ctx);
+        grpc_chttp2_transport_start_reading(transport, args->read_buffer,
+                                            &self->on_receive_settings_);
+        grpc_channel_args_destroy(args->args);
+        self->Ref().release();  // Held by OnTimeout().
+        GRPC_CHTTP2_REF_TRANSPORT(
+            reinterpret_cast<grpc_chttp2_transport*>(transport),
+            "receive settings timeout");
+        GRPC_CLOSURE_INIT(&self->on_timeout_, OnTimeout, self,
+                          grpc_schedule_on_exec_ctx);
+        grpc_timer_init(&self->timer_, self->deadline_, &self->on_timeout_);
+      } else {
+        if (resource_user != nullptr) {
+          grpc_resource_user_free(resource_user,
+                                  GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
+        }
+      }
     }
+    self->handshake_mgr_->RemoveFromPendingMgrList(
+        &self->listener_->pending_handshake_mgrs_);
   }
-  connection_state->handshake_mgr->RemoveFromPendingMgrList(
-      &connection_state->svr_state->pending_handshake_mgrs);
-  gpr_mu_unlock(&connection_state->svr_state->mu);
-  connection_state->handshake_mgr.reset();
-  gpr_free(connection_state->acceptor);
-  grpc_tcp_server_unref(connection_state->svr_state->tcp_server);
-  server_connection_state_unref(connection_state);
+  self->handshake_mgr_.reset();
+  gpr_free(self->acceptor_);
+  grpc_tcp_server_unref(self->listener_->tcp_server_);
+  self->Unref();
 }
 
-static void on_accept(void* arg, grpc_endpoint* tcp,
-                      grpc_pollset* accepting_pollset,
-                      grpc_tcp_server_acceptor* acceptor) {
-  server_state* state = static_cast<server_state*>(arg);
-  gpr_mu_lock(&state->mu);
-  if (state->shutdown) {
-    gpr_mu_unlock(&state->mu);
-    grpc_endpoint_shutdown(tcp, GRPC_ERROR_NONE);
-    grpc_endpoint_destroy(tcp);
-    gpr_free(acceptor);
-    return;
+//
+// Chttp2ServerListener
+//
+
+grpc_error* Chttp2ServerListener::Create(grpc_server* server, const char* addr,
+                                         grpc_channel_args* args,
+                                         int* port_num) {
+  std::vector<grpc_error*> error_list;
+  grpc_resolved_addresses* resolved = nullptr;
+  Chttp2ServerListener* listener = nullptr;
+  // The bulk of this method is inside of a lambda to make cleanup
+  // easier without using goto.
+  grpc_error* error = [&]() {
+    *port_num = -1;
+    /* resolve address */
+    grpc_error* error = grpc_blocking_resolve_address(addr, "https", &resolved);
+    if (error != GRPC_ERROR_NONE) return error;
+    // Create Chttp2ServerListener.
+    listener = new Chttp2ServerListener(server, args);
+    error = grpc_tcp_server_create(&listener->tcp_server_shutdown_complete_,
+                                   args, &listener->tcp_server_);
+    if (error != GRPC_ERROR_NONE) return error;
+    for (size_t i = 0; i < resolved->naddrs; i++) {
+      int port_temp;
+      error = grpc_tcp_server_add_port(listener->tcp_server_,
+                                       &resolved->addrs[i], &port_temp);
+      if (error != GRPC_ERROR_NONE) {
+        error_list.push_back(error);
+      } else {
+        if (*port_num == -1) {
+          *port_num = port_temp;
+        } else {
+          GPR_ASSERT(*port_num == port_temp);
+        }
+      }
+    }
+    if (error_list.size() == resolved->naddrs) {
+      std::string msg =
+          absl::StrFormat("No address added out of total %" PRIuPTR " resolved",
+                          resolved->naddrs);
+      return GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(
+          msg.c_str(), error_list.data(), error_list.size());
+    } else if (!error_list.empty()) {
+      std::string msg = absl::StrFormat(
+          "Only %" PRIuPTR " addresses added out of total %" PRIuPTR
+          " resolved",
+          resolved->naddrs - error_list.size(), resolved->naddrs);
+      error = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(
+          msg.c_str(), error_list.data(), error_list.size());
+      gpr_log(GPR_INFO, "WARNING: %s", grpc_error_string(error));
+      GRPC_ERROR_UNREF(error);
+      /* we managed to bind some addresses: continue */
+    }
+    // Create channelz node.
+    if (grpc_channel_args_find_bool(args, GRPC_ARG_ENABLE_CHANNELZ,
+                                    GRPC_ENABLE_CHANNELZ_DEFAULT)) {
+      listener->channelz_listen_socket_ =
+          MakeRefCounted<channelz::ListenSocketNode>(
+              addr, absl::StrFormat("chttp2 listener %s", addr));
+    }
+    /* Register with the server only upon success */
+    grpc_server_add_listener(server,
+                             OrphanablePtr<ServerListenerInterface>(listener));
+    return GRPC_ERROR_NONE;
+  }();
+  if (resolved != nullptr) {
+    grpc_resolved_addresses_destroy(resolved);
+  }
+  if (error != GRPC_ERROR_NONE) {
+    if (listener != nullptr) {
+      if (listener->tcp_server_ != nullptr) {
+        grpc_tcp_server_unref(listener->tcp_server_);
+      } else {
+        delete listener;
+      }
+    } else {
+      grpc_channel_args_destroy(args);
+    }
+    *port_num = 0;
+  }
+  for (grpc_error* error : error_list) {
+    GRPC_ERROR_UNREF(error);
   }
+  return error;
+}
+
+grpc_error* Chttp2ServerListener::CreateWithAcceptor(grpc_server* server,
+                                                     const char* name,
+                                                     grpc_channel_args* args) {
+  Chttp2ServerListener* listener = new Chttp2ServerListener(server, args);
+  grpc_error* error = grpc_tcp_server_create(
+      &listener->tcp_server_shutdown_complete_, args, &listener->tcp_server_);
+  if (error != GRPC_ERROR_NONE) {
+    delete listener;
+    return error;
+  }
+  // TODO(yangg) channelz
+  TcpServerFdHandler** arg_val =
+      grpc_channel_args_find_pointer<TcpServerFdHandler*>(args, name);
+  *arg_val = grpc_tcp_server_create_fd_handler(listener->tcp_server_);
+  grpc_server_add_listener(server,
+                           OrphanablePtr<ServerListenerInterface>(listener));
+  return GRPC_ERROR_NONE;
+}
+
+Chttp2ServerListener::Chttp2ServerListener(grpc_server* server,
+                                           grpc_channel_args* args)
+    : server_(server), args_(args) {
+  GRPC_CLOSURE_INIT(&tcp_server_shutdown_complete_, TcpServerShutdownComplete,
+                    this, grpc_schedule_on_exec_ctx);
+}
+
+Chttp2ServerListener::~Chttp2ServerListener() {
+  grpc_channel_args_destroy(args_);
+}
+
+/* Server callback: start listening on our ports */
+void Chttp2ServerListener::Start(grpc_server* /*server*/,
+                                 grpc_pollset** pollsets,
+                                 size_t pollset_count) {
+  {
+    MutexLock lock(&mu_);
+    shutdown_ = false;
+  }
+  grpc_tcp_server_start(tcp_server_, pollsets, pollset_count, OnAccept, this);
+}
+
+void Chttp2ServerListener::SetOnDestroyDone(grpc_closure* on_destroy_done) {
+  MutexLock lock(&mu_);
+  on_destroy_done_ = on_destroy_done;
+}
+
+RefCountedPtr<HandshakeManager> Chttp2ServerListener::CreateHandshakeManager() {
+  MutexLock lock(&mu_);
+  if (shutdown_) return nullptr;
   grpc_resource_user* resource_user =
-      grpc_server_get_default_resource_user(state->server);
+      grpc_server_get_default_resource_user(server_);
   if (resource_user != nullptr &&
       !grpc_resource_user_safe_alloc(resource_user,
                                      GRPC_RESOURCE_QUOTA_CHANNEL_SIZE)) {
-    gpr_log(
-        GPR_ERROR,
-        "Memory quota exhausted, rejecting the connection, no handshaking.");
-    gpr_mu_unlock(&state->mu);
+    gpr_log(GPR_ERROR,
+            "Memory quota exhausted, rejecting connection, no handshaking.");
+    return nullptr;
+  }
+  auto handshake_mgr = MakeRefCounted<HandshakeManager>();
+  handshake_mgr->AddToPendingMgrList(&pending_handshake_mgrs_);
+  grpc_tcp_server_ref(tcp_server_);  // Ref held by ConnectionState.
+  return handshake_mgr;
+}
+
+void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
+                                    grpc_pollset* accepting_pollset,
+                                    grpc_tcp_server_acceptor* acceptor) {
+  Chttp2ServerListener* self = static_cast<Chttp2ServerListener*>(arg);
+  RefCountedPtr<HandshakeManager> handshake_mgr =
+      self->CreateHandshakeManager();
+  if (handshake_mgr == nullptr) {
     grpc_endpoint_shutdown(tcp, GRPC_ERROR_NONE);
     grpc_endpoint_destroy(tcp);
     gpr_free(acceptor);
     return;
   }
-  auto handshake_mgr = grpc_core::MakeRefCounted<grpc_core::HandshakeManager>();
-  handshake_mgr->AddToPendingMgrList(&state->pending_handshake_mgrs);
-  grpc_tcp_server_ref(state->tcp_server);
-  gpr_mu_unlock(&state->mu);
-  server_connection_state* connection_state =
-      static_cast<server_connection_state*>(
-          gpr_zalloc(sizeof(*connection_state)));
-  gpr_ref_init(&connection_state->refs, 1);
-  connection_state->svr_state = state;
-  connection_state->accepting_pollset = accepting_pollset;
-  connection_state->acceptor = acceptor;
-  connection_state->handshake_mgr = handshake_mgr;
-  connection_state->interested_parties = grpc_pollset_set_create();
-  grpc_pollset_set_add_pollset(connection_state->interested_parties,
-                               connection_state->accepting_pollset);
-  grpc_core::HandshakerRegistry::AddHandshakers(
-      grpc_core::HANDSHAKER_SERVER, state->args,
-      connection_state->interested_parties,
-      connection_state->handshake_mgr.get());
-  const grpc_arg* timeout_arg =
-      grpc_channel_args_find(state->args, GRPC_ARG_SERVER_HANDSHAKE_TIMEOUT_MS);
-  connection_state->deadline =
-      grpc_core::ExecCtx::Get()->Now() +
-      grpc_channel_arg_get_integer(timeout_arg,
-                                   {120 * GPR_MS_PER_SEC, 1, INT_MAX});
-  connection_state->handshake_mgr->DoHandshake(
-      tcp, state->args, connection_state->deadline, acceptor, on_handshake_done,
-      connection_state);
-}
-
-/* Server callback: start listening on our ports */
-static void server_start_listener(grpc_server* /*server*/, void* arg,
-                                  grpc_pollset** pollsets,
-                                  size_t pollset_count) {
-  server_state* state = static_cast<server_state*>(arg);
-  gpr_mu_lock(&state->mu);
-  state->shutdown = false;
-  gpr_mu_unlock(&state->mu);
-  grpc_tcp_server_start(state->tcp_server, pollsets, pollset_count, on_accept,
-                        state);
+  // Deletes itself when done.
+  new ConnectionState(self, accepting_pollset, acceptor,
+                      std::move(handshake_mgr), self->args_, tcp);
 }
 
-static void tcp_server_shutdown_complete(void* arg, grpc_error* error) {
-  server_state* state = static_cast<server_state*>(arg);
+void Chttp2ServerListener::TcpServerShutdownComplete(void* arg,
+                                                     grpc_error* error) {
+  Chttp2ServerListener* self = static_cast<Chttp2ServerListener*>(arg);
   /* ensure all threads have unlocked */
-  gpr_mu_lock(&state->mu);
-  grpc_closure* destroy_done = state->server_destroy_listener_done;
-  GPR_ASSERT(state->shutdown);
-  if (state->pending_handshake_mgrs != nullptr) {
-    state->pending_handshake_mgrs->ShutdownAllPending(GRPC_ERROR_REF(error));
+  grpc_closure* destroy_done = nullptr;
+  {
+    MutexLock lock(&self->mu_);
+    destroy_done = self->on_destroy_done_;
+    GPR_ASSERT(self->shutdown_);
+    if (self->pending_handshake_mgrs_ != nullptr) {
+      self->pending_handshake_mgrs_->ShutdownAllPending(GRPC_ERROR_REF(error));
+    }
+    self->channelz_listen_socket_.reset();
   }
-  state->channelz_listen_socket.reset();
-  gpr_mu_unlock(&state->mu);
   // Flush queued work before destroying handshaker factory, since that
   // may do a synchronous unref.
-  grpc_core::ExecCtx::Get()->Flush();
+  ExecCtx::Get()->Flush();
   if (destroy_done != nullptr) {
-    grpc_core::ExecCtx::Run(DEBUG_LOCATION, destroy_done,
-                            GRPC_ERROR_REF(error));
-    grpc_core::ExecCtx::Get()->Flush();
+    ExecCtx::Run(DEBUG_LOCATION, destroy_done, GRPC_ERROR_REF(error));
+    ExecCtx::Get()->Flush();
   }
-  grpc_channel_args_destroy(state->args);
-  gpr_mu_destroy(&state->mu);
-  gpr_free(state);
+  delete self;
 }
 
 /* Server callback: destroy the tcp listener (so we don't generate further
    callbacks) */
-static void server_destroy_listener(grpc_server* /*server*/, void* arg,
-                                    grpc_closure* destroy_done) {
-  server_state* state = static_cast<server_state*>(arg);
-  gpr_mu_lock(&state->mu);
-  state->shutdown = true;
-  state->server_destroy_listener_done = destroy_done;
-  grpc_tcp_server* tcp_server = state->tcp_server;
-  gpr_mu_unlock(&state->mu);
+void Chttp2ServerListener::Orphan() {
+  grpc_tcp_server* tcp_server;
+  {
+    MutexLock lock(&mu_);
+    shutdown_ = true;
+    tcp_server = tcp_server_;
+  }
   grpc_tcp_server_shutdown_listeners(tcp_server);
   grpc_tcp_server_unref(tcp_server);
 }
 
-static grpc_error* chttp2_server_add_acceptor(grpc_server* server,
-                                              const char* name,
-                                              grpc_channel_args* args) {
-  grpc_tcp_server* tcp_server = nullptr;
-  grpc_error* err = GRPC_ERROR_NONE;
-  server_state* state = nullptr;
-  const grpc_arg* arg = nullptr;
-  grpc_core::TcpServerFdHandler** arg_val = nullptr;
-  state = static_cast<server_state*>(gpr_zalloc(sizeof(*state)));
-  GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete,
-                    tcp_server_shutdown_complete, state,
-                    grpc_schedule_on_exec_ctx);
-  err = grpc_tcp_server_create(&state->tcp_server_shutdown_complete, args,
-                               &tcp_server);
-  if (err != GRPC_ERROR_NONE) {
-    goto error;
-  }
-  state->server = server;
-  state->tcp_server = tcp_server;
-  state->args = args;
-  state->shutdown = true;
-  gpr_mu_init(&state->mu);
-  // TODO(yangg) channelz
-  arg = grpc_channel_args_find(args, name);
-  GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
-  arg_val = static_cast<grpc_core::TcpServerFdHandler**>(arg->value.pointer.p);
-  *arg_val = grpc_tcp_server_create_fd_handler(tcp_server);
-
-  grpc_server_add_listener(server, state, server_start_listener,
-                           server_destroy_listener, /* node */ nullptr);
-  return err;
-
-/* Error path: cleanup and return */
-error:
-  GPR_ASSERT(err != GRPC_ERROR_NONE);
-  if (tcp_server) {
-    grpc_tcp_server_unref(tcp_server);
-  } else {
-    grpc_channel_args_destroy(args);
-    gpr_free(state);
-  }
-  return err;
-}
+}  // namespace
 
-grpc_error* grpc_chttp2_server_add_port(grpc_server* server, const char* addr,
-                                        grpc_channel_args* args,
-                                        int* port_num) {
-  grpc_resolved_addresses* resolved = nullptr;
-  grpc_tcp_server* tcp_server = nullptr;
-  size_t i;
-  size_t count = 0;
-  int port_temp;
-  grpc_error* err = GRPC_ERROR_NONE;
-  server_state* state = nullptr;
-  grpc_error** errors = nullptr;
-  size_t naddrs = 0;
-  const grpc_arg* arg = nullptr;
-
-  *port_num = -1;
+//
+// Chttp2ServerAddPort()
+//
 
+grpc_error* Chttp2ServerAddPort(grpc_server* server, const char* addr,
+                                grpc_channel_args* args, int* port_num) {
   if (strncmp(addr, "external:", 9) == 0) {
-    return chttp2_server_add_acceptor(server, addr, args);
-  }
-
-  /* resolve address */
-  err = grpc_blocking_resolve_address(addr, "https", &resolved);
-  if (err != GRPC_ERROR_NONE) {
-    goto error;
-  }
-  state = static_cast<server_state*>(gpr_zalloc(sizeof(*state)));
-  GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete,
-                    tcp_server_shutdown_complete, state,
-                    grpc_schedule_on_exec_ctx);
-  err = grpc_tcp_server_create(&state->tcp_server_shutdown_complete, args,
-                               &tcp_server);
-  if (err != GRPC_ERROR_NONE) {
-    goto error;
-  }
-
-  state->server = server;
-  state->tcp_server = tcp_server;
-  state->args = args;
-  state->shutdown = true;
-  gpr_mu_init(&state->mu);
-
-  naddrs = resolved->naddrs;
-  errors = static_cast<grpc_error**>(gpr_malloc(sizeof(*errors) * naddrs));
-  for (i = 0; i < naddrs; i++) {
-    errors[i] =
-        grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp);
-    if (errors[i] == GRPC_ERROR_NONE) {
-      if (*port_num == -1) {
-        *port_num = port_temp;
-      } else {
-        GPR_ASSERT(*port_num == port_temp);
-      }
-      count++;
-    }
+    return grpc_core::Chttp2ServerListener::CreateWithAcceptor(server, addr,
+                                                               args);
   }
-  if (count == 0) {
-    char* msg;
-    gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
-                 naddrs);
-    err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs);
-    gpr_free(msg);
-    goto error;
-  } else if (count != naddrs) {
-    char* msg;
-    gpr_asprintf(&msg,
-                 "Only %" PRIuPTR " addresses added out of total %" PRIuPTR
-                 " resolved",
-                 count, naddrs);
-    err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs);
-    gpr_free(msg);
-
-    const char* warning_message = grpc_error_string(err);
-    gpr_log(GPR_INFO, "WARNING: %s", warning_message);
-
-    /* we managed to bind some addresses: continue */
-  }
-  grpc_resolved_addresses_destroy(resolved);
-
-  arg = grpc_channel_args_find(args, GRPC_ARG_ENABLE_CHANNELZ);
-  if (grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT)) {
-    state->channelz_listen_socket =
-        grpc_core::MakeRefCounted<grpc_core::channelz::ListenSocketNode>(
-            addr, absl::StrFormat("chttp2 listener %s", addr));
-  }
-
-  /* Register with the server only upon success */
-  grpc_server_add_listener(server, state, server_start_listener,
-                           server_destroy_listener,
-                           state->channelz_listen_socket);
-  goto done;
-
-/* Error path: cleanup and return */
-error:
-  GPR_ASSERT(err != GRPC_ERROR_NONE);
-  if (resolved) {
-    grpc_resolved_addresses_destroy(resolved);
-  }
-  if (tcp_server) {
-    grpc_tcp_server_unref(tcp_server);
-  } else {
-    grpc_channel_args_destroy(args);
-    gpr_free(state);
-  }
-  *port_num = 0;
-
-done:
-  if (errors != nullptr) {
-    for (i = 0; i < naddrs; i++) {
-      GRPC_ERROR_UNREF(errors[i]);
-    }
-    gpr_free(errors);
-  }
-  return err;
+  return grpc_core::Chttp2ServerListener::Create(server, addr, args, port_num);
 }
+
+}  // namespace grpc_core

+ 6 - 2
src/core/ext/transport/chttp2/server/chttp2_server.h

@@ -25,9 +25,13 @@
 
 #include "src/core/lib/iomgr/error.h"
 
+namespace grpc_core {
+
 /// Adds a port to \a server.  Sets \a port_num to the port number.
 /// Takes ownership of \a args.
-grpc_error* grpc_chttp2_server_add_port(grpc_server* server, const char* addr,
-                                        grpc_channel_args* args, int* port_num);
+grpc_error* Chttp2ServerAddPort(grpc_server* server, const char* addr,
+                                grpc_channel_args* args, int* port_num);
+
+}  // namespace grpc_core
 
 #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H */

Some files were not shown because too many files changed in this diff