grpc 1.32.0 → 1.33.0.pre1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +175 -376
  3. data/include/grpc/grpc.h +0 -5
  4. data/include/grpc/grpc_security.h +16 -0
  5. data/include/grpc/impl/codegen/grpc_types.h +0 -5
  6. data/src/core/ext/filters/client_channel/client_channel.cc +204 -170
  7. data/src/core/ext/filters/client_channel/config_selector.cc +0 -4
  8. data/src/core/ext/filters/client_channel/config_selector.h +34 -5
  9. data/src/core/ext/filters/client_channel/lb_policy.h +1 -1
  10. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +48 -35
  11. data/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +7 -5
  12. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +3 -2
  13. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +106 -106
  14. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +2 -2
  15. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +3 -3
  16. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +3 -3
  17. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +9 -32
  18. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +3 -3
  19. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +198 -126
  20. data/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc +439 -249
  21. data/src/core/ext/filters/client_channel/lb_policy/xds/eds_drop.cc +571 -0
  22. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +727 -0
  23. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +8 -1
  24. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +1 -1
  25. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +553 -358
  26. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h +28 -0
  27. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +8 -39
  28. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +4 -2
  29. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +44 -43
  30. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +5 -9
  31. data/src/core/ext/filters/client_channel/server_address.cc +80 -0
  32. data/src/core/ext/filters/client_channel/server_address.h +25 -36
  33. data/src/core/ext/filters/client_channel/service_config.cc +16 -13
  34. data/src/core/ext/filters/client_channel/service_config.h +7 -4
  35. data/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +2 -2
  36. data/src/core/ext/filters/client_channel/service_config_parser.cc +8 -6
  37. data/src/core/ext/filters/client_channel/service_config_parser.h +8 -5
  38. data/src/core/ext/filters/client_channel/subchannel_interface.h +44 -0
  39. data/src/core/ext/filters/message_size/message_size_filter.cc +2 -1
  40. data/src/core/ext/filters/message_size/message_size_filter.h +2 -1
  41. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +17 -10
  42. data/src/core/ext/transport/chttp2/transport/flow_control.cc +10 -2
  43. data/src/core/ext/transport/chttp2/transport/flow_control.h +10 -0
  44. data/src/core/ext/transport/chttp2/transport/internal.h +5 -0
  45. data/src/core/ext/transport/chttp2/transport/parsing.cc +16 -2
  46. data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c +29 -9
  47. data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h +66 -0
  48. data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c +123 -45
  49. data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h +310 -53
  50. data/src/core/ext/upb-generated/envoy/config/core/v3/address.upb.c +17 -5
  51. data/src/core/ext/upb-generated/envoy/config/core/v3/address.upb.h +45 -0
  52. data/src/core/ext/upb-generated/envoy/config/core/v3/base.upb.c +1 -0
  53. data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.c +16 -9
  54. data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.h +38 -15
  55. data/src/core/ext/upb-generated/envoy/config/core/v3/extension.upb.c +53 -0
  56. data/src/core/ext/upb-generated/envoy/config/core/v3/extension.upb.h +133 -0
  57. data/src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.c +54 -8
  58. data/src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.h +123 -5
  59. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c +40 -16
  60. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h +114 -5
  61. data/src/core/ext/upb-generated/envoy/config/core/v3/substitution_format_string.upb.c +36 -0
  62. data/src/core/ext/upb-generated/envoy/config/core/v3/substitution_format_string.upb.h +85 -0
  63. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c +36 -16
  64. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h +86 -20
  65. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c +23 -6
  66. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h +54 -5
  67. data/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c +10 -6
  68. data/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h +28 -11
  69. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c +184 -57
  70. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h +504 -69
  71. data/src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c +6 -5
  72. data/src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h +11 -7
  73. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c +78 -26
  74. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h +236 -25
  75. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c +8 -9
  76. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h +19 -33
  77. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c +7 -3
  78. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.h +16 -0
  79. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls.upb.c +65 -23
  80. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls.upb.h +229 -47
  81. data/src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.c +20 -10
  82. data/src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.h +67 -4
  83. data/src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c +3 -2
  84. data/src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h +6 -0
  85. data/src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c +242 -0
  86. data/src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h +753 -0
  87. data/src/core/ext/upb-generated/udpa/annotations/security.upb.c +31 -0
  88. data/src/core/ext/upb-generated/udpa/annotations/security.upb.h +57 -0
  89. data/src/core/ext/upb-generated/udpa/core/v1/authority.upb.c +28 -0
  90. data/src/core/ext/upb-generated/udpa/core/v1/authority.upb.h +53 -0
  91. data/src/core/ext/upb-generated/udpa/core/v1/collection_entry.upb.c +52 -0
  92. data/src/core/ext/upb-generated/udpa/core/v1/collection_entry.upb.h +129 -0
  93. data/src/core/ext/upb-generated/udpa/core/v1/context_params.upb.c +42 -0
  94. data/src/core/ext/upb-generated/udpa/core/v1/context_params.upb.h +77 -0
  95. data/src/core/ext/upb-generated/udpa/core/v1/resource.upb.c +36 -0
  96. data/src/core/ext/upb-generated/udpa/core/v1/resource.upb.h +85 -0
  97. data/src/core/ext/upb-generated/udpa/core/v1/resource_locator.upb.c +54 -0
  98. data/src/core/ext/upb-generated/udpa/core/v1/resource_locator.upb.h +160 -0
  99. data/src/core/ext/upb-generated/udpa/core/v1/resource_name.upb.c +36 -0
  100. data/src/core/ext/upb-generated/udpa/core/v1/resource_name.upb.h +84 -0
  101. data/src/core/ext/xds/certificate_provider_factory.h +59 -0
  102. data/src/core/ext/xds/certificate_provider_registry.cc +103 -0
  103. data/src/core/ext/xds/certificate_provider_registry.h +57 -0
  104. data/src/core/ext/xds/certificate_provider_store.h +50 -0
  105. data/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.cc +377 -0
  106. data/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.h +102 -0
  107. data/src/core/ext/xds/xds_api.cc +301 -93
  108. data/src/core/ext/xds/xds_api.h +129 -92
  109. data/src/core/ext/xds/xds_channel_args.h +6 -3
  110. data/src/core/ext/xds/xds_client.cc +498 -410
  111. data/src/core/ext/xds/xds_client.h +105 -51
  112. data/src/core/ext/xds/xds_client_stats.cc +18 -12
  113. data/src/core/ext/xds/xds_client_stats.h +33 -5
  114. data/src/core/lib/channel/channel_args.h +0 -1
  115. data/src/core/lib/channel/channelz.cc +10 -45
  116. data/src/core/lib/channel/channelz.h +11 -19
  117. data/src/core/lib/channel/channelz_registry.cc +12 -11
  118. data/src/core/lib/channel/channelz_registry.h +3 -0
  119. data/src/core/lib/gpr/time_precise.cc +2 -0
  120. data/src/core/lib/gpr/time_precise.h +6 -2
  121. data/src/core/lib/gprpp/dual_ref_counted.h +336 -0
  122. data/src/core/lib/gprpp/ref_counted.h +51 -22
  123. data/src/core/lib/gprpp/ref_counted_ptr.h +153 -0
  124. data/src/core/lib/iomgr/endpoint_cfstream.cc +9 -5
  125. data/src/core/lib/iomgr/exec_ctx.h +10 -8
  126. data/src/core/lib/json/json_util.cc +58 -0
  127. data/src/core/lib/json/json_util.h +37 -0
  128. data/src/core/lib/security/certificate_provider.h +60 -0
  129. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc +321 -0
  130. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h +214 -0
  131. data/src/core/lib/security/credentials/xds/xds_credentials.cc +45 -0
  132. data/src/core/lib/security/credentials/xds/xds_credentials.h +51 -0
  133. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +6 -10
  134. data/src/core/lib/security/security_connector/ssl_utils.h +5 -0
  135. data/src/core/lib/surface/channel.cc +9 -31
  136. data/src/core/lib/surface/channel.h +6 -1
  137. data/src/core/lib/surface/init.cc +26 -9
  138. data/src/core/lib/surface/version.cc +2 -2
  139. data/src/core/lib/transport/bdp_estimator.h +2 -1
  140. data/src/core/lib/transport/connectivity_state.h +2 -2
  141. data/src/core/lib/transport/metadata.cc +11 -1
  142. data/src/core/plugin_registry/grpc_plugin_registry.cc +35 -20
  143. data/src/core/tsi/ssl_transport_security.cc +2 -2
  144. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -2
  145. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -3
  146. data/src/ruby/lib/grpc/version.rb +1 -1
  147. data/third_party/boringssl-with-bazel/err_data.c +465 -463
  148. data/third_party/boringssl-with-bazel/src/crypto/asn1/asn1_lib.c +0 -6
  149. data/third_party/boringssl-with-bazel/src/crypto/dsa/dsa.c +9 -43
  150. data/third_party/boringssl-with-bazel/src/crypto/dsa/dsa_asn1.c +55 -4
  151. data/third_party/boringssl-with-bazel/src/crypto/dsa/internal.h +34 -0
  152. data/third_party/boringssl-with-bazel/src/crypto/evp/evp.c +4 -0
  153. data/third_party/boringssl-with-bazel/src/crypto/evp/p_dsa_asn1.c +6 -2
  154. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/digest.c +2 -0
  155. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/internal.h +4 -0
  156. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa.c +30 -10
  157. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c +10 -15
  158. data/third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c +98 -11
  159. data/third_party/boringssl-with-bazel/src/crypto/hpke/internal.h +51 -6
  160. data/third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h +44 -2
  161. data/third_party/boringssl-with-bazel/src/crypto/trust_token/pmbtoken.c +221 -49
  162. data/third_party/boringssl-with-bazel/src/crypto/trust_token/trust_token.c +64 -20
  163. data/third_party/boringssl-with-bazel/src/crypto/x509/a_strex.c +3 -3
  164. data/third_party/boringssl-with-bazel/src/crypto/x509/algorithm.c +0 -8
  165. data/third_party/boringssl-with-bazel/src/crypto/x509/t_crl.c +3 -3
  166. data/third_party/boringssl-with-bazel/src/crypto/x509/t_x509.c +1 -1
  167. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_cmp.c +7 -2
  168. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c +21 -18
  169. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_obj.c +1 -1
  170. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c +24 -3
  171. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c +3 -3
  172. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_txt.c +67 -67
  173. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_v3.c +3 -3
  174. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_vfy.c +29 -35
  175. data/third_party/boringssl-with-bazel/src/crypto/x509/x509cset.c +13 -2
  176. data/third_party/boringssl-with-bazel/src/crypto/x509/x509name.c +9 -8
  177. data/third_party/boringssl-with-bazel/src/crypto/x509/x_all.c +10 -10
  178. data/third_party/boringssl-with-bazel/src/crypto/x509/x_crl.c +2 -2
  179. data/third_party/boringssl-with-bazel/src/crypto/x509/x_name.c +28 -40
  180. data/third_party/boringssl-with-bazel/src/crypto/x509/x_x509.c +3 -1
  181. data/third_party/boringssl-with-bazel/src/crypto/x509v3/ext_dat.h +1 -4
  182. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_conf.c +7 -3
  183. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_genn.c +2 -2
  184. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_info.c +1 -1
  185. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_purp.c +55 -8
  186. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_skey.c +1 -1
  187. data/third_party/boringssl-with-bazel/src/include/openssl/asn1.h +0 -1
  188. data/third_party/boringssl-with-bazel/src/include/openssl/base.h +1 -1
  189. data/third_party/boringssl-with-bazel/src/include/openssl/cipher.h +6 -0
  190. data/third_party/boringssl-with-bazel/src/include/openssl/crypto.h +1 -1
  191. data/third_party/boringssl-with-bazel/src/include/openssl/dh.h +12 -0
  192. data/third_party/boringssl-with-bazel/src/include/openssl/digest.h +9 -0
  193. data/third_party/boringssl-with-bazel/src/include/openssl/evp.h +4 -1
  194. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +9 -2
  195. data/third_party/boringssl-with-bazel/src/include/openssl/trust_token.h +26 -6
  196. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +188 -78
  197. data/third_party/boringssl-with-bazel/src/include/openssl/x509v3.h +52 -43
  198. data/third_party/boringssl-with-bazel/src/ssl/handshake.cc +18 -18
  199. data/third_party/boringssl-with-bazel/src/ssl/handshake_client.cc +2 -3
  200. data/third_party/boringssl-with-bazel/src/ssl/handshake_server.cc +1 -1
  201. data/third_party/boringssl-with-bazel/src/ssl/internal.h +9 -9
  202. data/third_party/boringssl-with-bazel/src/ssl/ssl_cipher.cc +8 -9
  203. data/third_party/boringssl-with-bazel/src/ssl/tls13_both.cc +1 -2
  204. data/third_party/boringssl-with-bazel/src/ssl/tls13_client.cc +4 -8
  205. data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +2 -2
  206. metadata +72 -42
  207. data/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc +0 -537
  208. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc +0 -1141
  209. data/src/core/ext/upb-generated/gogoproto/gogo.upb.c +0 -17
  210. data/src/core/ext/upb-generated/gogoproto/gogo.upb.h +0 -29
  211. data/src/core/ext/xds/xds_channel.h +0 -46
  212. data/src/core/ext/xds/xds_channel_secure.cc +0 -103
  213. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_pku.c +0 -110
  214. data/third_party/boringssl-with-bazel/src/crypto/x509v3/v3_sxnet.c +0 -274
@@ -36,6 +36,7 @@
36
36
  #include "src/core/ext/xds/xds_client.h"
37
37
  #include "src/core/ext/xds/xds_client_stats.h"
38
38
  #include "src/core/lib/channel/channel_args.h"
39
+ #include "src/core/lib/gpr/string.h"
39
40
  #include "src/core/lib/gprpp/orphanable.h"
40
41
  #include "src/core/lib/gprpp/ref_counted_ptr.h"
41
42
  #include "src/core/lib/iomgr/timer.h"
@@ -53,18 +54,22 @@ namespace {
53
54
 
54
55
  constexpr char kEds[] = "eds_experimental";
55
56
 
57
+ const char* kXdsLocalityNameAttributeKey = "xds_locality_name";
58
+
56
59
  // Config for EDS LB policy.
57
60
  class EdsLbConfig : public LoadBalancingPolicy::Config {
58
61
  public:
59
62
  EdsLbConfig(std::string cluster_name, std::string eds_service_name,
60
63
  absl::optional<std::string> lrs_load_reporting_server_name,
61
- Json locality_picking_policy, Json endpoint_picking_policy)
64
+ Json locality_picking_policy, Json endpoint_picking_policy,
65
+ uint32_t max_concurrent_requests)
62
66
  : cluster_name_(std::move(cluster_name)),
63
67
  eds_service_name_(std::move(eds_service_name)),
64
68
  lrs_load_reporting_server_name_(
65
69
  std::move(lrs_load_reporting_server_name)),
66
70
  locality_picking_policy_(std::move(locality_picking_policy)),
67
- endpoint_picking_policy_(std::move(endpoint_picking_policy)) {}
71
+ endpoint_picking_policy_(std::move(endpoint_picking_policy)),
72
+ max_concurrent_requests_(max_concurrent_requests) {}
68
73
 
69
74
  const char* name() const override { return kEds; }
70
75
 
@@ -79,6 +84,9 @@ class EdsLbConfig : public LoadBalancingPolicy::Config {
79
84
  const Json& endpoint_picking_policy() const {
80
85
  return endpoint_picking_policy_;
81
86
  }
87
+ const uint32_t max_concurrent_requests() const {
88
+ return max_concurrent_requests_;
89
+ }
82
90
 
83
91
  private:
84
92
  std::string cluster_name_;
@@ -86,12 +94,13 @@ class EdsLbConfig : public LoadBalancingPolicy::Config {
86
94
  absl::optional<std::string> lrs_load_reporting_server_name_;
87
95
  Json locality_picking_policy_;
88
96
  Json endpoint_picking_policy_;
97
+ uint32_t max_concurrent_requests_;
89
98
  };
90
99
 
91
100
  // EDS LB policy.
92
101
  class EdsLb : public LoadBalancingPolicy {
93
102
  public:
94
- explicit EdsLb(Args args);
103
+ EdsLb(RefCountedPtr<XdsClient> xds_client, Args args);
95
104
 
96
105
  const char* name() const override { return kEds; }
97
106
 
@@ -99,7 +108,80 @@ class EdsLb : public LoadBalancingPolicy {
99
108
  void ResetBackoffLocked() override;
100
109
 
101
110
  private:
102
- class EndpointWatcher;
111
+ class XdsLocalityAttribute : public ServerAddress::AttributeInterface {
112
+ public:
113
+ explicit XdsLocalityAttribute(RefCountedPtr<XdsLocalityName> locality_name)
114
+ : locality_name_(std::move(locality_name)) {}
115
+
116
+ RefCountedPtr<XdsLocalityName> locality_name() const {
117
+ return locality_name_;
118
+ }
119
+
120
+ std::unique_ptr<AttributeInterface> Copy() const override {
121
+ return absl::make_unique<XdsLocalityAttribute>(locality_name_->Ref());
122
+ }
123
+
124
+ int Cmp(const AttributeInterface* other) const override {
125
+ const auto* other_locality_attr =
126
+ static_cast<const XdsLocalityAttribute*>(other);
127
+ return locality_name_->Compare(*other_locality_attr->locality_name_);
128
+ }
129
+
130
+ std::string ToString() const override {
131
+ return locality_name_->AsHumanReadableString();
132
+ }
133
+
134
+ private:
135
+ RefCountedPtr<XdsLocalityName> locality_name_;
136
+ };
137
+
138
+ class StatsSubchannelWrapper : public DelegatingSubchannel {
139
+ public:
140
+ StatsSubchannelWrapper(
141
+ RefCountedPtr<SubchannelInterface> wrapped_subchannel,
142
+ RefCountedPtr<XdsClusterLocalityStats> locality_stats)
143
+ : DelegatingSubchannel(std::move(wrapped_subchannel)),
144
+ locality_stats_(std::move(locality_stats)) {}
145
+
146
+ XdsClusterLocalityStats* locality_stats() const {
147
+ return locality_stats_.get();
148
+ }
149
+
150
+ private:
151
+ RefCountedPtr<XdsClusterLocalityStats> locality_stats_;
152
+ };
153
+
154
+ class EndpointWatcher : public XdsClient::EndpointWatcherInterface {
155
+ public:
156
+ explicit EndpointWatcher(RefCountedPtr<EdsLb> parent)
157
+ : parent_(std::move(parent)) {}
158
+ void OnEndpointChanged(XdsApi::EdsUpdate update) override {
159
+ new Notifier(parent_, std::move(update));
160
+ }
161
+ void OnError(grpc_error* error) override { new Notifier(parent_, error); }
162
+ void OnResourceDoesNotExist() override { new Notifier(parent_); }
163
+
164
+ private:
165
+ class Notifier {
166
+ public:
167
+ Notifier(RefCountedPtr<EdsLb> parent, XdsApi::EdsUpdate update);
168
+ Notifier(RefCountedPtr<EdsLb> parent, grpc_error* error);
169
+ explicit Notifier(RefCountedPtr<EdsLb> parent);
170
+
171
+ private:
172
+ enum Type { kUpdate, kError, kDoesNotExist };
173
+
174
+ static void RunInExecCtx(void* arg, grpc_error* error);
175
+ void RunInWorkSerializer(grpc_error* error);
176
+
177
+ RefCountedPtr<EdsLb> parent_;
178
+ grpc_closure closure_;
179
+ XdsApi::EdsUpdate update_;
180
+ Type type_;
181
+ };
182
+
183
+ RefCountedPtr<EdsLb> parent_;
184
+ };
103
185
 
104
186
  // A simple wrapper for ref-counting a picker from the child policy.
105
187
  class ChildPickerWrapper : public RefCounted<ChildPickerWrapper> {
@@ -113,16 +195,18 @@ class EdsLb : public LoadBalancingPolicy {
113
195
  };
114
196
 
115
197
  // A picker that handles drops.
116
- class DropPicker : public SubchannelPicker {
198
+ class EdsPicker : public SubchannelPicker {
117
199
  public:
118
- explicit DropPicker(EdsLb* eds_policy);
200
+ explicit EdsPicker(RefCountedPtr<EdsLb> eds_policy);
119
201
 
120
202
  PickResult Pick(PickArgs args) override;
121
203
 
122
204
  private:
123
- RefCountedPtr<XdsApi::DropConfig> drop_config_;
205
+ RefCountedPtr<EdsLb> eds_policy_;
206
+ RefCountedPtr<XdsApi::EdsUpdate::DropConfig> drop_config_;
124
207
  RefCountedPtr<XdsClusterDropStats> drop_stats_;
125
208
  RefCountedPtr<ChildPickerWrapper> child_picker_;
209
+ uint32_t max_concurrent_requests_;
126
210
  };
127
211
 
128
212
  class Helper : public ChannelControlHelper {
@@ -133,7 +217,7 @@ class EdsLb : public LoadBalancingPolicy {
133
217
  ~Helper() { eds_policy_.reset(DEBUG_LOCATION, "Helper"); }
134
218
 
135
219
  RefCountedPtr<SubchannelInterface> CreateSubchannel(
136
- const grpc_channel_args& args) override;
220
+ ServerAddress address, const grpc_channel_args& args) override;
137
221
  void UpdateState(grpc_connectivity_state state, const absl::Status& status,
138
222
  std::unique_ptr<SubchannelPicker> picker) override;
139
223
  // This is a no-op, because we get the addresses from the xds
@@ -150,9 +234,13 @@ class EdsLb : public LoadBalancingPolicy {
150
234
 
151
235
  void ShutdownLocked() override;
152
236
 
237
+ void OnEndpointChanged(XdsApi::EdsUpdate update);
238
+ void OnError(grpc_error* error);
239
+ void OnResourceDoesNotExist();
240
+
153
241
  void MaybeDestroyChildPolicyLocked();
154
242
 
155
- void UpdatePriorityList(XdsApi::PriorityListUpdate priority_list_update);
243
+ void UpdatePriorityList(XdsApi::EdsUpdate::PriorityList priority_list);
156
244
  void UpdateChildPolicyLocked();
157
245
  OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
158
246
  const grpc_channel_args* args);
@@ -160,11 +248,11 @@ class EdsLb : public LoadBalancingPolicy {
160
248
  RefCountedPtr<Config> CreateChildPolicyConfigLocked();
161
249
  grpc_channel_args* CreateChildPolicyArgsLocked(
162
250
  const grpc_channel_args* args_in);
163
- void MaybeUpdateDropPickerLocked();
251
+ void MaybeUpdateEdsPickerLocked();
164
252
 
165
253
  // Caller must ensure that config_ is set before calling.
166
254
  const absl::string_view GetEdsResourceName() const {
167
- if (xds_client_from_channel_ == nullptr) return server_name_;
255
+ if (!is_xds_uri_) return server_name_;
168
256
  if (!config_->eds_service_name().empty()) {
169
257
  return config_->eds_service_name();
170
258
  }
@@ -175,17 +263,13 @@ class EdsLb : public LoadBalancingPolicy {
175
263
  // for LRS load reporting.
176
264
  // Caller must ensure that config_ is set before calling.
177
265
  std::pair<absl::string_view, absl::string_view> GetLrsClusterKey() const {
178
- if (xds_client_from_channel_ == nullptr) return {server_name_, nullptr};
266
+ if (!is_xds_uri_) return {server_name_, nullptr};
179
267
  return {config_->cluster_name(), config_->eds_service_name()};
180
268
  }
181
269
 
182
- XdsClient* xds_client() const {
183
- return xds_client_from_channel_ != nullptr ? xds_client_from_channel_.get()
184
- : xds_client_.get();
185
- }
186
-
187
270
  // Server name from target URI.
188
271
  std::string server_name_;
272
+ bool is_xds_uri_;
189
273
 
190
274
  // Current channel args and config from the resolver.
191
275
  const grpc_channel_args* args_ = nullptr;
@@ -195,21 +279,19 @@ class EdsLb : public LoadBalancingPolicy {
195
279
  bool shutting_down_ = false;
196
280
 
197
281
  // The xds client and endpoint watcher.
198
- // If we get the XdsClient from the channel, we store it in
199
- // xds_client_from_channel_; if we create it ourselves, we store it in
200
- // xds_client_.
201
- RefCountedPtr<XdsClient> xds_client_from_channel_;
202
- OrphanablePtr<XdsClient> xds_client_;
282
+ RefCountedPtr<XdsClient> xds_client_;
203
283
  // A pointer to the endpoint watcher, to be used when cancelling the watch.
204
284
  // Note that this is not owned, so this pointer must never be derefernced.
205
285
  EndpointWatcher* endpoint_watcher_ = nullptr;
206
286
  // The latest data from the endpoint watcher.
207
- XdsApi::PriorityListUpdate priority_list_update_;
287
+ XdsApi::EdsUpdate::PriorityList priority_list_;
208
288
  // State used to retain child policy names for priority policy.
209
289
  std::vector<size_t /*child_number*/> priority_child_numbers_;
210
290
 
211
- RefCountedPtr<XdsApi::DropConfig> drop_config_;
291
+ RefCountedPtr<XdsApi::EdsUpdate::DropConfig> drop_config_;
212
292
  RefCountedPtr<XdsClusterDropStats> drop_stats_;
293
+ // Current concurrent number of requests;
294
+ Atomic<uint32_t> concurrent_requests_{0};
213
295
 
214
296
  OrphanablePtr<LoadBalancingPolicy> child_policy_;
215
297
 
@@ -220,29 +302,34 @@ class EdsLb : public LoadBalancingPolicy {
220
302
  };
221
303
 
222
304
  //
223
- // EdsLb::DropPicker
305
+ // EdsLb::EdsPicker
224
306
  //
225
307
 
226
- EdsLb::DropPicker::DropPicker(EdsLb* eds_policy)
227
- : drop_config_(eds_policy->drop_config_),
228
- drop_stats_(eds_policy->drop_stats_),
229
- child_picker_(eds_policy->child_picker_) {
308
+ EdsLb::EdsPicker::EdsPicker(RefCountedPtr<EdsLb> eds_policy)
309
+ : eds_policy_(std::move(eds_policy)),
310
+ drop_stats_(eds_policy_->drop_stats_),
311
+ child_picker_(eds_policy_->child_picker_),
312
+ max_concurrent_requests_(
313
+ eds_policy_->config_->max_concurrent_requests()) {
230
314
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
231
- gpr_log(GPR_INFO, "[edslb %p] constructed new drop picker %p", eds_policy,
232
- this);
315
+ gpr_log(GPR_INFO, "[edslb %p] constructed new drop picker %p",
316
+ eds_policy_.get(), this);
233
317
  }
234
318
  }
235
319
 
236
- EdsLb::PickResult EdsLb::DropPicker::Pick(PickArgs args) {
237
- // Handle drop.
238
- const std::string* drop_category;
239
- if (drop_config_->ShouldDrop(&drop_category)) {
240
- if (drop_stats_ != nullptr) drop_stats_->AddCallDropped(*drop_category);
320
+ EdsLb::PickResult EdsLb::EdsPicker::Pick(PickArgs args) {
321
+ // Check and see if we exceeded the max concurrent requests count.
322
+ uint32_t current = eds_policy_->concurrent_requests_.FetchAdd(1);
323
+ if (current >= max_concurrent_requests_) {
324
+ eds_policy_->concurrent_requests_.FetchSub(1);
325
+ if (drop_stats_ != nullptr) {
326
+ drop_stats_->AddUncategorizedDrops();
327
+ }
241
328
  PickResult result;
242
329
  result.type = PickResult::PICK_COMPLETE;
243
330
  return result;
244
331
  }
245
- // If we're not dropping all calls, we should always have a child picker.
332
+ // If we're not dropping the call, we should always have a child picker.
246
333
  if (child_picker_ == nullptr) { // Should never happen.
247
334
  PickResult result;
248
335
  result.type = PickResult::PICK_FAILED;
@@ -250,10 +337,56 @@ EdsLb::PickResult EdsLb::DropPicker::Pick(PickArgs args) {
250
337
  grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
251
338
  "eds drop picker not given any child picker"),
252
339
  GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL);
340
+ eds_policy_->concurrent_requests_.FetchSub(1);
253
341
  return result;
254
342
  }
255
343
  // Not dropping, so delegate to child's picker.
256
- return child_picker_->Pick(args);
344
+ PickResult result = child_picker_->Pick(args);
345
+ if (result.type == result.PICK_COMPLETE && result.subchannel != nullptr) {
346
+ XdsClusterLocalityStats* locality_stats = nullptr;
347
+ if (drop_stats_ != nullptr) { // If load reporting is enabled.
348
+ auto* subchannel_wrapper =
349
+ static_cast<StatsSubchannelWrapper*>(result.subchannel.get());
350
+ // Handle load reporting.
351
+ locality_stats = subchannel_wrapper->locality_stats()->Ref().release();
352
+ // Record a call started.
353
+ locality_stats->AddCallStarted();
354
+ // Unwrap subchannel to pass back up the stack.
355
+ result.subchannel = subchannel_wrapper->wrapped_subchannel();
356
+ }
357
+ // Intercept the recv_trailing_metadata op to record call completion.
358
+ EdsLb* eds_policy = static_cast<EdsLb*>(
359
+ eds_policy_->Ref(DEBUG_LOCATION, "DropPickPicker+call").release());
360
+ auto original_recv_trailing_metadata_ready =
361
+ result.recv_trailing_metadata_ready;
362
+ result.recv_trailing_metadata_ready =
363
+ // Note: This callback does not run in either the control plane
364
+ // work serializer or in the data plane mutex.
365
+ [locality_stats, original_recv_trailing_metadata_ready, eds_policy](
366
+ grpc_error* error, MetadataInterface* metadata,
367
+ CallState* call_state) {
368
+ // Record call completion for load reporting.
369
+ if (locality_stats != nullptr) {
370
+ const bool call_failed = error != GRPC_ERROR_NONE;
371
+ locality_stats->AddCallFinished(call_failed);
372
+ locality_stats->Unref(DEBUG_LOCATION, "LocalityStats+call");
373
+ }
374
+ // Decrement number of calls in flight.
375
+ eds_policy->concurrent_requests_.FetchSub(1);
376
+ eds_policy->Unref(DEBUG_LOCATION, "DropPickPicker+call");
377
+ // Invoke the original recv_trailing_metadata_ready callback, if any.
378
+ if (original_recv_trailing_metadata_ready != nullptr) {
379
+ original_recv_trailing_metadata_ready(error, metadata, call_state);
380
+ }
381
+ };
382
+ } else {
383
+ // TODO(roth): We should ideally also record call failures here in the case
384
+ // where a pick fails. This is challenging, because we don't know which
385
+ // picks are for wait_for_ready RPCs or how many times we'll return a
386
+ // failure for the same wait_for_ready RPC.
387
+ eds_policy_->concurrent_requests_.FetchSub(1);
388
+ }
389
+ return result;
257
390
  }
258
391
 
259
392
  //
@@ -261,9 +394,31 @@ EdsLb::PickResult EdsLb::DropPicker::Pick(PickArgs args) {
261
394
  //
262
395
 
263
396
  RefCountedPtr<SubchannelInterface> EdsLb::Helper::CreateSubchannel(
264
- const grpc_channel_args& args) {
397
+ ServerAddress address, const grpc_channel_args& args) {
265
398
  if (eds_policy_->shutting_down_) return nullptr;
266
- return eds_policy_->channel_control_helper()->CreateSubchannel(args);
399
+ // If load reporting is enabled, wrap the subchannel such that it
400
+ // includes the locality stats object, which will be used by the EdsPicker.
401
+ if (eds_policy_->config_->lrs_load_reporting_server_name().has_value()) {
402
+ RefCountedPtr<XdsLocalityName> locality_name;
403
+ auto* attribute = address.GetAttribute(kXdsLocalityNameAttributeKey);
404
+ if (attribute != nullptr) {
405
+ const auto* locality_attr =
406
+ static_cast<const XdsLocalityAttribute*>(attribute);
407
+ locality_name = locality_attr->locality_name();
408
+ }
409
+ RefCountedPtr<XdsClusterLocalityStats> locality_stats =
410
+ eds_policy_->xds_client_->AddClusterLocalityStats(
411
+ *eds_policy_->config_->lrs_load_reporting_server_name(),
412
+ eds_policy_->config_->cluster_name(),
413
+ eds_policy_->config_->eds_service_name(), std::move(locality_name));
414
+ return MakeRefCounted<StatsSubchannelWrapper>(
415
+ eds_policy_->channel_control_helper()->CreateSubchannel(
416
+ std::move(address), args),
417
+ std::move(locality_stats));
418
+ }
419
+ // Load reporting not enabled, so don't wrap the subchannel.
420
+ return eds_policy_->channel_control_helper()->CreateSubchannel(
421
+ std::move(address), args);
267
422
  }
268
423
 
269
424
  void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
@@ -284,8 +439,8 @@ void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
284
439
  eds_policy_->child_status_ = status;
285
440
  eds_policy_->child_picker_ =
286
441
  MakeRefCounted<ChildPickerWrapper>(std::move(picker));
287
- // Wrap the picker in a DropPicker and pass it up.
288
- eds_policy_->MaybeUpdateDropPickerLocked();
442
+ // Wrap the picker in a EdsPicker and pass it up.
443
+ eds_policy_->MaybeUpdateEdsPickerLocked();
289
444
  }
290
445
 
291
446
  void EdsLb::Helper::AddTraceEvent(TraceSeverity severity,
@@ -295,112 +450,94 @@ void EdsLb::Helper::AddTraceEvent(TraceSeverity severity,
295
450
  }
296
451
 
297
452
  //
298
- // EdsLb::EndpointWatcher
453
+ // EdsLb::EndpointWatcher::Notifier
299
454
  //
300
455
 
301
- class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
302
- public:
303
- explicit EndpointWatcher(RefCountedPtr<EdsLb> eds_policy)
304
- : eds_policy_(std::move(eds_policy)) {}
456
+ EdsLb::EndpointWatcher::Notifier::Notifier(RefCountedPtr<EdsLb> parent,
457
+ XdsApi::EdsUpdate update)
458
+ : parent_(std::move(parent)), update_(std::move(update)), type_(kUpdate) {
459
+ GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
460
+ ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
461
+ }
305
462
 
306
- ~EndpointWatcher() { eds_policy_.reset(DEBUG_LOCATION, "EndpointWatcher"); }
463
+ EdsLb::EndpointWatcher::Notifier::Notifier(RefCountedPtr<EdsLb> parent,
464
+ grpc_error* error)
465
+ : parent_(std::move(parent)), type_(kError) {
466
+ GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
467
+ ExecCtx::Run(DEBUG_LOCATION, &closure_, error);
468
+ }
307
469
 
308
- void OnEndpointChanged(XdsApi::EdsUpdate update) override {
309
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
310
- gpr_log(GPR_INFO, "[edslb %p] Received EDS update from xds client",
311
- eds_policy_.get());
312
- }
313
- // Update the drop config.
314
- const bool drop_config_changed =
315
- eds_policy_->drop_config_ == nullptr ||
316
- *eds_policy_->drop_config_ != *update.drop_config;
317
- if (drop_config_changed) {
318
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
319
- gpr_log(GPR_INFO, "[edslb %p] Updating drop config", eds_policy_.get());
320
- }
321
- eds_policy_->drop_config_ = std::move(update.drop_config);
322
- eds_policy_->MaybeUpdateDropPickerLocked();
323
- } else if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
324
- gpr_log(GPR_INFO, "[edslb %p] Drop config unchanged, ignoring",
325
- eds_policy_.get());
326
- }
327
- // Update priority and locality info.
328
- if (eds_policy_->child_policy_ == nullptr ||
329
- eds_policy_->priority_list_update_ != update.priority_list_update) {
330
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
331
- gpr_log(GPR_INFO, "[edslb %p] Updating priority list",
332
- eds_policy_.get());
333
- }
334
- eds_policy_->UpdatePriorityList(std::move(update.priority_list_update));
335
- } else if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
336
- gpr_log(GPR_INFO, "[edslb %p] Priority list unchanged, ignoring",
337
- eds_policy_.get());
338
- }
339
- }
340
-
341
- void OnError(grpc_error* error) override {
342
- gpr_log(GPR_ERROR, "[edslb %p] xds watcher reported error: %s",
343
- eds_policy_.get(), grpc_error_string(error));
344
- // Go into TRANSIENT_FAILURE if we have not yet created the child
345
- // policy (i.e., we have not yet received data from xds). Otherwise,
346
- // we keep running with the data we had previously.
347
- if (eds_policy_->child_policy_ == nullptr) {
348
- eds_policy_->channel_control_helper()->UpdateState(
349
- GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
350
- absl::make_unique<TransientFailurePicker>(error));
351
- } else {
352
- GRPC_ERROR_UNREF(error);
353
- }
354
- }
470
+ EdsLb::EndpointWatcher::Notifier::Notifier(RefCountedPtr<EdsLb> parent)
471
+ : parent_(std::move(parent)), type_(kDoesNotExist) {
472
+ GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
473
+ ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
474
+ }
355
475
 
356
- void OnResourceDoesNotExist() override {
357
- gpr_log(
358
- GPR_ERROR,
359
- "[edslb %p] EDS resource does not exist -- reporting TRANSIENT_FAILURE",
360
- eds_policy_.get());
361
- grpc_error* error = grpc_error_set_int(
362
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("EDS resource does not exist"),
363
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
364
- eds_policy_->channel_control_helper()->UpdateState(
365
- GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
366
- absl::make_unique<TransientFailurePicker>(error));
367
- eds_policy_->MaybeDestroyChildPolicyLocked();
368
- }
476
+ void EdsLb::EndpointWatcher::Notifier::RunInExecCtx(void* arg,
477
+ grpc_error* error) {
478
+ Notifier* self = static_cast<Notifier*>(arg);
479
+ GRPC_ERROR_REF(error);
480
+ self->parent_->work_serializer()->Run(
481
+ [self, error]() { self->RunInWorkSerializer(error); }, DEBUG_LOCATION);
482
+ }
369
483
 
370
- private:
371
- RefCountedPtr<EdsLb> eds_policy_;
372
- };
484
+ void EdsLb::EndpointWatcher::Notifier::RunInWorkSerializer(grpc_error* error) {
485
+ switch (type_) {
486
+ case kUpdate:
487
+ parent_->OnEndpointChanged(std::move(update_));
488
+ break;
489
+ case kError:
490
+ parent_->OnError(error);
491
+ break;
492
+ case kDoesNotExist:
493
+ parent_->OnResourceDoesNotExist();
494
+ break;
495
+ };
496
+ delete this;
497
+ }
373
498
 
374
499
  //
375
500
  // EdsLb public methods
376
501
  //
377
502
 
378
- EdsLb::EdsLb(Args args)
379
- : LoadBalancingPolicy(std::move(args)),
380
- xds_client_from_channel_(XdsClient::GetFromChannelArgs(*args.args)) {
503
+ EdsLb::EdsLb(RefCountedPtr<XdsClient> xds_client, Args args)
504
+ : LoadBalancingPolicy(std::move(args)), xds_client_(std::move(xds_client)) {
381
505
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
382
- gpr_log(GPR_INFO, "[edslb %p] created -- xds client from channel: %p", this,
383
- xds_client_from_channel_.get());
506
+ gpr_log(GPR_INFO, "[edslb %p] created -- using xds client %p", this,
507
+ xds_client_.get());
384
508
  }
385
509
  // Record server name.
386
- const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI);
387
- const char* server_uri = grpc_channel_arg_get_string(arg);
510
+ const char* server_uri =
511
+ grpc_channel_args_find_string(args.args, GRPC_ARG_SERVER_URI);
388
512
  GPR_ASSERT(server_uri != nullptr);
389
513
  grpc_uri* uri = grpc_uri_parse(server_uri, true);
390
514
  GPR_ASSERT(uri->path[0] != '\0');
391
515
  server_name_ = uri->path[0] == '/' ? uri->path + 1 : uri->path;
516
+ is_xds_uri_ = strcmp(uri->scheme, "xds") == 0;
392
517
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
393
- gpr_log(GPR_INFO, "[edslb %p] server name from channel: %s", this,
394
- server_name_.c_str());
518
+ gpr_log(GPR_INFO, "[edslb %p] server name from channel (is_xds_uri=%d): %s",
519
+ this, is_xds_uri_, server_name_.c_str());
395
520
  }
396
521
  grpc_uri_destroy(uri);
522
+ // EDS-only flow.
523
+ if (!is_xds_uri_) {
524
+ // Setup channelz linkage.
525
+ channelz::ChannelNode* parent_channelz_node =
526
+ grpc_channel_args_find_pointer<channelz::ChannelNode>(
527
+ args.args, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
528
+ if (parent_channelz_node != nullptr) {
529
+ xds_client_->AddChannelzLinkage(parent_channelz_node);
530
+ }
531
+ // Couple polling.
532
+ grpc_pollset_set_add_pollset_set(xds_client_->interested_parties(),
533
+ interested_parties());
534
+ }
397
535
  }
398
536
 
399
537
  EdsLb::~EdsLb() {
400
538
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
401
- gpr_log(GPR_INFO, "[edslb %p] destroying xds LB policy", this);
539
+ gpr_log(GPR_INFO, "[edslb %p] destroying eds LB policy", this);
402
540
  }
403
- grpc_channel_args_destroy(args_);
404
541
  }
405
542
 
406
543
  void EdsLb::ShutdownLocked() {
@@ -413,22 +550,31 @@ void EdsLb::ShutdownLocked() {
413
550
  child_picker_.reset();
414
551
  MaybeDestroyChildPolicyLocked();
415
552
  drop_stats_.reset();
416
- // Cancel the endpoint watch here instead of in our dtor if we are using the
417
- // xds resolver, because the watcher holds a ref to us and we might not be
418
- // destroying the XdsClient, leading to a situation where this LB policy is
419
- // never destroyed.
420
- if (xds_client_from_channel_ != nullptr) {
421
- if (config_ != nullptr) {
422
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
423
- gpr_log(GPR_INFO, "[edslb %p] cancelling xds watch for %s", this,
424
- std::string(GetEdsResourceName()).c_str());
425
- }
426
- xds_client()->CancelEndpointDataWatch(GetEdsResourceName(),
427
- endpoint_watcher_);
553
+ // Cancel watcher.
554
+ if (endpoint_watcher_ != nullptr) {
555
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
556
+ gpr_log(GPR_INFO, "[edslb %p] cancelling xds watch for %s", this,
557
+ std::string(GetEdsResourceName()).c_str());
428
558
  }
429
- xds_client_from_channel_.reset();
559
+ xds_client_->CancelEndpointDataWatch(GetEdsResourceName(),
560
+ endpoint_watcher_);
430
561
  }
431
- xds_client_.reset();
562
+ if (!is_xds_uri_) {
563
+ // Remove channelz linkage.
564
+ channelz::ChannelNode* parent_channelz_node =
565
+ grpc_channel_args_find_pointer<channelz::ChannelNode>(
566
+ args_, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
567
+ if (parent_channelz_node != nullptr) {
568
+ xds_client_->RemoveChannelzLinkage(parent_channelz_node);
569
+ }
570
+ // Decouple polling.
571
+ grpc_pollset_set_del_pollset_set(xds_client_->interested_parties(),
572
+ interested_parties());
573
+ }
574
+ xds_client_.reset(DEBUG_LOCATION, "EdsLb");
575
+ // Destroy channel args.
576
+ grpc_channel_args_destroy(args_);
577
+ args_ = nullptr;
432
578
  }
433
579
 
434
580
  void EdsLb::MaybeDestroyChildPolicyLocked() {
@@ -451,33 +597,24 @@ void EdsLb::UpdateLocked(UpdateArgs args) {
451
597
  grpc_channel_args_destroy(args_);
452
598
  args_ = args.args;
453
599
  args.args = nullptr;
454
- if (is_initial_update) {
455
- // Initialize XdsClient.
456
- if (xds_client_from_channel_ == nullptr) {
457
- grpc_error* error = GRPC_ERROR_NONE;
458
- xds_client_ = MakeOrphanable<XdsClient>(
459
- work_serializer(), interested_parties(), GetEdsResourceName(),
460
- nullptr /* service config watcher */, *args_, &error);
461
- // TODO(roth): If we decide that we care about EDS-only mode, add
462
- // proper error handling here.
463
- GPR_ASSERT(error == GRPC_ERROR_NONE);
464
- if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
465
- gpr_log(GPR_INFO, "[edslb %p] Created xds client %p", this,
466
- xds_client_.get());
467
- }
468
- }
469
- }
600
+ const bool lrs_server_changed =
601
+ is_initial_update || config_->lrs_load_reporting_server_name() !=
602
+ old_config->lrs_load_reporting_server_name();
603
+ const bool max_concurrent_requests_changed =
604
+ is_initial_update || config_->max_concurrent_requests() !=
605
+ old_config->max_concurrent_requests();
470
606
  // Update drop stats for load reporting if needed.
471
- if (is_initial_update || config_->lrs_load_reporting_server_name() !=
472
- old_config->lrs_load_reporting_server_name()) {
607
+ if (lrs_server_changed) {
473
608
  drop_stats_.reset();
474
609
  if (config_->lrs_load_reporting_server_name().has_value()) {
475
610
  const auto key = GetLrsClusterKey();
476
- drop_stats_ = xds_client()->AddClusterDropStats(
611
+ drop_stats_ = xds_client_->AddClusterDropStats(
477
612
  config_->lrs_load_reporting_server_name().value(),
478
613
  key.first /*cluster_name*/, key.second /*eds_service_name*/);
479
614
  }
480
- MaybeUpdateDropPickerLocked();
615
+ }
616
+ if (lrs_server_changed || max_concurrent_requests_changed) {
617
+ MaybeUpdateEdsPickerLocked();
481
618
  }
482
619
  // Update child policy if needed.
483
620
  // Note that this comes after updating drop_stats_, since we want that
@@ -492,53 +629,89 @@ void EdsLb::UpdateLocked(UpdateArgs args) {
492
629
  auto watcher = absl::make_unique<EndpointWatcher>(
493
630
  Ref(DEBUG_LOCATION, "EndpointWatcher"));
494
631
  endpoint_watcher_ = watcher.get();
495
- xds_client()->WatchEndpointData(GetEdsResourceName(), std::move(watcher));
632
+ xds_client_->WatchEndpointData(GetEdsResourceName(), std::move(watcher));
496
633
  }
497
634
  }
498
635
 
499
636
  void EdsLb::ResetBackoffLocked() {
500
637
  // When the XdsClient is instantiated in the resolver instead of in this
501
- // LB policy, this is done via the resolver, so we don't need to do it
502
- // for xds_client_from_channel_ here.
503
- if (xds_client_ != nullptr) xds_client_->ResetBackoff();
638
+ // LB policy, this is done via the resolver, so we don't need to do it here.
639
+ if (!is_xds_uri_ && xds_client_ != nullptr) xds_client_->ResetBackoff();
504
640
  if (child_policy_ != nullptr) {
505
641
  child_policy_->ResetBackoffLocked();
506
642
  }
507
643
  }
508
644
 
645
+ void EdsLb::OnEndpointChanged(XdsApi::EdsUpdate update) {
646
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
647
+ gpr_log(GPR_INFO, "[edslb %p] Received EDS update from xds client", this);
648
+ }
649
+ // Update the drop config.
650
+ drop_config_ = std::move(update.drop_config);
651
+ // If priority list is empty, add a single priority, just so that we
652
+ // have a child in which to create the eds_drop policy.
653
+ if (update.priorities.empty()) update.priorities.emplace_back();
654
+ // Update child policy.
655
+ UpdatePriorityList(std::move(update.priorities));
656
+ }
657
+
658
+ void EdsLb::OnError(grpc_error* error) {
659
+ gpr_log(GPR_ERROR, "[edslb %p] xds watcher reported error: %s", this,
660
+ grpc_error_string(error));
661
+ // Go into TRANSIENT_FAILURE if we have not yet created the child
662
+ // policy (i.e., we have not yet received data from xds). Otherwise,
663
+ // we keep running with the data we had previously.
664
+ if (child_policy_ == nullptr) {
665
+ channel_control_helper()->UpdateState(
666
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
667
+ absl::make_unique<TransientFailurePicker>(error));
668
+ } else {
669
+ GRPC_ERROR_UNREF(error);
670
+ }
671
+ }
672
+
673
+ void EdsLb::OnResourceDoesNotExist() {
674
+ gpr_log(
675
+ GPR_ERROR,
676
+ "[edslb %p] EDS resource does not exist -- reporting TRANSIENT_FAILURE",
677
+ this);
678
+ grpc_error* error = grpc_error_set_int(
679
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("EDS resource does not exist"),
680
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
681
+ channel_control_helper()->UpdateState(
682
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
683
+ absl::make_unique<TransientFailurePicker>(error));
684
+ MaybeDestroyChildPolicyLocked();
685
+ }
686
+
509
687
  //
510
688
  // child policy-related methods
511
689
  //
512
690
 
513
- void EdsLb::UpdatePriorityList(
514
- XdsApi::PriorityListUpdate priority_list_update) {
691
+ void EdsLb::UpdatePriorityList(XdsApi::EdsUpdate::PriorityList priority_list) {
515
692
  // Build some maps from locality to child number and the reverse from
516
- // the old data in priority_list_update_ and priority_child_numbers_.
693
+ // the old data in priority_list_ and priority_child_numbers_.
517
694
  std::map<XdsLocalityName*, size_t /*child_number*/, XdsLocalityName::Less>
518
695
  locality_child_map;
519
696
  std::map<size_t, std::set<XdsLocalityName*>> child_locality_map;
520
- for (uint32_t priority = 0; priority < priority_list_update_.size();
521
- ++priority) {
522
- auto* locality_map = priority_list_update_.Find(priority);
523
- GPR_ASSERT(locality_map != nullptr);
697
+ for (size_t priority = 0; priority < priority_list_.size(); ++priority) {
524
698
  size_t child_number = priority_child_numbers_[priority];
525
- for (const auto& p : locality_map->localities) {
526
- XdsLocalityName* locality_name = p.first.get();
699
+ const auto& localities = priority_list_[priority].localities;
700
+ for (const auto& p : localities) {
701
+ XdsLocalityName* locality_name = p.first;
527
702
  locality_child_map[locality_name] = child_number;
528
703
  child_locality_map[child_number].insert(locality_name);
529
704
  }
530
705
  }
531
706
  // Construct new list of children.
532
707
  std::vector<size_t> priority_child_numbers;
533
- for (uint32_t priority = 0; priority < priority_list_update.size();
534
- ++priority) {
535
- auto* locality_map = priority_list_update.Find(priority);
536
- GPR_ASSERT(locality_map != nullptr);
708
+ for (size_t priority = 0; priority < priority_list.size(); ++priority) {
709
+ const auto& localities = priority_list[priority].localities;
537
710
  absl::optional<size_t> child_number;
538
711
  // If one of the localities in this priority already existed, reuse its
539
712
  // child number.
540
- for (const auto& p : locality_map->localities) {
541
- XdsLocalityName* locality_name = p.first.get();
713
+ for (const auto& p : localities) {
714
+ XdsLocalityName* locality_name = p.first;
542
715
  if (!child_number.has_value()) {
543
716
  auto it = locality_child_map.find(locality_name);
544
717
  if (it != locality_child_map.end()) {
@@ -572,7 +745,7 @@ void EdsLb::UpdatePriorityList(
572
745
  priority_child_numbers.push_back(*child_number);
573
746
  }
574
747
  // Save update.
575
- priority_list_update_ = std::move(priority_list_update);
748
+ priority_list_ = std::move(priority_list);
576
749
  priority_child_numbers_ = std::move(priority_child_numbers);
577
750
  // Update child policy.
578
751
  UpdateChildPolicyLocked();
@@ -580,23 +753,23 @@ void EdsLb::UpdatePriorityList(
580
753
 
581
754
  ServerAddressList EdsLb::CreateChildPolicyAddressesLocked() {
582
755
  ServerAddressList addresses;
583
- for (uint32_t priority = 0; priority < priority_list_update_.size();
584
- ++priority) {
756
+ for (size_t priority = 0; priority < priority_list_.size(); ++priority) {
757
+ const auto& localities = priority_list_[priority].localities;
585
758
  std::string priority_child_name =
586
759
  absl::StrCat("child", priority_child_numbers_[priority]);
587
- const auto* locality_map = priority_list_update_.Find(priority);
588
- GPR_ASSERT(locality_map != nullptr);
589
- for (const auto& p : locality_map->localities) {
760
+ for (const auto& p : localities) {
590
761
  const auto& locality_name = p.first;
591
762
  const auto& locality = p.second;
592
763
  std::vector<std::string> hierarchical_path = {
593
764
  priority_child_name, locality_name->AsHumanReadableString()};
594
- for (size_t i = 0; i < locality.serverlist.size(); ++i) {
595
- const ServerAddress& address = locality.serverlist[i];
596
- grpc_arg new_arg = MakeHierarchicalPathArg(hierarchical_path);
597
- grpc_channel_args* args =
598
- grpc_channel_args_copy_and_add(address.args(), &new_arg, 1);
599
- addresses.emplace_back(address.address(), args);
765
+ for (const auto& endpoint : locality.endpoints) {
766
+ addresses.emplace_back(
767
+ endpoint
768
+ .WithAttribute(kHierarchicalPathAttributeKey,
769
+ MakeHierarchicalPathAttribute(hierarchical_path))
770
+ .WithAttribute(kXdsLocalityNameAttributeKey,
771
+ absl::make_unique<XdsLocalityAttribute>(
772
+ locality_name->Ref())));
600
773
  }
601
774
  }
602
775
  }
@@ -605,15 +778,14 @@ ServerAddressList EdsLb::CreateChildPolicyAddressesLocked() {
605
778
 
606
779
  RefCountedPtr<LoadBalancingPolicy::Config>
607
780
  EdsLb::CreateChildPolicyConfigLocked() {
781
+ const auto lrs_key = GetLrsClusterKey();
608
782
  Json::Object priority_children;
609
783
  Json::Array priority_priorities;
610
- for (uint32_t priority = 0; priority < priority_list_update_.size();
611
- ++priority) {
612
- const auto* locality_map = priority_list_update_.Find(priority);
613
- GPR_ASSERT(locality_map != nullptr);
784
+ for (size_t priority = 0; priority < priority_list_.size(); ++priority) {
785
+ const auto& localities = priority_list_[priority].localities;
614
786
  Json::Object weighted_targets;
615
- for (const auto& p : locality_map->localities) {
616
- XdsLocalityName* locality_name = p.first.get();
787
+ for (const auto& p : localities) {
788
+ XdsLocalityName* locality_name = p.first;
617
789
  const auto& locality = p.second;
618
790
  // Construct JSON object containing locality name.
619
791
  Json::Object locality_name_json;
@@ -626,45 +798,49 @@ EdsLb::CreateChildPolicyConfigLocked() {
626
798
  if (!locality_name->sub_zone().empty()) {
627
799
  locality_name_json["subzone"] = locality_name->sub_zone();
628
800
  }
629
- // Construct endpoint-picking policy.
630
- // Wrap it in the LRS policy if load reporting is enabled.
631
- Json endpoint_picking_policy;
632
- if (config_->lrs_load_reporting_server_name().has_value()) {
633
- const auto key = GetLrsClusterKey();
634
- Json::Object lrs_config = {
635
- {"clusterName", std::string(key.first)},
636
- {"locality", std::move(locality_name_json)},
637
- {"lrsLoadReportingServerName",
638
- config_->lrs_load_reporting_server_name().value()},
639
- {"childPolicy", config_->endpoint_picking_policy()},
640
- };
641
- if (!key.second.empty()) {
642
- lrs_config["edsServiceName"] = std::string(key.second);
643
- }
644
- endpoint_picking_policy = Json::Array{Json::Object{
645
- {"lrs_experimental", std::move(lrs_config)},
646
- }};
647
- } else {
648
- endpoint_picking_policy = config_->endpoint_picking_policy();
649
- }
650
801
  // Add weighted target entry.
651
802
  weighted_targets[locality_name->AsHumanReadableString()] = Json::Object{
652
803
  {"weight", locality.lb_weight},
653
- {"childPolicy", std::move(endpoint_picking_policy)},
804
+ {"childPolicy", config_->endpoint_picking_policy()},
654
805
  };
655
806
  }
656
- // Add priority entry.
657
- const size_t child_number = priority_child_numbers_[priority];
658
- std::string child_name = absl::StrCat("child", child_number);
659
- priority_priorities.emplace_back(child_name);
807
+ // Construct locality-picking policy.
808
+ // Start with field from our config and add the "targets" field.
660
809
  Json locality_picking_config = config_->locality_picking_policy();
661
810
  Json::Object& config =
662
811
  *(*locality_picking_config.mutable_array())[0].mutable_object();
663
812
  auto it = config.begin();
664
813
  GPR_ASSERT(it != config.end());
665
814
  (*it->second.mutable_object())["targets"] = std::move(weighted_targets);
815
+ // Wrap it in the drop policy.
816
+ Json::Array drop_categories;
817
+ for (const auto& category : drop_config_->drop_category_list()) {
818
+ drop_categories.push_back(Json::Object{
819
+ {"category", category.name},
820
+ {"requests_per_million", category.parts_per_million},
821
+ });
822
+ }
823
+ Json::Object eds_drop_config = {
824
+ {"clusterName", std::string(lrs_key.first)},
825
+ {"childPolicy", std::move(locality_picking_config)},
826
+ {"dropCategories", std::move(drop_categories)},
827
+ };
828
+ if (!lrs_key.second.empty()) {
829
+ eds_drop_config["edsServiceName"] = std::string(lrs_key.second);
830
+ }
831
+ if (config_->lrs_load_reporting_server_name().has_value()) {
832
+ eds_drop_config["lrsLoadReportingServerName"] =
833
+ config_->lrs_load_reporting_server_name().value();
834
+ }
835
+ Json locality_picking_policy = Json::Array{Json::Object{
836
+ {"eds_drop_experimental", std::move(eds_drop_config)},
837
+ }};
838
+ // Add priority entry.
839
+ const size_t child_number = priority_child_numbers_[priority];
840
+ std::string child_name = absl::StrCat("child", child_number);
841
+ priority_priorities.emplace_back(child_name);
666
842
  priority_children[child_name] = Json::Object{
667
- {"config", std::move(locality_picking_config)},
843
+ {"config", std::move(locality_picking_policy)},
668
844
  };
669
845
  }
670
846
  Json json = Json::Array{Json::Object{
@@ -722,9 +898,11 @@ void EdsLb::UpdateChildPolicyLocked() {
722
898
 
723
899
  grpc_channel_args* EdsLb::CreateChildPolicyArgsLocked(
724
900
  const grpc_channel_args* args) {
725
- absl::InlinedVector<grpc_arg, 3> args_to_add = {
901
+ grpc_arg args_to_add[] = {
726
902
  // A channel arg indicating if the target is a backend inferred from an
727
903
  // xds load balancer.
904
+ // TODO(roth): This isn't needed with the new fallback design.
905
+ // Remove as part of implementing the new fallback functionality.
728
906
  grpc_channel_arg_integer_create(
729
907
  const_cast<char*>(GRPC_ARG_ADDRESS_IS_BACKEND_FROM_XDS_LOAD_BALANCER),
730
908
  1),
@@ -733,18 +911,8 @@ grpc_channel_args* EdsLb::CreateChildPolicyArgsLocked(
733
911
  grpc_channel_arg_integer_create(
734
912
  const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1),
735
913
  };
736
- absl::InlinedVector<const char*, 1> args_to_remove;
737
- if (xds_client_from_channel_ == nullptr) {
738
- args_to_add.emplace_back(xds_client_->MakeChannelArg());
739
- } else if (!config_->lrs_load_reporting_server_name().has_value()) {
740
- // Remove XdsClient from channel args, so that its presence doesn't
741
- // prevent us from sharing subchannels between channels.
742
- // If load reporting is enabled, this happens in the LRS policy instead.
743
- args_to_remove.push_back(GRPC_ARG_XDS_CLIENT);
744
- }
745
- return grpc_channel_args_copy_and_add_and_remove(
746
- args, args_to_remove.data(), args_to_remove.size(), args_to_add.data(),
747
- args_to_add.size());
914
+ return grpc_channel_args_copy_and_add(args, args_to_add,
915
+ GPR_ARRAY_SIZE(args_to_add));
748
916
  }
749
917
 
750
918
  OrphanablePtr<LoadBalancingPolicy> EdsLb::CreateChildPolicyLocked(
@@ -773,18 +941,12 @@ OrphanablePtr<LoadBalancingPolicy> EdsLb::CreateChildPolicyLocked(
773
941
  return lb_policy;
774
942
  }
775
943
 
776
- void EdsLb::MaybeUpdateDropPickerLocked() {
777
- // If we're dropping all calls, report READY, regardless of what (or
778
- // whether) the child has reported.
779
- if (drop_config_ != nullptr && drop_config_->drop_all()) {
780
- channel_control_helper()->UpdateState(GRPC_CHANNEL_READY, absl::Status(),
781
- absl::make_unique<DropPicker>(this));
782
- return;
783
- }
944
+ void EdsLb::MaybeUpdateEdsPickerLocked() {
784
945
  // Update only if we have a child picker.
785
946
  if (child_picker_ != nullptr) {
786
- channel_control_helper()->UpdateState(child_state_, child_status_,
787
- absl::make_unique<DropPicker>(this));
947
+ channel_control_helper()->UpdateState(
948
+ child_state_, child_status_,
949
+ absl::make_unique<EdsPicker>(Ref(DEBUG_LOCATION, "EdsPicker")));
788
950
  }
789
951
  }
790
952
 
@@ -796,7 +958,17 @@ class EdsLbFactory : public LoadBalancingPolicyFactory {
796
958
  public:
797
959
  OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
798
960
  LoadBalancingPolicy::Args args) const override {
799
- return MakeOrphanable<EdsChildHandler>(std::move(args), &grpc_lb_eds_trace);
961
+ grpc_error* error = GRPC_ERROR_NONE;
962
+ RefCountedPtr<XdsClient> xds_client = XdsClient::GetOrCreate(&error);
963
+ if (error != GRPC_ERROR_NONE) {
964
+ gpr_log(GPR_ERROR,
965
+ "cannot get XdsClient to instantiate eds LB policy: %s",
966
+ grpc_error_string(error));
967
+ GRPC_ERROR_UNREF(error);
968
+ return nullptr;
969
+ }
970
+ return MakeOrphanable<EdsChildHandler>(std::move(xds_client),
971
+ std::move(args));
800
972
  }
801
973
 
802
974
  const char* name() const override { return kEds; }
@@ -890,13 +1062,25 @@ class EdsLbFactory : public LoadBalancingPolicyFactory {
890
1062
  "endpointPickingPolicy", &parse_error, 1));
891
1063
  GRPC_ERROR_UNREF(parse_error);
892
1064
  }
1065
+ // Max concurrent requests.
1066
+ uint32_t max_concurrent_requests = 1024;
1067
+ it = json.object_value().find("max_concurrent_requests");
1068
+ if (it != json.object_value().end()) {
1069
+ if (it->second.type() != Json::Type::NUMBER) {
1070
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1071
+ "field:max_concurrent_requests error:must be of type number"));
1072
+ } else {
1073
+ max_concurrent_requests =
1074
+ gpr_parse_nonnegative_int(it->second.string_value().c_str());
1075
+ }
1076
+ }
893
1077
  // Construct config.
894
1078
  if (error_list.empty()) {
895
1079
  return MakeRefCounted<EdsLbConfig>(
896
1080
  std::move(cluster_name), std::move(eds_service_name),
897
1081
  std::move(lrs_load_reporting_server_name),
898
1082
  std::move(locality_picking_policy),
899
- std::move(endpoint_picking_policy));
1083
+ std::move(endpoint_picking_policy), max_concurrent_requests);
900
1084
  } else {
901
1085
  *error = GRPC_ERROR_CREATE_FROM_VECTOR(
902
1086
  "eds_experimental LB policy config", &error_list);
@@ -907,8 +1091,9 @@ class EdsLbFactory : public LoadBalancingPolicyFactory {
907
1091
  private:
908
1092
  class EdsChildHandler : public ChildPolicyHandler {
909
1093
  public:
910
- EdsChildHandler(Args args, TraceFlag* tracer)
911
- : ChildPolicyHandler(std::move(args), tracer) {}
1094
+ EdsChildHandler(RefCountedPtr<XdsClient> xds_client, Args args)
1095
+ : ChildPolicyHandler(std::move(args), &grpc_lb_eds_trace),
1096
+ xds_client_(std::move(xds_client)) {}
912
1097
 
913
1098
  bool ConfigChangeRequiresNewPolicyInstance(
914
1099
  LoadBalancingPolicy::Config* old_config,
@@ -919,13 +1104,18 @@ class EdsLbFactory : public LoadBalancingPolicyFactory {
919
1104
  EdsLbConfig* new_eds_config = static_cast<EdsLbConfig*>(new_config);
920
1105
  return old_eds_config->cluster_name() != new_eds_config->cluster_name() ||
921
1106
  old_eds_config->eds_service_name() !=
922
- new_eds_config->eds_service_name();
1107
+ new_eds_config->eds_service_name() ||
1108
+ old_eds_config->lrs_load_reporting_server_name() !=
1109
+ new_eds_config->lrs_load_reporting_server_name();
923
1110
  }
924
1111
 
925
1112
  OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
926
1113
  const char* name, LoadBalancingPolicy::Args args) const override {
927
- return MakeOrphanable<EdsLb>(std::move(args));
1114
+ return MakeOrphanable<EdsLb>(xds_client_, std::move(args));
928
1115
  }
1116
+
1117
+ private:
1118
+ RefCountedPtr<XdsClient> xds_client_;
929
1119
  };
930
1120
  };
931
1121