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
@@ -147,8 +147,56 @@ class XdsApi {
147
147
  return virtual_hosts == other.virtual_hosts;
148
148
  }
149
149
  std::string ToString() const;
150
- const VirtualHost* FindVirtualHostForDomain(
151
- const std::string& domain) const;
150
+ VirtualHost* FindVirtualHostForDomain(const std::string& domain);
151
+ };
152
+
153
+ struct StringMatcher {
154
+ enum class StringMatcherType {
155
+ EXACT, // value stored in string_matcher_field
156
+ PREFIX, // value stored in string_matcher_field
157
+ SUFFIX, // value stored in string_matcher_field
158
+ SAFE_REGEX, // use regex_match field
159
+ CONTAINS, // value stored in string_matcher_field
160
+ };
161
+ StringMatcherType type;
162
+ std::string string_matcher;
163
+ std::unique_ptr<RE2> regex_match;
164
+ bool ignore_case;
165
+
166
+ StringMatcher() = default;
167
+ StringMatcher(const StringMatcher& other);
168
+ StringMatcher& operator=(const StringMatcher& other);
169
+ bool operator==(const StringMatcher& other) const;
170
+ };
171
+
172
+ struct CommonTlsContext {
173
+ struct CertificateValidationContext {
174
+ std::vector<StringMatcher> match_subject_alt_names;
175
+
176
+ bool operator==(const CertificateValidationContext& other) const {
177
+ return match_subject_alt_names == other.match_subject_alt_names;
178
+ }
179
+ };
180
+
181
+ struct CombinedCertificateValidationContext {
182
+ CertificateValidationContext default_validation_context;
183
+ std::string validation_context_certificate_provider_instance;
184
+
185
+ bool operator==(const CombinedCertificateValidationContext& other) const {
186
+ return default_validation_context == other.default_validation_context &&
187
+ validation_context_certificate_provider_instance ==
188
+ other.validation_context_certificate_provider_instance;
189
+ }
190
+ };
191
+
192
+ std::string tls_certificate_certificate_provider_instance;
193
+ CombinedCertificateValidationContext combined_validation_context;
194
+
195
+ bool operator==(const CommonTlsContext& other) const {
196
+ return tls_certificate_certificate_provider_instance ==
197
+ other.tls_certificate_certificate_provider_instance &&
198
+ combined_validation_context == other.combined_validation_context;
199
+ }
152
200
  };
153
201
 
154
202
  // TODO(roth): When we can use absl::variant<>, consider using that
@@ -174,125 +222,114 @@ class XdsApi {
174
222
  // The name to use in the EDS request.
175
223
  // If empty, the cluster name will be used.
176
224
  std::string eds_service_name;
225
+ // Tls Context used by clients
226
+ CommonTlsContext common_tls_context;
177
227
  // The LRS server to use for load reporting.
178
228
  // If not set, load reporting will be disabled.
179
229
  // If set to the empty string, will use the same server we obtained the CDS
180
230
  // data from.
181
231
  absl::optional<std::string> lrs_load_reporting_server_name;
232
+ // Maximum number of outstanding requests can be made to the upstream
233
+ // cluster.
234
+ uint32_t max_concurrent_requests = 1024;
235
+
236
+ bool operator==(const CdsUpdate& other) const {
237
+ return eds_service_name == other.eds_service_name &&
238
+ common_tls_context == other.common_tls_context &&
239
+ lrs_load_reporting_server_name ==
240
+ other.lrs_load_reporting_server_name &&
241
+ max_concurrent_requests == other.max_concurrent_requests;
242
+ }
182
243
  };
183
244
 
184
245
  using CdsUpdateMap = std::map<std::string /*cluster_name*/, CdsUpdate>;
185
246
 
186
- class PriorityListUpdate {
187
- public:
188
- struct LocalityMap {
247
+ struct EdsUpdate {
248
+ struct Priority {
189
249
  struct Locality {
190
- bool operator==(const Locality& other) const {
191
- return *name == *other.name && serverlist == other.serverlist &&
192
- lb_weight == other.lb_weight && priority == other.priority;
193
- }
194
-
195
- // This comparator only compares the locality names.
196
- struct Less {
197
- bool operator()(const Locality& lhs, const Locality& rhs) const {
198
- return XdsLocalityName::Less()(lhs.name, rhs.name);
199
- }
200
- };
201
-
202
250
  RefCountedPtr<XdsLocalityName> name;
203
- ServerAddressList serverlist;
204
251
  uint32_t lb_weight;
205
- uint32_t priority;
206
- };
252
+ ServerAddressList endpoints;
207
253
 
208
- bool Contains(const RefCountedPtr<XdsLocalityName>& name) const {
209
- return localities.find(name) != localities.end();
210
- }
254
+ bool operator==(const Locality& other) const {
255
+ return *name == *other.name && lb_weight == other.lb_weight &&
256
+ endpoints == other.endpoints;
257
+ }
258
+ bool operator!=(const Locality& other) const {
259
+ return !(*this == other);
260
+ }
261
+ std::string ToString() const;
262
+ };
211
263
 
212
- size_t size() const { return localities.size(); }
264
+ std::map<XdsLocalityName*, Locality, XdsLocalityName::Less> localities;
213
265
 
214
- std::map<RefCountedPtr<XdsLocalityName>, Locality, XdsLocalityName::Less>
215
- localities;
266
+ bool operator==(const Priority& other) const;
267
+ std::string ToString() const;
216
268
  };
269
+ using PriorityList = absl::InlinedVector<Priority, 2>;
270
+
271
+ // There are two phases of accessing this class's content:
272
+ // 1. to initialize in the control plane combiner;
273
+ // 2. to use in the data plane combiner.
274
+ // So no additional synchronization is needed.
275
+ class DropConfig : public RefCounted<DropConfig> {
276
+ public:
277
+ struct DropCategory {
278
+ bool operator==(const DropCategory& other) const {
279
+ return name == other.name &&
280
+ parts_per_million == other.parts_per_million;
281
+ }
217
282
 
218
- bool operator==(const PriorityListUpdate& other) const;
219
- bool operator!=(const PriorityListUpdate& other) const {
220
- return !(*this == other);
221
- }
222
-
223
- void Add(LocalityMap::Locality locality);
224
-
225
- const LocalityMap* Find(uint32_t priority) const;
226
-
227
- bool Contains(uint32_t priority) const {
228
- return priority < priorities_.size();
229
- }
230
- bool Contains(const RefCountedPtr<XdsLocalityName>& name);
283
+ std::string name;
284
+ const uint32_t parts_per_million;
285
+ };
231
286
 
232
- bool empty() const { return priorities_.empty(); }
233
- size_t size() const { return priorities_.size(); }
287
+ using DropCategoryList = absl::InlinedVector<DropCategory, 2>;
234
288
 
235
- // Callers should make sure the priority list is non-empty.
236
- uint32_t LowestPriority() const {
237
- return static_cast<uint32_t>(priorities_.size()) - 1;
238
- }
289
+ void AddCategory(std::string name, uint32_t parts_per_million) {
290
+ drop_category_list_.emplace_back(
291
+ DropCategory{std::move(name), parts_per_million});
292
+ if (parts_per_million == 1000000) drop_all_ = true;
293
+ }
239
294
 
240
- private:
241
- absl::InlinedVector<LocalityMap, 2> priorities_;
242
- };
295
+ // The only method invoked from outside the WorkSerializer (used in
296
+ // the data plane).
297
+ bool ShouldDrop(const std::string** category_name) const;
243
298
 
244
- // There are two phases of accessing this class's content:
245
- // 1. to initialize in the control plane combiner;
246
- // 2. to use in the data plane combiner.
247
- // So no additional synchronization is needed.
248
- class DropConfig : public RefCounted<DropConfig> {
249
- public:
250
- struct DropCategory {
251
- bool operator==(const DropCategory& other) const {
252
- return name == other.name &&
253
- parts_per_million == other.parts_per_million;
299
+ const DropCategoryList& drop_category_list() const {
300
+ return drop_category_list_;
254
301
  }
255
302
 
256
- std::string name;
257
- const uint32_t parts_per_million;
258
- };
259
-
260
- using DropCategoryList = absl::InlinedVector<DropCategory, 2>;
303
+ bool drop_all() const { return drop_all_; }
261
304
 
262
- void AddCategory(std::string name, uint32_t parts_per_million) {
263
- drop_category_list_.emplace_back(
264
- DropCategory{std::move(name), parts_per_million});
265
- if (parts_per_million == 1000000) drop_all_ = true;
266
- }
305
+ bool operator==(const DropConfig& other) const {
306
+ return drop_category_list_ == other.drop_category_list_;
307
+ }
308
+ bool operator!=(const DropConfig& other) const {
309
+ return !(*this == other);
310
+ }
267
311
 
268
- // The only method invoked from the data plane combiner.
269
- bool ShouldDrop(const std::string** category_name) const;
312
+ std::string ToString() const;
270
313
 
271
- const DropCategoryList& drop_category_list() const {
272
- return drop_category_list_;
273
- }
314
+ private:
315
+ DropCategoryList drop_category_list_;
316
+ bool drop_all_ = false;
317
+ };
274
318
 
275
- bool drop_all() const { return drop_all_; }
319
+ PriorityList priorities;
320
+ RefCountedPtr<DropConfig> drop_config;
276
321
 
277
- bool operator==(const DropConfig& other) const {
278
- return drop_category_list_ == other.drop_category_list_;
322
+ bool operator==(const EdsUpdate& other) const {
323
+ return priorities == other.priorities &&
324
+ *drop_config == *other.drop_config;
279
325
  }
280
- bool operator!=(const DropConfig& other) const { return !(*this == other); }
281
-
282
- private:
283
- DropCategoryList drop_category_list_;
284
- bool drop_all_ = false;
285
- };
286
-
287
- struct EdsUpdate {
288
- PriorityListUpdate priority_list_update;
289
- RefCountedPtr<DropConfig> drop_config;
326
+ std::string ToString() const;
290
327
  };
291
328
 
292
329
  using EdsUpdateMap = std::map<std::string /*eds_service_name*/, EdsUpdate>;
293
330
 
294
331
  struct ClusterLoadReport {
295
- XdsClusterDropStats::DroppedRequestsMap dropped_requests;
332
+ XdsClusterDropStats::Snapshot dropped_requests;
296
333
  std::map<RefCountedPtr<XdsLocalityName>, XdsClusterLocalityStats::Snapshot,
297
334
  XdsLocalityName::Less>
298
335
  locality_stats;
@@ -320,20 +357,20 @@ class XdsApi {
320
357
  std::string version;
321
358
  std::string nonce;
322
359
  std::string type_url;
323
- absl::optional<LdsUpdate> lds_update;
324
- absl::optional<RdsUpdate> rds_update;
360
+ LdsUpdateMap lds_update_map;
361
+ RdsUpdateMap rds_update_map;
325
362
  CdsUpdateMap cds_update_map;
326
363
  EdsUpdateMap eds_update_map;
327
364
  };
328
365
  AdsParseResult ParseAdsResponse(
329
366
  const grpc_slice& encoded_response,
330
- const std::string& expected_server_name,
367
+ const std::set<absl::string_view>& expected_listener_names,
331
368
  const std::set<absl::string_view>& expected_route_configuration_names,
332
369
  const std::set<absl::string_view>& expected_cluster_names,
333
370
  const std::set<absl::string_view>& expected_eds_service_names);
334
371
 
335
- // Creates an LRS request querying \a server_name.
336
- grpc_slice CreateLrsInitialRequest(const std::string& server_name);
372
+ // Creates an initial LRS request.
373
+ grpc_slice CreateLrsInitialRequest();
337
374
 
338
375
  // Creates an LRS request sending a client-side load report.
339
376
  grpc_slice CreateLrsRequest(ClusterLoadReportMap cluster_load_report_map);
@@ -17,10 +17,13 @@
17
17
  #ifndef GRPC_CORE_EXT_XDS_XDS_CHANNEL_ARGS_H
18
18
  #define GRPC_CORE_EXT_XDS_XDS_CHANNEL_ARGS_H
19
19
 
20
- // Boolean channel arg indicating whether the target is an xds server.
21
- #define GRPC_ARG_ADDRESS_IS_XDS_SERVER "grpc.address_is_xds_server"
22
-
23
20
  // Pointer channel arg containing a ref to the XdsClient object.
24
21
  #define GRPC_ARG_XDS_CLIENT "grpc.xds_client"
25
22
 
23
+ // Timeout in milliseconds to wait for a resource to be returned from
24
+ // the xds server before assuming that it does not exist.
25
+ // The default is 15 seconds.
26
+ #define GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS \
27
+ "grpc.xds_resource_does_not_exist_timeout_ms"
28
+
26
29
  #endif /* GRPC_CORE_EXT_XDS_XDS_CHANNEL_ARGS_H */
@@ -35,7 +35,6 @@
35
35
  #include "src/core/ext/filters/client_channel/client_channel.h"
36
36
  #include "src/core/ext/filters/client_channel/service_config.h"
37
37
  #include "src/core/ext/xds/xds_api.h"
38
- #include "src/core/ext/xds/xds_channel.h"
39
38
  #include "src/core/ext/xds/xds_channel_args.h"
40
39
  #include "src/core/ext/xds/xds_client.h"
41
40
  #include "src/core/ext/xds/xds_client_stats.h"
@@ -51,7 +50,8 @@
51
50
  #include "src/core/lib/iomgr/sockaddr.h"
52
51
  #include "src/core/lib/iomgr/sockaddr_utils.h"
53
52
  #include "src/core/lib/iomgr/timer.h"
54
- #include "src/core/lib/iomgr/work_serializer.h"
53
+ #include "src/core/lib/security/credentials/credentials.h"
54
+ #include "src/core/lib/security/credentials/fake/fake_credentials.h"
55
55
  #include "src/core/lib/slice/slice_internal.h"
56
56
  #include "src/core/lib/slice/slice_string_helpers.h"
57
57
  #include "src/core/lib/surface/call.h"
@@ -69,6 +69,14 @@ namespace grpc_core {
69
69
 
70
70
  TraceFlag grpc_xds_client_trace(false, "xds_client");
71
71
 
72
+ namespace {
73
+
74
+ Mutex* g_mu = nullptr;
75
+ const grpc_channel_args* g_channel_args = nullptr;
76
+ XdsClient* g_xds_client = nullptr;
77
+
78
+ } // namespace
79
+
72
80
  //
73
81
  // Internal class declarations
74
82
  //
@@ -143,14 +151,14 @@ class XdsClient::ChannelState::AdsCallState
143
151
 
144
152
  void Orphan() override {
145
153
  Finish();
146
- Unref();
154
+ Unref(DEBUG_LOCATION, "Orphan");
147
155
  }
148
156
 
149
157
  void Start(RefCountedPtr<AdsCallState> ads_calld) {
150
158
  if (sent_) return;
151
159
  sent_ = true;
152
160
  ads_calld_ = std::move(ads_calld);
153
- Ref().release();
161
+ Ref(DEBUG_LOCATION, "timer").release();
154
162
  timer_pending_ = true;
155
163
  grpc_timer_init(
156
164
  &timer_,
@@ -168,9 +176,12 @@ class XdsClient::ChannelState::AdsCallState
168
176
  private:
169
177
  static void OnTimer(void* arg, grpc_error* error) {
170
178
  ResourceState* self = static_cast<ResourceState*>(arg);
171
- GRPC_ERROR_REF(error); // ref owned by lambda
172
- self->ads_calld_->xds_client()->work_serializer_->Run(
173
- [self, error]() { self->OnTimerLocked(error); }, DEBUG_LOCATION);
179
+ {
180
+ MutexLock lock(&self->ads_calld_->xds_client()->mu_);
181
+ self->OnTimerLocked(GRPC_ERROR_REF(error));
182
+ }
183
+ self->ads_calld_.reset();
184
+ self->Unref(DEBUG_LOCATION, "timer");
174
185
  }
175
186
 
176
187
  void OnTimerLocked(grpc_error* error) {
@@ -185,27 +196,32 @@ class XdsClient::ChannelState::AdsCallState
185
196
  gpr_log(GPR_INFO, "[xds_client %p] %s", ads_calld_->xds_client(),
186
197
  grpc_error_string(watcher_error));
187
198
  }
188
- if (type_url_ == XdsApi::kLdsTypeUrl ||
189
- type_url_ == XdsApi::kRdsTypeUrl) {
190
- ads_calld_->xds_client()->listener_watcher_->OnError(watcher_error);
199
+ if (type_url_ == XdsApi::kLdsTypeUrl) {
200
+ ListenerState& state = ads_calld_->xds_client()->listener_map_[name_];
201
+ for (const auto& p : state.watchers) {
202
+ p.first->OnError(GRPC_ERROR_REF(watcher_error));
203
+ }
204
+ } else if (type_url_ == XdsApi::kRdsTypeUrl) {
205
+ RouteConfigState& state =
206
+ ads_calld_->xds_client()->route_config_map_[name_];
207
+ for (const auto& p : state.watchers) {
208
+ p.first->OnError(GRPC_ERROR_REF(watcher_error));
209
+ }
191
210
  } else if (type_url_ == XdsApi::kCdsTypeUrl) {
192
211
  ClusterState& state = ads_calld_->xds_client()->cluster_map_[name_];
193
212
  for (const auto& p : state.watchers) {
194
213
  p.first->OnError(GRPC_ERROR_REF(watcher_error));
195
214
  }
196
- GRPC_ERROR_UNREF(watcher_error);
197
215
  } else if (type_url_ == XdsApi::kEdsTypeUrl) {
198
216
  EndpointState& state = ads_calld_->xds_client()->endpoint_map_[name_];
199
217
  for (const auto& p : state.watchers) {
200
218
  p.first->OnError(GRPC_ERROR_REF(watcher_error));
201
219
  }
202
- GRPC_ERROR_UNREF(watcher_error);
203
220
  } else {
204
221
  GPR_UNREACHABLE_CODE(return );
205
222
  }
223
+ GRPC_ERROR_UNREF(watcher_error);
206
224
  }
207
- ads_calld_.reset();
208
- Unref();
209
225
  GRPC_ERROR_UNREF(error);
210
226
  }
211
227
 
@@ -234,15 +250,15 @@ class XdsClient::ChannelState::AdsCallState
234
250
 
235
251
  void SendMessageLocked(const std::string& type_url);
236
252
 
237
- void AcceptLdsUpdate(absl::optional<XdsApi::LdsUpdate> lds_update);
238
- void AcceptRdsUpdate(absl::optional<XdsApi::RdsUpdate> rds_update);
253
+ void AcceptLdsUpdate(XdsApi::LdsUpdateMap lds_update_map);
254
+ void AcceptRdsUpdate(XdsApi::RdsUpdateMap rds_update_map);
239
255
  void AcceptCdsUpdate(XdsApi::CdsUpdateMap cds_update_map);
240
256
  void AcceptEdsUpdate(XdsApi::EdsUpdateMap eds_update_map);
241
257
 
242
258
  static void OnRequestSent(void* arg, grpc_error* error);
243
259
  void OnRequestSentLocked(grpc_error* error);
244
260
  static void OnResponseReceived(void* arg, grpc_error* error);
245
- void OnResponseReceivedLocked();
261
+ bool OnResponseReceivedLocked();
246
262
  static void OnStatusReceived(void* arg, grpc_error* error);
247
263
  void OnStatusReceivedLocked(grpc_error* error);
248
264
 
@@ -319,10 +335,10 @@ class XdsClient::ChannelState::LrsCallState
319
335
  private:
320
336
  void ScheduleNextReportLocked();
321
337
  static void OnNextReportTimer(void* arg, grpc_error* error);
322
- void OnNextReportTimerLocked(grpc_error* error);
338
+ bool OnNextReportTimerLocked(grpc_error* error);
323
339
  void SendReportLocked();
324
340
  static void OnReportDone(void* arg, grpc_error* error);
325
- void OnReportDoneLocked(grpc_error* error);
341
+ bool OnReportDoneLocked(grpc_error* error);
326
342
 
327
343
  bool IsCurrentReporterOnCall() const {
328
344
  return this == parent_->reporter_.get();
@@ -344,7 +360,7 @@ class XdsClient::ChannelState::LrsCallState
344
360
  static void OnInitialRequestSent(void* arg, grpc_error* error);
345
361
  void OnInitialRequestSentLocked();
346
362
  static void OnResponseReceived(void* arg, grpc_error* error);
347
- void OnResponseReceivedLocked();
363
+ bool OnResponseReceivedLocked();
348
364
  static void OnStatusReceived(void* arg, grpc_error* error);
349
365
  void OnStatusReceivedLocked(grpc_error* error);
350
366
 
@@ -389,13 +405,12 @@ class XdsClient::ChannelState::StateWatcher
389
405
  : public AsyncConnectivityStateWatcherInterface {
390
406
  public:
391
407
  explicit StateWatcher(RefCountedPtr<ChannelState> parent)
392
- : AsyncConnectivityStateWatcherInterface(
393
- parent->xds_client()->work_serializer_),
394
- parent_(std::move(parent)) {}
408
+ : parent_(std::move(parent)) {}
395
409
 
396
410
  private:
397
411
  void OnConnectivityStateChange(grpc_connectivity_state new_state,
398
412
  const absl::Status& status) override {
413
+ MutexLock lock(&parent_->xds_client_->mu_);
399
414
  if (!parent_->shutting_down_ &&
400
415
  new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
401
416
  // In TRANSIENT_FAILURE. Notify all watchers of error.
@@ -403,8 +418,9 @@ class XdsClient::ChannelState::StateWatcher
403
418
  "[xds_client %p] xds channel in state:TRANSIENT_FAILURE "
404
419
  "status_message:(%s)",
405
420
  parent_->xds_client(), status.ToString().c_str());
406
- parent_->xds_client()->NotifyOnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
407
- "xds channel in TRANSIENT_FAILURE"));
421
+ parent_->xds_client()->NotifyOnErrorLocked(
422
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING(
423
+ "xds channel in TRANSIENT_FAILURE"));
408
424
  }
409
425
  }
410
426
 
@@ -415,67 +431,7 @@ class XdsClient::ChannelState::StateWatcher
415
431
  // XdsClient::ChannelState
416
432
  //
417
433
 
418
- namespace {
419
-
420
- // Returns the channel args for the xds channel.
421
- grpc_channel_args* BuildXdsChannelArgs(const grpc_channel_args& args) {
422
- static const char* args_to_remove[] = {
423
- // LB policy name, since we want to use the default (pick_first) in
424
- // the LB channel.
425
- GRPC_ARG_LB_POLICY_NAME,
426
- // The service config that contains the LB config. We don't want to
427
- // recursively use xds in the LB channel.
428
- GRPC_ARG_SERVICE_CONFIG,
429
- // The channel arg for the server URI, since that will be different for
430
- // the xds channel than for the parent channel. The client channel
431
- // factory will re-add this arg with the right value.
432
- GRPC_ARG_SERVER_URI,
433
- // The xds channel should use the authority indicated by the target
434
- // authority table (see \a ModifyXdsChannelArgs),
435
- // as opposed to the authority from the parent channel.
436
- GRPC_ARG_DEFAULT_AUTHORITY,
437
- // Just as for \a GRPC_ARG_DEFAULT_AUTHORITY, the xds channel should be
438
- // treated as a stand-alone channel and not inherit this argument from the
439
- // args of the parent channel.
440
- GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
441
- // Don't want to pass down channelz node from parent; the balancer
442
- // channel will get its own.
443
- GRPC_ARG_CHANNELZ_CHANNEL_NODE,
444
- // Keepalive interval. We are explicitly setting our own value below.
445
- GRPC_ARG_KEEPALIVE_TIME_MS,
446
- };
447
- // Channel args to add.
448
- absl::InlinedVector<grpc_arg, 3> args_to_add;
449
- // Keepalive interval.
450
- args_to_add.emplace_back(grpc_channel_arg_integer_create(
451
- const_cast<char*>(GRPC_ARG_KEEPALIVE_TIME_MS), 5000));
452
- // A channel arg indicating that the target is an xds server.
453
- // TODO(roth): Once we figure out our fallback and credentials story, decide
454
- // whether this is actually needed. Note that it's currently used by the
455
- // fake security connector as well.
456
- args_to_add.emplace_back(grpc_channel_arg_integer_create(
457
- const_cast<char*>(GRPC_ARG_ADDRESS_IS_XDS_SERVER), 1));
458
- // The parent channel's channelz uuid.
459
- channelz::ChannelNode* channelz_node = nullptr;
460
- const grpc_arg* arg =
461
- grpc_channel_args_find(&args, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
462
- if (arg != nullptr && arg->type == GRPC_ARG_POINTER &&
463
- arg->value.pointer.p != nullptr) {
464
- channelz_node = static_cast<channelz::ChannelNode*>(arg->value.pointer.p);
465
- args_to_add.emplace_back(
466
- channelz::MakeParentUuidArg(channelz_node->uuid()));
467
- }
468
- // Construct channel args.
469
- grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
470
- &args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add.data(),
471
- args_to_add.size());
472
- // Make any necessary modifications for security.
473
- return ModifyXdsChannelArgs(new_args);
474
- }
475
-
476
- } // namespace
477
-
478
- XdsClient::ChannelState::ChannelState(RefCountedPtr<XdsClient> xds_client,
434
+ XdsClient::ChannelState::ChannelState(WeakRefCountedPtr<XdsClient> xds_client,
479
435
  grpc_channel* channel)
480
436
  : InternallyRefCounted<ChannelState>(&grpc_xds_client_trace),
481
437
  xds_client_(std::move(xds_client)),
@@ -490,6 +446,7 @@ XdsClient::ChannelState::~ChannelState() {
490
446
  this);
491
447
  }
492
448
  grpc_channel_destroy(channel_);
449
+ xds_client_.reset(DEBUG_LOCATION, "ChannelState");
493
450
  }
494
451
 
495
452
  void XdsClient::ChannelState::Orphan() {
@@ -526,7 +483,7 @@ void XdsClient::ChannelState::StartConnectivityWatchLocked() {
526
483
  grpc_channel_element* client_channel_elem =
527
484
  grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel_));
528
485
  GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
529
- watcher_ = new StateWatcher(Ref());
486
+ watcher_ = new StateWatcher(Ref(DEBUG_LOCATION, "ChannelState+watch"));
530
487
  grpc_client_channel_start_connectivity_watch(
531
488
  client_channel_elem, GRPC_CHANNEL_IDLE,
532
489
  OrphanablePtr<AsyncConnectivityStateWatcherInterface>(watcher_));
@@ -561,8 +518,11 @@ void XdsClient::ChannelState::Unsubscribe(const std::string& type_url,
561
518
  const std::string& name,
562
519
  bool delay_unsubscription) {
563
520
  if (ads_calld_ != nullptr) {
564
- ads_calld_->calld()->Unsubscribe(type_url, name, delay_unsubscription);
565
- if (!ads_calld_->calld()->HasSubscribedResources()) ads_calld_.reset();
521
+ auto* calld = ads_calld_->calld();
522
+ if (calld != nullptr) {
523
+ calld->Unsubscribe(type_url, name, delay_unsubscription);
524
+ if (!calld->HasSubscribedResources()) ads_calld_.reset();
525
+ }
566
526
  }
567
527
  }
568
528
 
@@ -645,9 +605,11 @@ template <typename T>
645
605
  void XdsClient::ChannelState::RetryableCall<T>::OnRetryTimer(
646
606
  void* arg, grpc_error* error) {
647
607
  RetryableCall* calld = static_cast<RetryableCall*>(arg);
648
- GRPC_ERROR_REF(error); // ref owned by lambda
649
- calld->chand_->xds_client()->work_serializer_->Run(
650
- [calld, error]() { calld->OnRetryTimerLocked(error); }, DEBUG_LOCATION);
608
+ {
609
+ MutexLock lock(&calld->chand_->xds_client()->mu_);
610
+ calld->OnRetryTimerLocked(GRPC_ERROR_REF(error));
611
+ }
612
+ calld->Unref(DEBUG_LOCATION, "RetryableCall+retry_timer_done");
651
613
  }
652
614
 
653
615
  template <typename T>
@@ -663,7 +625,6 @@ void XdsClient::ChannelState::RetryableCall<T>::OnRetryTimerLocked(
663
625
  }
664
626
  StartNewCallLocked();
665
627
  }
666
- this->Unref(DEBUG_LOCATION, "RetryableCall+retry_timer_done");
667
628
  GRPC_ERROR_UNREF(error);
668
629
  }
669
630
 
@@ -679,7 +640,6 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
679
640
  // activity in xds_client()->interested_parties_, which is comprised of
680
641
  // the polling entities from client_channel.
681
642
  GPR_ASSERT(xds_client() != nullptr);
682
- GPR_ASSERT(!xds_client()->server_name_.empty());
683
643
  // Create a call with the specified method name.
684
644
  const auto& method =
685
645
  xds_client()->bootstrap_->server().ShouldUseV3()
@@ -718,13 +678,11 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
718
678
  // Op: send request message.
719
679
  GRPC_CLOSURE_INIT(&on_request_sent_, OnRequestSent, this,
720
680
  grpc_schedule_on_exec_ctx);
721
- if (xds_client()->listener_watcher_ != nullptr) {
722
- Subscribe(XdsApi::kLdsTypeUrl, xds_client()->server_name_);
723
- if (xds_client()->lds_result_.has_value() &&
724
- !xds_client()->lds_result_->route_config_name.empty()) {
725
- Subscribe(XdsApi::kRdsTypeUrl,
726
- xds_client()->lds_result_->route_config_name);
727
- }
681
+ for (const auto& p : xds_client()->listener_map_) {
682
+ Subscribe(XdsApi::kLdsTypeUrl, std::string(p.first));
683
+ }
684
+ for (const auto& p : xds_client()->route_config_map_) {
685
+ Subscribe(XdsApi::kRdsTypeUrl, std::string(p.first));
728
686
  }
729
687
  for (const auto& p : xds_client()->cluster_map_) {
730
688
  Subscribe(XdsApi::kCdsTypeUrl, std::string(p.first));
@@ -868,118 +826,139 @@ bool XdsClient::ChannelState::AdsCallState::HasSubscribedResources() const {
868
826
  }
869
827
 
870
828
  void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate(
871
- absl::optional<XdsApi::LdsUpdate> lds_update) {
872
- if (!lds_update.has_value()) {
873
- gpr_log(GPR_INFO,
874
- "[xds_client %p] LDS update does not include requested resource",
875
- xds_client());
876
- if (xds_client()->lds_result_.has_value() &&
877
- !xds_client()->lds_result_->route_config_name.empty()) {
878
- Unsubscribe(XdsApi::kRdsTypeUrl,
879
- xds_client()->lds_result_->route_config_name,
880
- /*delay_unsubscription=*/false);
881
- xds_client()->rds_result_.reset();
882
- }
883
- xds_client()->lds_result_.reset();
884
- xds_client()->listener_watcher_->OnResourceDoesNotExist();
885
- return;
886
- }
829
+ XdsApi::LdsUpdateMap lds_update_map) {
887
830
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
888
831
  gpr_log(GPR_INFO,
889
- "[xds_client %p] LDS update received: route_config_name=%s",
890
- xds_client(),
891
- (!lds_update->route_config_name.empty()
892
- ? lds_update->route_config_name.c_str()
893
- : "<inlined>"));
894
- if (lds_update->rds_update.has_value()) {
895
- gpr_log(GPR_INFO, "RouteConfiguration: %s",
896
- lds_update->rds_update->ToString().c_str());
897
- }
832
+ "[xds_client %p] LDS update received containing %" PRIuPTR
833
+ " resources",
834
+ xds_client(), lds_update_map.size());
898
835
  }
899
836
  auto& lds_state = state_map_[XdsApi::kLdsTypeUrl];
900
- auto& state = lds_state.subscribed_resources[xds_client()->server_name_];
901
- if (state != nullptr) state->Finish();
902
- // Ignore identical update.
903
- if (xds_client()->lds_result_ == lds_update) {
837
+ std::set<std::string> rds_resource_names_seen;
838
+ for (auto& p : lds_update_map) {
839
+ const std::string& listener_name = p.first;
840
+ XdsApi::LdsUpdate& lds_update = p.second;
841
+ auto& state = lds_state.subscribed_resources[listener_name];
842
+ if (state != nullptr) state->Finish();
904
843
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
905
- gpr_log(GPR_INFO,
906
- "[xds_client %p] LDS update identical to current, ignoring.",
907
- xds_client());
844
+ gpr_log(GPR_INFO, "[xds_client %p] LDS resource %s: route_config_name=%s",
845
+ xds_client(), listener_name.c_str(),
846
+ (!lds_update.route_config_name.empty()
847
+ ? lds_update.route_config_name.c_str()
848
+ : "<inlined>"));
849
+ if (lds_update.rds_update.has_value()) {
850
+ gpr_log(GPR_INFO, "RouteConfiguration: %s",
851
+ lds_update.rds_update->ToString().c_str());
852
+ }
853
+ }
854
+ // Record the RDS resource names seen.
855
+ if (!lds_update.route_config_name.empty()) {
856
+ rds_resource_names_seen.insert(lds_update.route_config_name);
857
+ }
858
+ // Ignore identical update.
859
+ ListenerState& listener_state = xds_client()->listener_map_[listener_name];
860
+ if (listener_state.update.has_value() &&
861
+ *listener_state.update == lds_update) {
862
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
863
+ gpr_log(GPR_INFO,
864
+ "[xds_client %p] LDS update for %s identical to current, "
865
+ "ignoring.",
866
+ xds_client(), listener_name.c_str());
867
+ }
868
+ continue;
869
+ }
870
+ // Update the listener state.
871
+ listener_state.update = std::move(lds_update);
872
+ // Notify watchers.
873
+ for (const auto& p : listener_state.watchers) {
874
+ p.first->OnListenerChanged(*listener_state.update);
908
875
  }
909
- return;
910
876
  }
911
- if (xds_client()->lds_result_.has_value() &&
912
- !xds_client()->lds_result_->route_config_name.empty()) {
913
- Unsubscribe(
914
- XdsApi::kRdsTypeUrl, xds_client()->lds_result_->route_config_name,
915
- /*delay_unsubscription=*/!lds_update->route_config_name.empty());
916
- xds_client()->rds_result_.reset();
917
- }
918
- xds_client()->lds_result_ = std::move(lds_update);
919
- if (xds_client()->lds_result_->rds_update.has_value()) {
920
- // If the RouteConfiguration was found inlined in LDS response, notify
921
- // the watcher immediately.
922
- const XdsApi::RdsUpdate::VirtualHost* vhost =
923
- xds_client()->lds_result_->rds_update->FindVirtualHostForDomain(
924
- xds_client()->server_name_);
925
- if (vhost == nullptr) {
926
- xds_client()->listener_watcher_->OnError(
927
- GRPC_ERROR_CREATE_FROM_STATIC_STRING(
928
- "no VirtualHost found for domain"));
929
- } else {
930
- xds_client()->listener_watcher_->OnListenerChanged(vhost->routes);
877
+ // For any subscribed resource that is not present in the update,
878
+ // remove it from the cache and notify watchers that it does not exist.
879
+ for (const auto& p : lds_state.subscribed_resources) {
880
+ const std::string& listener_name = p.first;
881
+ if (lds_update_map.find(listener_name) == lds_update_map.end()) {
882
+ ListenerState& listener_state =
883
+ xds_client()->listener_map_[listener_name];
884
+ // If the resource was newly requested but has not yet been received,
885
+ // we don't want to generate an error for the watchers, because this LDS
886
+ // response may be in reaction to an earlier request that did not yet
887
+ // request the new resource, so its absence from the response does not
888
+ // necessarily indicate that the resource does not exist.
889
+ // For that case, we rely on the request timeout instead.
890
+ if (!listener_state.update.has_value()) continue;
891
+ listener_state.update.reset();
892
+ for (const auto& p : listener_state.watchers) {
893
+ p.first->OnResourceDoesNotExist();
894
+ }
895
+ }
896
+ }
897
+ // For any RDS resource that is no longer referred to by any LDS
898
+ // resources, remove it from the cache and notify watchers that it
899
+ // does not exist.
900
+ auto& rds_state = state_map_[XdsApi::kRdsTypeUrl];
901
+ for (const auto& p : rds_state.subscribed_resources) {
902
+ const std::string& rds_resource_name = p.first;
903
+ if (rds_resource_names_seen.find(rds_resource_name) ==
904
+ rds_resource_names_seen.end()) {
905
+ RouteConfigState& route_config_state =
906
+ xds_client()->route_config_map_[rds_resource_name];
907
+ route_config_state.update.reset();
908
+ for (const auto& p : route_config_state.watchers) {
909
+ p.first->OnResourceDoesNotExist();
910
+ }
931
911
  }
932
- } else {
933
- // Send RDS request for dynamic resolution.
934
- Subscribe(XdsApi::kRdsTypeUrl,
935
- xds_client()->lds_result_->route_config_name);
936
912
  }
937
913
  }
938
914
 
939
915
  void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdate(
940
- absl::optional<XdsApi::RdsUpdate> rds_update) {
941
- if (!rds_update.has_value()) {
942
- gpr_log(GPR_INFO,
943
- "[xds_client %p] RDS update does not include requested resource",
944
- xds_client());
945
- xds_client()->rds_result_.reset();
946
- xds_client()->listener_watcher_->OnResourceDoesNotExist();
947
- return;
948
- }
916
+ XdsApi::RdsUpdateMap rds_update_map) {
949
917
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
950
- gpr_log(GPR_INFO, "[xds_client %p] RDS update received:\n%s", xds_client(),
951
- rds_update->ToString().c_str());
918
+ gpr_log(GPR_INFO,
919
+ "[xds_client %p] RDS update received containing %" PRIuPTR
920
+ " resources",
921
+ xds_client(), rds_update_map.size());
952
922
  }
953
923
  auto& rds_state = state_map_[XdsApi::kRdsTypeUrl];
954
- auto& state =
955
- rds_state
956
- .subscribed_resources[xds_client()->lds_result_->route_config_name];
957
- if (state != nullptr) state->Finish();
958
- // Ignore identical update.
959
- if (xds_client()->rds_result_ == rds_update) {
924
+ for (auto& p : rds_update_map) {
925
+ const std::string& route_config_name = p.first;
926
+ XdsApi::RdsUpdate& rds_update = p.second;
927
+ auto& state = rds_state.subscribed_resources[route_config_name];
928
+ if (state != nullptr) state->Finish();
960
929
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
961
- gpr_log(GPR_INFO,
962
- "[xds_client %p] RDS update identical to current, ignoring.",
963
- xds_client());
930
+ gpr_log(GPR_INFO, "[xds_client %p] RDS resource:\n%s", xds_client(),
931
+ rds_update.ToString().c_str());
932
+ }
933
+ RouteConfigState& route_config_state =
934
+ xds_client()->route_config_map_[route_config_name];
935
+ // Ignore identical update.
936
+ if (route_config_state.update.has_value() &&
937
+ *route_config_state.update == rds_update) {
938
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
939
+ gpr_log(GPR_INFO,
940
+ "[xds_client %p] RDS resource identical to current, ignoring",
941
+ xds_client());
942
+ }
943
+ continue;
944
+ }
945
+ // Update the cache.
946
+ route_config_state.update = std::move(rds_update);
947
+ // Notify all watchers.
948
+ for (const auto& p : route_config_state.watchers) {
949
+ p.first->OnRouteConfigChanged(*route_config_state.update);
964
950
  }
965
- return;
966
- }
967
- xds_client()->rds_result_ = std::move(rds_update);
968
- // Notify the watcher.
969
- const XdsApi::RdsUpdate::VirtualHost* vhost =
970
- xds_client()->rds_result_->FindVirtualHostForDomain(
971
- xds_client()->server_name_);
972
- if (vhost == nullptr) {
973
- xds_client()->listener_watcher_->OnError(
974
- GRPC_ERROR_CREATE_FROM_STATIC_STRING(
975
- "no VirtualHost found for domain"));
976
- } else {
977
- xds_client()->listener_watcher_->OnListenerChanged(vhost->routes);
978
951
  }
979
952
  }
980
953
 
981
954
  void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
982
955
  XdsApi::CdsUpdateMap cds_update_map) {
956
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
957
+ gpr_log(GPR_INFO,
958
+ "[xds_client %p] CDS update received containing %" PRIuPTR
959
+ " resources",
960
+ xds_client(), cds_update_map.size());
961
+ }
983
962
  auto& cds_state = state_map_[XdsApi::kCdsTypeUrl];
984
963
  std::set<std::string> eds_resource_names_seen;
985
964
  for (auto& p : cds_update_map) {
@@ -989,8 +968,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
989
968
  if (state != nullptr) state->Finish();
990
969
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
991
970
  gpr_log(GPR_INFO,
992
- "[xds_client %p] CDS update (cluster=%s) received: "
993
- "eds_service_name=%s, lrs_load_reporting_server_name=%s",
971
+ "[xds_client %p] cluster=%s: eds_service_name=%s, "
972
+ "lrs_load_reporting_server_name=%s",
994
973
  xds_client(), cluster_name, cds_update.eds_service_name.c_str(),
995
974
  cds_update.lrs_load_reporting_server_name.has_value()
996
975
  ? cds_update.lrs_load_reporting_server_name.value().c_str()
@@ -1003,9 +982,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
1003
982
  // Ignore identical update.
1004
983
  ClusterState& cluster_state = xds_client()->cluster_map_[cluster_name];
1005
984
  if (cluster_state.update.has_value() &&
1006
- cds_update.eds_service_name == cluster_state.update->eds_service_name &&
1007
- cds_update.lrs_load_reporting_server_name ==
1008
- cluster_state.update->lrs_load_reporting_server_name) {
985
+ *cluster_state.update == cds_update) {
1009
986
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1010
987
  gpr_log(GPR_INFO,
1011
988
  "[xds_client %p] CDS update identical to current, ignoring.",
@@ -1059,6 +1036,12 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
1059
1036
 
1060
1037
  void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate(
1061
1038
  XdsApi::EdsUpdateMap eds_update_map) {
1039
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1040
+ gpr_log(GPR_INFO,
1041
+ "[xds_client %p] EDS update received containing %" PRIuPTR
1042
+ " resources",
1043
+ xds_client(), eds_update_map.size());
1044
+ }
1062
1045
  auto& eds_state = state_map_[XdsApi::kEdsTypeUrl];
1063
1046
  for (auto& p : eds_update_map) {
1064
1047
  const char* eds_service_name = p.first.c_str();
@@ -1066,71 +1049,20 @@ void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate(
1066
1049
  auto& state = eds_state.subscribed_resources[eds_service_name];
1067
1050
  if (state != nullptr) state->Finish();
1068
1051
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1069
- gpr_log(GPR_INFO,
1070
- "[xds_client %p] EDS response with %" PRIuPTR
1071
- " priorities and %" PRIuPTR
1072
- " drop categories received (drop_all=%d)",
1073
- xds_client(), eds_update.priority_list_update.size(),
1074
- eds_update.drop_config->drop_category_list().size(),
1075
- eds_update.drop_config->drop_all());
1076
- for (size_t priority = 0;
1077
- priority < eds_update.priority_list_update.size(); ++priority) {
1078
- const auto* locality_map_update = eds_update.priority_list_update.Find(
1079
- static_cast<uint32_t>(priority));
1080
- gpr_log(GPR_INFO,
1081
- "[xds_client %p] Priority %" PRIuPTR " contains %" PRIuPTR
1082
- " localities",
1083
- xds_client(), priority, locality_map_update->size());
1084
- size_t locality_count = 0;
1085
- for (const auto& p : locality_map_update->localities) {
1086
- const auto& locality = p.second;
1087
- gpr_log(GPR_INFO,
1088
- "[xds_client %p] Priority %" PRIuPTR ", locality %" PRIuPTR
1089
- " %s has weight %d, contains %" PRIuPTR " server addresses",
1090
- xds_client(), priority, locality_count,
1091
- locality.name->AsHumanReadableString().c_str(),
1092
- locality.lb_weight, locality.serverlist.size());
1093
- for (size_t i = 0; i < locality.serverlist.size(); ++i) {
1094
- std::string ipport = grpc_sockaddr_to_string(
1095
- &locality.serverlist[i].address(), false);
1096
- gpr_log(GPR_INFO,
1097
- "[xds_client %p] Priority %" PRIuPTR ", locality %" PRIuPTR
1098
- " %s, server address %" PRIuPTR ": %s",
1099
- xds_client(), priority, locality_count,
1100
- locality.name->AsHumanReadableString().c_str(), i,
1101
- ipport.c_str());
1102
- }
1103
- ++locality_count;
1104
- }
1105
- }
1106
- for (size_t i = 0;
1107
- i < eds_update.drop_config->drop_category_list().size(); ++i) {
1108
- const XdsApi::DropConfig::DropCategory& drop_category =
1109
- eds_update.drop_config->drop_category_list()[i];
1110
- gpr_log(GPR_INFO,
1111
- "[xds_client %p] Drop category %s has drop rate %d per million",
1112
- xds_client(), drop_category.name.c_str(),
1113
- drop_category.parts_per_million);
1114
- }
1052
+ gpr_log(GPR_INFO, "[xds_client %p] EDS resource %s: %s", xds_client(),
1053
+ eds_service_name, eds_update.ToString().c_str());
1115
1054
  }
1116
1055
  EndpointState& endpoint_state =
1117
1056
  xds_client()->endpoint_map_[eds_service_name];
1118
1057
  // Ignore identical update.
1119
- if (endpoint_state.update.has_value()) {
1120
- const XdsApi::EdsUpdate& prev_update = endpoint_state.update.value();
1121
- const bool priority_list_changed =
1122
- prev_update.priority_list_update != eds_update.priority_list_update;
1123
- const bool drop_config_changed =
1124
- prev_update.drop_config == nullptr ||
1125
- *prev_update.drop_config != *eds_update.drop_config;
1126
- if (!priority_list_changed && !drop_config_changed) {
1127
- if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1128
- gpr_log(GPR_INFO,
1129
- "[xds_client %p] EDS update identical to current, ignoring.",
1130
- xds_client());
1131
- }
1132
- continue;
1058
+ if (endpoint_state.update.has_value() &&
1059
+ *endpoint_state.update == eds_update) {
1060
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1061
+ gpr_log(GPR_INFO,
1062
+ "[xds_client %p] EDS update identical to current, ignoring.",
1063
+ xds_client());
1133
1064
  }
1065
+ continue;
1134
1066
  }
1135
1067
  // Update the cluster state.
1136
1068
  endpoint_state.update = std::move(eds_update);
@@ -1144,10 +1076,11 @@ void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate(
1144
1076
  void XdsClient::ChannelState::AdsCallState::OnRequestSent(void* arg,
1145
1077
  grpc_error* error) {
1146
1078
  AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
1147
- GRPC_ERROR_REF(error); // ref owned by lambda
1148
- ads_calld->xds_client()->work_serializer_->Run(
1149
- [ads_calld, error]() { ads_calld->OnRequestSentLocked(error); },
1150
- DEBUG_LOCATION);
1079
+ {
1080
+ MutexLock lock(&ads_calld->xds_client()->mu_);
1081
+ ads_calld->OnRequestSentLocked(GRPC_ERROR_REF(error));
1082
+ }
1083
+ ads_calld->Unref(DEBUG_LOCATION, "ADS+OnRequestSentLocked");
1151
1084
  }
1152
1085
 
1153
1086
  void XdsClient::ChannelState::AdsCallState::OnRequestSentLocked(
@@ -1171,22 +1104,24 @@ void XdsClient::ChannelState::AdsCallState::OnRequestSentLocked(
1171
1104
  buffered_requests_.erase(it);
1172
1105
  }
1173
1106
  }
1174
- Unref(DEBUG_LOCATION, "ADS+OnRequestSentLocked");
1175
1107
  GRPC_ERROR_UNREF(error);
1176
1108
  }
1177
1109
 
1178
1110
  void XdsClient::ChannelState::AdsCallState::OnResponseReceived(
1179
1111
  void* arg, grpc_error* /* error */) {
1180
1112
  AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
1181
- ads_calld->xds_client()->work_serializer_->Run(
1182
- [ads_calld]() { ads_calld->OnResponseReceivedLocked(); }, DEBUG_LOCATION);
1113
+ bool done;
1114
+ {
1115
+ MutexLock lock(&ads_calld->xds_client()->mu_);
1116
+ done = ads_calld->OnResponseReceivedLocked();
1117
+ }
1118
+ if (done) ads_calld->Unref(DEBUG_LOCATION, "ADS+OnResponseReceivedLocked");
1183
1119
  }
1184
1120
 
1185
- void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
1121
+ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
1186
1122
  // Empty payload means the call was cancelled.
1187
1123
  if (!IsCurrentCallOnChannel() || recv_message_payload_ == nullptr) {
1188
- Unref(DEBUG_LOCATION, "ADS+OnResponseReceivedLocked");
1189
- return;
1124
+ return true;
1190
1125
  }
1191
1126
  // Read the response.
1192
1127
  grpc_byte_buffer_reader bbr;
@@ -1197,7 +1132,7 @@ void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
1197
1132
  recv_message_payload_ = nullptr;
1198
1133
  // Parse and validate the response.
1199
1134
  XdsApi::AdsParseResult result = xds_client()->api_.ParseAdsResponse(
1200
- response_slice, xds_client()->server_name_,
1135
+ response_slice, ResourceNamesForRequest(XdsApi::kLdsTypeUrl),
1201
1136
  ResourceNamesForRequest(XdsApi::kRdsTypeUrl),
1202
1137
  ResourceNamesForRequest(XdsApi::kCdsTypeUrl),
1203
1138
  ResourceNamesForRequest(XdsApi::kEdsTypeUrl));
@@ -1227,9 +1162,9 @@ void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
1227
1162
  seen_response_ = true;
1228
1163
  // Accept the ADS response according to the type_url.
1229
1164
  if (result.type_url == XdsApi::kLdsTypeUrl) {
1230
- AcceptLdsUpdate(std::move(result.lds_update));
1165
+ AcceptLdsUpdate(std::move(result.lds_update_map));
1231
1166
  } else if (result.type_url == XdsApi::kRdsTypeUrl) {
1232
- AcceptRdsUpdate(std::move(result.rds_update));
1167
+ AcceptRdsUpdate(std::move(result.rds_update_map));
1233
1168
  } else if (result.type_url == XdsApi::kCdsTypeUrl) {
1234
1169
  AcceptCdsUpdate(std::move(result.cds_update_map));
1235
1170
  } else if (result.type_url == XdsApi::kEdsTypeUrl) {
@@ -1246,10 +1181,7 @@ void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
1246
1181
  }
1247
1182
  }
1248
1183
  }
1249
- if (xds_client()->shutting_down_) {
1250
- Unref(DEBUG_LOCATION, "ADS+OnResponseReceivedLocked+xds_shutdown");
1251
- return;
1252
- }
1184
+ if (xds_client()->shutting_down_) return true;
1253
1185
  // Keep listening for updates.
1254
1186
  grpc_op op;
1255
1187
  memset(&op, 0, sizeof(op));
@@ -1262,15 +1194,17 @@ void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() {
1262
1194
  const grpc_call_error call_error =
1263
1195
  grpc_call_start_batch_and_execute(call_, &op, 1, &on_response_received_);
1264
1196
  GPR_ASSERT(GRPC_CALL_OK == call_error);
1197
+ return false;
1265
1198
  }
1266
1199
 
1267
1200
  void XdsClient::ChannelState::AdsCallState::OnStatusReceived(
1268
1201
  void* arg, grpc_error* error) {
1269
1202
  AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
1270
- GRPC_ERROR_REF(error); // ref owned by lambda
1271
- ads_calld->xds_client()->work_serializer_->Run(
1272
- [ads_calld, error]() { ads_calld->OnStatusReceivedLocked(error); },
1273
- DEBUG_LOCATION);
1203
+ {
1204
+ MutexLock lock(&ads_calld->xds_client()->mu_);
1205
+ ads_calld->OnStatusReceivedLocked(GRPC_ERROR_REF(error));
1206
+ }
1207
+ ads_calld->Unref(DEBUG_LOCATION, "ADS+OnStatusReceivedLocked");
1274
1208
  }
1275
1209
 
1276
1210
  void XdsClient::ChannelState::AdsCallState::OnStatusReceivedLocked(
@@ -1289,10 +1223,9 @@ void XdsClient::ChannelState::AdsCallState::OnStatusReceivedLocked(
1289
1223
  // Try to restart the call.
1290
1224
  parent_->OnCallFinishedLocked();
1291
1225
  // Send error to all watchers.
1292
- xds_client()->NotifyOnError(
1226
+ xds_client()->NotifyOnErrorLocked(
1293
1227
  GRPC_ERROR_CREATE_FROM_STATIC_STRING("xds call failed"));
1294
1228
  }
1295
- Unref(DEBUG_LOCATION, "ADS+OnStatusReceivedLocked");
1296
1229
  GRPC_ERROR_UNREF(error);
1297
1230
  }
1298
1231
 
@@ -1312,7 +1245,7 @@ XdsClient::ChannelState::AdsCallState::ResourceNamesForRequest(
1312
1245
  for (auto& p : it->second.subscribed_resources) {
1313
1246
  resource_names.insert(p.first);
1314
1247
  OrphanablePtr<ResourceState>& state = p.second;
1315
- state->Start(Ref());
1248
+ state->Start(Ref(DEBUG_LOCATION, "ResourceState"));
1316
1249
  }
1317
1250
  }
1318
1251
  return resource_names;
@@ -1339,21 +1272,23 @@ void XdsClient::ChannelState::LrsCallState::Reporter::
1339
1272
  void XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimer(
1340
1273
  void* arg, grpc_error* error) {
1341
1274
  Reporter* self = static_cast<Reporter*>(arg);
1342
- GRPC_ERROR_REF(error); // ref owned by lambda
1343
- self->xds_client()->work_serializer_->Run(
1344
- [self, error]() { self->OnNextReportTimerLocked(error); },
1345
- DEBUG_LOCATION);
1275
+ bool done;
1276
+ {
1277
+ MutexLock lock(&self->xds_client()->mu_);
1278
+ done = self->OnNextReportTimerLocked(GRPC_ERROR_REF(error));
1279
+ }
1280
+ if (done) self->Unref(DEBUG_LOCATION, "Reporter+timer");
1346
1281
  }
1347
1282
 
1348
- void XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimerLocked(
1283
+ bool XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimerLocked(
1349
1284
  grpc_error* error) {
1350
1285
  next_report_timer_callback_pending_ = false;
1351
1286
  if (error != GRPC_ERROR_NONE || !IsCurrentReporterOnCall()) {
1352
- Unref(DEBUG_LOCATION, "Reporter+timer");
1353
- } else {
1354
- SendReportLocked();
1287
+ GRPC_ERROR_UNREF(error);
1288
+ return true;
1355
1289
  }
1356
- GRPC_ERROR_UNREF(error);
1290
+ SendReportLocked();
1291
+ return false;
1357
1292
  }
1358
1293
 
1359
1294
  namespace {
@@ -1361,9 +1296,7 @@ namespace {
1361
1296
  bool LoadReportCountersAreZero(const XdsApi::ClusterLoadReportMap& snapshot) {
1362
1297
  for (const auto& p : snapshot) {
1363
1298
  const XdsApi::ClusterLoadReport& cluster_snapshot = p.second;
1364
- for (const auto& q : cluster_snapshot.dropped_requests) {
1365
- if (q.second > 0) return false;
1366
- }
1299
+ if (!cluster_snapshot.dropped_requests.IsZero()) return false;
1367
1300
  for (const auto& q : cluster_snapshot.locality_stats) {
1368
1301
  const XdsClusterLocalityStats::Snapshot& locality_snapshot = q.second;
1369
1302
  if (!locality_snapshot.IsZero()) return false;
@@ -1376,8 +1309,9 @@ bool LoadReportCountersAreZero(const XdsApi::ClusterLoadReportMap& snapshot) {
1376
1309
 
1377
1310
  void XdsClient::ChannelState::LrsCallState::Reporter::SendReportLocked() {
1378
1311
  // Construct snapshot from all reported stats.
1379
- XdsApi::ClusterLoadReportMap snapshot = xds_client()->BuildLoadReportSnapshot(
1380
- parent_->send_all_clusters_, parent_->cluster_names_);
1312
+ XdsApi::ClusterLoadReportMap snapshot =
1313
+ xds_client()->BuildLoadReportSnapshotLocked(parent_->send_all_clusters_,
1314
+ parent_->cluster_names_);
1381
1315
  // Skip client load report if the counters were all zero in the last
1382
1316
  // report and they are still zero in this one.
1383
1317
  const bool old_val = last_report_counters_were_zero_;
@@ -1410,32 +1344,35 @@ void XdsClient::ChannelState::LrsCallState::Reporter::SendReportLocked() {
1410
1344
  void XdsClient::ChannelState::LrsCallState::Reporter::OnReportDone(
1411
1345
  void* arg, grpc_error* error) {
1412
1346
  Reporter* self = static_cast<Reporter*>(arg);
1413
- GRPC_ERROR_REF(error); // ref owned by lambda
1414
- self->xds_client()->work_serializer_->Run(
1415
- [self, error]() { self->OnReportDoneLocked(error); }, DEBUG_LOCATION);
1347
+ bool done;
1348
+ {
1349
+ MutexLock lock(&self->xds_client()->mu_);
1350
+ done = self->OnReportDoneLocked(GRPC_ERROR_REF(error));
1351
+ }
1352
+ if (done) self->Unref(DEBUG_LOCATION, "Reporter+report_done");
1416
1353
  }
1417
1354
 
1418
- void XdsClient::ChannelState::LrsCallState::Reporter::OnReportDoneLocked(
1355
+ bool XdsClient::ChannelState::LrsCallState::Reporter::OnReportDoneLocked(
1419
1356
  grpc_error* error) {
1420
1357
  grpc_byte_buffer_destroy(parent_->send_message_payload_);
1421
1358
  parent_->send_message_payload_ = nullptr;
1422
1359
  // If there are no more registered stats to report, cancel the call.
1423
1360
  if (xds_client()->load_report_map_.empty()) {
1424
1361
  parent_->chand()->StopLrsCall();
1425
- Unref(DEBUG_LOCATION, "Reporter+report_done+no_more_reporters");
1426
- return;
1362
+ GRPC_ERROR_UNREF(error);
1363
+ return true;
1427
1364
  }
1428
1365
  if (error != GRPC_ERROR_NONE || !IsCurrentReporterOnCall()) {
1366
+ GRPC_ERROR_UNREF(error);
1429
1367
  // If this reporter is no longer the current one on the call, the reason
1430
1368
  // might be that it was orphaned for a new one due to config update.
1431
1369
  if (!IsCurrentReporterOnCall()) {
1432
1370
  parent_->MaybeStartReportingLocked();
1433
1371
  }
1434
- Unref(DEBUG_LOCATION, "Reporter+report_done");
1435
- } else {
1436
- ScheduleNextReportLocked();
1372
+ return true;
1437
1373
  }
1438
- GRPC_ERROR_UNREF(error);
1374
+ ScheduleNextReportLocked();
1375
+ return false;
1439
1376
  }
1440
1377
 
1441
1378
  //
@@ -1450,7 +1387,6 @@ XdsClient::ChannelState::LrsCallState::LrsCallState(
1450
1387
  // activity in xds_client()->interested_parties_, which is comprised of
1451
1388
  // the polling entities from client_channel.
1452
1389
  GPR_ASSERT(xds_client() != nullptr);
1453
- GPR_ASSERT(!xds_client()->server_name_.empty());
1454
1390
  const auto& method =
1455
1391
  xds_client()->bootstrap_->server().ShouldUseV3()
1456
1392
  ? GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V3_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS
@@ -1462,7 +1398,7 @@ XdsClient::ChannelState::LrsCallState::LrsCallState(
1462
1398
  GPR_ASSERT(call_ != nullptr);
1463
1399
  // Init the request payload.
1464
1400
  grpc_slice request_payload_slice =
1465
- xds_client()->api_.CreateLrsInitialRequest(xds_client()->server_name_);
1401
+ xds_client()->api_.CreateLrsInitialRequest();
1466
1402
  send_message_payload_ =
1467
1403
  grpc_raw_byte_buffer_create(&request_payload_slice, 1);
1468
1404
  grpc_slice_unref_internal(request_payload_slice);
@@ -1586,9 +1522,11 @@ void XdsClient::ChannelState::LrsCallState::MaybeStartReportingLocked() {
1586
1522
  void XdsClient::ChannelState::LrsCallState::OnInitialRequestSent(
1587
1523
  void* arg, grpc_error* /*error*/) {
1588
1524
  LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
1589
- lrs_calld->xds_client()->work_serializer_->Run(
1590
- [lrs_calld]() { lrs_calld->OnInitialRequestSentLocked(); },
1591
- DEBUG_LOCATION);
1525
+ {
1526
+ MutexLock lock(&lrs_calld->xds_client()->mu_);
1527
+ lrs_calld->OnInitialRequestSentLocked();
1528
+ }
1529
+ lrs_calld->Unref(DEBUG_LOCATION, "LRS+OnInitialRequestSentLocked");
1592
1530
  }
1593
1531
 
1594
1532
  void XdsClient::ChannelState::LrsCallState::OnInitialRequestSentLocked() {
@@ -1596,21 +1534,23 @@ void XdsClient::ChannelState::LrsCallState::OnInitialRequestSentLocked() {
1596
1534
  grpc_byte_buffer_destroy(send_message_payload_);
1597
1535
  send_message_payload_ = nullptr;
1598
1536
  MaybeStartReportingLocked();
1599
- Unref(DEBUG_LOCATION, "LRS+OnInitialRequestSentLocked");
1600
1537
  }
1601
1538
 
1602
1539
  void XdsClient::ChannelState::LrsCallState::OnResponseReceived(
1603
1540
  void* arg, grpc_error* /*error*/) {
1604
1541
  LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
1605
- lrs_calld->xds_client()->work_serializer_->Run(
1606
- [lrs_calld]() { lrs_calld->OnResponseReceivedLocked(); }, DEBUG_LOCATION);
1542
+ bool done;
1543
+ {
1544
+ MutexLock lock(&lrs_calld->xds_client()->mu_);
1545
+ done = lrs_calld->OnResponseReceivedLocked();
1546
+ }
1547
+ if (done) lrs_calld->Unref(DEBUG_LOCATION, "LRS+OnResponseReceivedLocked");
1607
1548
  }
1608
1549
 
1609
- void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() {
1550
+ bool XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() {
1610
1551
  // Empty payload means the call was cancelled.
1611
1552
  if (!IsCurrentCallOnChannel() || recv_message_payload_ == nullptr) {
1612
- Unref(DEBUG_LOCATION, "LRS+OnResponseReceivedLocked");
1613
- return;
1553
+ return true;
1614
1554
  }
1615
1555
  // Read the response.
1616
1556
  grpc_byte_buffer_reader bbr;
@@ -1683,10 +1623,7 @@ void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() {
1683
1623
  MaybeStartReportingLocked();
1684
1624
  }();
1685
1625
  grpc_slice_unref_internal(response_slice);
1686
- if (xds_client()->shutting_down_) {
1687
- Unref(DEBUG_LOCATION, "LRS+OnResponseReceivedLocked+xds_shutdown");
1688
- return;
1689
- }
1626
+ if (xds_client()->shutting_down_) return true;
1690
1627
  // Keep listening for LRS config updates.
1691
1628
  grpc_op op;
1692
1629
  memset(&op, 0, sizeof(op));
@@ -1699,15 +1636,17 @@ void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() {
1699
1636
  const grpc_call_error call_error =
1700
1637
  grpc_call_start_batch_and_execute(call_, &op, 1, &on_response_received_);
1701
1638
  GPR_ASSERT(GRPC_CALL_OK == call_error);
1639
+ return false;
1702
1640
  }
1703
1641
 
1704
1642
  void XdsClient::ChannelState::LrsCallState::OnStatusReceived(
1705
1643
  void* arg, grpc_error* error) {
1706
1644
  LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
1707
- GRPC_ERROR_REF(error); // ref owned by lambda
1708
- lrs_calld->xds_client()->work_serializer_->Run(
1709
- [lrs_calld, error]() { lrs_calld->OnStatusReceivedLocked(error); },
1710
- DEBUG_LOCATION);
1645
+ {
1646
+ MutexLock lock(&lrs_calld->xds_client()->mu_);
1647
+ lrs_calld->OnStatusReceivedLocked(GRPC_ERROR_REF(error));
1648
+ }
1649
+ lrs_calld->Unref(DEBUG_LOCATION, "LRS+OnStatusReceivedLocked");
1711
1650
  }
1712
1651
 
1713
1652
  void XdsClient::ChannelState::LrsCallState::OnStatusReceivedLocked(
@@ -1728,7 +1667,6 @@ void XdsClient::ChannelState::LrsCallState::OnStatusReceivedLocked(
1728
1667
  // Try to restart the call.
1729
1668
  parent_->OnCallFinishedLocked();
1730
1669
  }
1731
- Unref(DEBUG_LOCATION, "LRS+OnStatusReceivedLocked");
1732
1670
  GRPC_ERROR_UNREF(error);
1733
1671
  }
1734
1672
 
@@ -1745,28 +1683,62 @@ bool XdsClient::ChannelState::LrsCallState::IsCurrentCallOnChannel() const {
1745
1683
 
1746
1684
  namespace {
1747
1685
 
1748
- grpc_millis GetRequestTimeout(const grpc_channel_args& args) {
1686
+ grpc_millis GetRequestTimeout() {
1749
1687
  return grpc_channel_args_find_integer(
1750
- &args, GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS,
1688
+ g_channel_args, GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS,
1751
1689
  {15000, 0, INT_MAX});
1752
1690
  }
1753
1691
 
1692
+ grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
1693
+ grpc_error** error) {
1694
+ // Build channel args.
1695
+ absl::InlinedVector<grpc_arg, 2> args_to_add = {
1696
+ grpc_channel_arg_integer_create(
1697
+ const_cast<char*>(GRPC_ARG_KEEPALIVE_TIME_MS),
1698
+ 5 * 60 * GPR_MS_PER_SEC),
1699
+ grpc_channel_arg_integer_create(
1700
+ const_cast<char*>(GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL), 1),
1701
+ };
1702
+ grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
1703
+ g_channel_args, args_to_add.data(), args_to_add.size());
1704
+ // Find credentials and create channel.
1705
+ RefCountedPtr<grpc_channel_credentials> creds;
1706
+ for (const auto& channel_creds : bootstrap.server().channel_creds) {
1707
+ if (channel_creds.type == "google_default") {
1708
+ creds.reset(grpc_google_default_credentials_create(nullptr));
1709
+ break;
1710
+ }
1711
+ if (channel_creds.type == "insecure") {
1712
+ grpc_channel* channel = grpc_insecure_channel_create(
1713
+ bootstrap.server().server_uri.c_str(), new_args, nullptr);
1714
+ grpc_channel_args_destroy(new_args);
1715
+ return channel;
1716
+ }
1717
+ if (channel_creds.type == "fake") {
1718
+ creds.reset(grpc_fake_transport_security_credentials_create());
1719
+ break;
1720
+ }
1721
+ }
1722
+ if (creds == nullptr) {
1723
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1724
+ "no supported credential types found");
1725
+ return nullptr;
1726
+ }
1727
+ grpc_channel* channel = grpc_secure_channel_create(
1728
+ creds.get(), bootstrap.server().server_uri.c_str(), new_args, nullptr);
1729
+ grpc_channel_args_destroy(new_args);
1730
+ return channel;
1731
+ }
1732
+
1754
1733
  } // namespace
1755
1734
 
1756
- XdsClient::XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
1757
- grpc_pollset_set* interested_parties,
1758
- absl::string_view server_name,
1759
- std::unique_ptr<ListenerWatcherInterface> watcher,
1760
- const grpc_channel_args& channel_args, grpc_error** error)
1761
- : InternallyRefCounted<XdsClient>(&grpc_xds_client_trace),
1762
- request_timeout_(GetRequestTimeout(channel_args)),
1763
- work_serializer_(std::move(work_serializer)),
1764
- interested_parties_(interested_parties),
1735
+ XdsClient::XdsClient(grpc_error** error)
1736
+ : DualRefCounted<XdsClient>(&grpc_xds_client_trace),
1737
+ request_timeout_(GetRequestTimeout()),
1738
+ interested_parties_(grpc_pollset_set_create()),
1765
1739
  bootstrap_(
1766
1740
  XdsBootstrap::ReadFromFile(this, &grpc_xds_client_trace, error)),
1767
- api_(this, &grpc_xds_client_trace, bootstrap_.get()),
1768
- server_name_(server_name),
1769
- listener_watcher_(std::move(watcher)) {
1741
+ api_(this, &grpc_xds_client_trace, bootstrap_.get()) {
1770
1742
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1771
1743
  gpr_log(GPR_INFO, "[xds_client %p] creating xds client", this);
1772
1744
  }
@@ -1779,54 +1751,156 @@ XdsClient::XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
1779
1751
  gpr_log(GPR_INFO, "[xds_client %p] creating channel to %s", this,
1780
1752
  bootstrap_->server().server_uri.c_str());
1781
1753
  }
1782
- grpc_channel_args* new_args = BuildXdsChannelArgs(channel_args);
1783
- grpc_channel* channel = CreateXdsChannel(*bootstrap_, *new_args, error);
1784
- grpc_channel_args_destroy(new_args);
1754
+ grpc_channel* channel = CreateXdsChannel(*bootstrap_, error);
1785
1755
  if (*error != GRPC_ERROR_NONE) {
1786
1756
  gpr_log(GPR_ERROR, "[xds_client %p] failed to create xds channel: %s", this,
1787
1757
  grpc_error_string(*error));
1788
1758
  return;
1789
1759
  }
1760
+ // Create ChannelState object.
1790
1761
  chand_ = MakeOrphanable<ChannelState>(
1791
- Ref(DEBUG_LOCATION, "XdsClient+ChannelState"), channel);
1792
- if (listener_watcher_ != nullptr) {
1793
- chand_->Subscribe(XdsApi::kLdsTypeUrl, std::string(server_name));
1794
- }
1762
+ WeakRef(DEBUG_LOCATION, "XdsClient+ChannelState"), channel);
1795
1763
  }
1796
1764
 
1797
1765
  XdsClient::~XdsClient() {
1798
1766
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1799
1767
  gpr_log(GPR_INFO, "[xds_client %p] destroying xds client", this);
1800
1768
  }
1769
+ grpc_pollset_set_destroy(interested_parties_);
1770
+ }
1771
+
1772
+ void XdsClient::AddChannelzLinkage(
1773
+ channelz::ChannelNode* parent_channelz_node) {
1774
+ channelz::ChannelNode* xds_channelz_node =
1775
+ grpc_channel_get_channelz_node(chand_->channel());
1776
+ if (xds_channelz_node != nullptr) {
1777
+ parent_channelz_node->AddChildChannel(xds_channelz_node->uuid());
1778
+ }
1779
+ }
1780
+
1781
+ void XdsClient::RemoveChannelzLinkage(
1782
+ channelz::ChannelNode* parent_channelz_node) {
1783
+ channelz::ChannelNode* xds_channelz_node =
1784
+ grpc_channel_get_channelz_node(chand_->channel());
1785
+ if (xds_channelz_node != nullptr) {
1786
+ parent_channelz_node->RemoveChildChannel(xds_channelz_node->uuid());
1787
+ }
1801
1788
  }
1802
1789
 
1803
1790
  void XdsClient::Orphan() {
1804
1791
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1805
1792
  gpr_log(GPR_INFO, "[xds_client %p] shutting down xds client", this);
1806
1793
  }
1807
- shutting_down_ = true;
1808
- chand_.reset();
1809
- // We do not clear cluster_map_ and endpoint_map_ if the xds client was
1810
- // created by the XdsResolver because the maps contain refs for watchers which
1811
- // in turn hold refs to the loadbalancing policies. At this point, it is
1812
- // possible for ADS calls to be in progress. Unreffing the loadbalancing
1813
- // policies before those calls are done would lead to issues such as
1814
- // https://github.com/grpc/grpc/issues/20928.
1815
- if (listener_watcher_ != nullptr) {
1816
- cluster_map_.clear();
1817
- endpoint_map_.clear();
1794
+ {
1795
+ MutexLock lock(g_mu);
1796
+ if (g_xds_client == this) g_xds_client = nullptr;
1797
+ }
1798
+ {
1799
+ MutexLock lock(&mu_);
1800
+ shutting_down_ = true;
1801
+ // Orphan ChannelState object.
1802
+ chand_.reset();
1803
+ // We do not clear cluster_map_ and endpoint_map_ if the xds client was
1804
+ // created by the XdsResolver because the maps contain refs for watchers
1805
+ // which in turn hold refs to the loadbalancing policies. At this point, it
1806
+ // is possible for ADS calls to be in progress. Unreffing the loadbalancing
1807
+ // policies before those calls are done would lead to issues such as
1808
+ // https://github.com/grpc/grpc/issues/20928.
1809
+ if (!listener_map_.empty()) {
1810
+ cluster_map_.clear();
1811
+ endpoint_map_.clear();
1812
+ }
1813
+ }
1814
+ }
1815
+
1816
+ void XdsClient::WatchListenerData(
1817
+ absl::string_view listener_name,
1818
+ std::unique_ptr<ListenerWatcherInterface> watcher) {
1819
+ std::string listener_name_str = std::string(listener_name);
1820
+ MutexLock lock(&mu_);
1821
+ ListenerState& listener_state = listener_map_[listener_name_str];
1822
+ ListenerWatcherInterface* w = watcher.get();
1823
+ listener_state.watchers[w] = std::move(watcher);
1824
+ // If we've already received an LDS update, notify the new watcher
1825
+ // immediately.
1826
+ if (listener_state.update.has_value()) {
1827
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1828
+ gpr_log(GPR_INFO, "[xds_client %p] returning cached listener data for %s",
1829
+ this, listener_name_str.c_str());
1830
+ }
1831
+ w->OnListenerChanged(*listener_state.update);
1832
+ }
1833
+ chand_->Subscribe(XdsApi::kLdsTypeUrl, listener_name_str);
1834
+ }
1835
+
1836
+ void XdsClient::CancelListenerDataWatch(absl::string_view listener_name,
1837
+ ListenerWatcherInterface* watcher,
1838
+ bool delay_unsubscription) {
1839
+ MutexLock lock(&mu_);
1840
+ if (shutting_down_) return;
1841
+ std::string listener_name_str = std::string(listener_name);
1842
+ ListenerState& listener_state = listener_map_[listener_name_str];
1843
+ auto it = listener_state.watchers.find(watcher);
1844
+ if (it != listener_state.watchers.end()) {
1845
+ listener_state.watchers.erase(it);
1846
+ if (listener_state.watchers.empty()) {
1847
+ listener_map_.erase(listener_name_str);
1848
+ chand_->Unsubscribe(XdsApi::kLdsTypeUrl, listener_name_str,
1849
+ delay_unsubscription);
1850
+ }
1851
+ }
1852
+ }
1853
+
1854
+ void XdsClient::WatchRouteConfigData(
1855
+ absl::string_view route_config_name,
1856
+ std::unique_ptr<RouteConfigWatcherInterface> watcher) {
1857
+ std::string route_config_name_str = std::string(route_config_name);
1858
+ MutexLock lock(&mu_);
1859
+ RouteConfigState& route_config_state =
1860
+ route_config_map_[route_config_name_str];
1861
+ RouteConfigWatcherInterface* w = watcher.get();
1862
+ route_config_state.watchers[w] = std::move(watcher);
1863
+ // If we've already received an RDS update, notify the new watcher
1864
+ // immediately.
1865
+ if (route_config_state.update.has_value()) {
1866
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
1867
+ gpr_log(GPR_INFO,
1868
+ "[xds_client %p] returning cached route config data for %s", this,
1869
+ route_config_name_str.c_str());
1870
+ }
1871
+ w->OnRouteConfigChanged(*route_config_state.update);
1872
+ }
1873
+ chand_->Subscribe(XdsApi::kRdsTypeUrl, route_config_name_str);
1874
+ }
1875
+
1876
+ void XdsClient::CancelRouteConfigDataWatch(absl::string_view route_config_name,
1877
+ RouteConfigWatcherInterface* watcher,
1878
+ bool delay_unsubscription) {
1879
+ MutexLock lock(&mu_);
1880
+ if (shutting_down_) return;
1881
+ std::string route_config_name_str = std::string(route_config_name);
1882
+ RouteConfigState& route_config_state =
1883
+ route_config_map_[route_config_name_str];
1884
+ auto it = route_config_state.watchers.find(watcher);
1885
+ if (it != route_config_state.watchers.end()) {
1886
+ route_config_state.watchers.erase(it);
1887
+ if (route_config_state.watchers.empty()) {
1888
+ route_config_map_.erase(route_config_name_str);
1889
+ chand_->Unsubscribe(XdsApi::kRdsTypeUrl, route_config_name_str,
1890
+ delay_unsubscription);
1891
+ }
1818
1892
  }
1819
- Unref(DEBUG_LOCATION, "XdsClient::Orphan()");
1820
1893
  }
1821
1894
 
1822
1895
  void XdsClient::WatchClusterData(
1823
1896
  absl::string_view cluster_name,
1824
1897
  std::unique_ptr<ClusterWatcherInterface> watcher) {
1825
1898
  std::string cluster_name_str = std::string(cluster_name);
1899
+ MutexLock lock(&mu_);
1826
1900
  ClusterState& cluster_state = cluster_map_[cluster_name_str];
1827
1901
  ClusterWatcherInterface* w = watcher.get();
1828
1902
  cluster_state.watchers[w] = std::move(watcher);
1829
- // If we've already received an CDS update, notify the new watcher
1903
+ // If we've already received a CDS update, notify the new watcher
1830
1904
  // immediately.
1831
1905
  if (cluster_state.update.has_value()) {
1832
1906
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
@@ -1841,6 +1915,7 @@ void XdsClient::WatchClusterData(
1841
1915
  void XdsClient::CancelClusterDataWatch(absl::string_view cluster_name,
1842
1916
  ClusterWatcherInterface* watcher,
1843
1917
  bool delay_unsubscription) {
1918
+ MutexLock lock(&mu_);
1844
1919
  if (shutting_down_) return;
1845
1920
  std::string cluster_name_str = std::string(cluster_name);
1846
1921
  ClusterState& cluster_state = cluster_map_[cluster_name_str];
@@ -1859,6 +1934,7 @@ void XdsClient::WatchEndpointData(
1859
1934
  absl::string_view eds_service_name,
1860
1935
  std::unique_ptr<EndpointWatcherInterface> watcher) {
1861
1936
  std::string eds_service_name_str = std::string(eds_service_name);
1937
+ MutexLock lock(&mu_);
1862
1938
  EndpointState& endpoint_state = endpoint_map_[eds_service_name_str];
1863
1939
  EndpointWatcherInterface* w = watcher.get();
1864
1940
  endpoint_state.watchers[w] = std::move(watcher);
@@ -1877,6 +1953,7 @@ void XdsClient::WatchEndpointData(
1877
1953
  void XdsClient::CancelEndpointDataWatch(absl::string_view eds_service_name,
1878
1954
  EndpointWatcherInterface* watcher,
1879
1955
  bool delay_unsubscription) {
1956
+ MutexLock lock(&mu_);
1880
1957
  if (shutting_down_) return;
1881
1958
  std::string eds_service_name_str = std::string(eds_service_name);
1882
1959
  EndpointState& endpoint_state = endpoint_map_[eds_service_name_str];
@@ -1898,6 +1975,7 @@ RefCountedPtr<XdsClusterDropStats> XdsClient::AddClusterDropStats(
1898
1975
  // server name specified in lrs_server.
1899
1976
  auto key =
1900
1977
  std::make_pair(std::string(cluster_name), std::string(eds_service_name));
1978
+ MutexLock lock(&mu_);
1901
1979
  // We jump through some hoops here to make sure that the absl::string_views
1902
1980
  // stored in the XdsClusterDropStats object point to the strings
1903
1981
  // in the load_report_map_ key, so that they have the same lifetime.
@@ -1916,6 +1994,7 @@ void XdsClient::RemoveClusterDropStats(
1916
1994
  absl::string_view /*lrs_server*/, absl::string_view cluster_name,
1917
1995
  absl::string_view eds_service_name,
1918
1996
  XdsClusterDropStats* cluster_drop_stats) {
1997
+ MutexLock lock(&mu_);
1919
1998
  auto load_report_it = load_report_map_.find(
1920
1999
  std::make_pair(std::string(cluster_name), std::string(eds_service_name)));
1921
2000
  if (load_report_it == load_report_map_.end()) return;
@@ -1926,9 +2005,8 @@ void XdsClient::RemoveClusterDropStats(
1926
2005
  if (it != load_report_state.drop_stats.end()) {
1927
2006
  // Record final drop stats in deleted_drop_stats, which will be
1928
2007
  // added to the next load report.
1929
- for (const auto& p : cluster_drop_stats->GetSnapshotAndReset()) {
1930
- load_report_state.deleted_drop_stats[p.first] += p.second;
1931
- }
2008
+ auto dropped_requests = cluster_drop_stats->GetSnapshotAndReset();
2009
+ load_report_state.deleted_drop_stats += dropped_requests;
1932
2010
  load_report_state.drop_stats.erase(it);
1933
2011
  }
1934
2012
  }
@@ -1941,6 +2019,7 @@ RefCountedPtr<XdsClusterLocalityStats> XdsClient::AddClusterLocalityStats(
1941
2019
  // server name specified in lrs_server.
1942
2020
  auto key =
1943
2021
  std::make_pair(std::string(cluster_name), std::string(eds_service_name));
2022
+ MutexLock lock(&mu_);
1944
2023
  // We jump through some hoops here to make sure that the absl::string_views
1945
2024
  // stored in the XdsClusterLocalityStats object point to the strings
1946
2025
  // in the load_report_map_ key, so that they have the same lifetime.
@@ -1962,6 +2041,7 @@ void XdsClient::RemoveClusterLocalityStats(
1962
2041
  absl::string_view eds_service_name,
1963
2042
  const RefCountedPtr<XdsLocalityName>& locality,
1964
2043
  XdsClusterLocalityStats* cluster_locality_stats) {
2044
+ MutexLock lock(&mu_);
1965
2045
  auto load_report_it = load_report_map_.find(
1966
2046
  std::make_pair(std::string(cluster_name), std::string(eds_service_name)));
1967
2047
  if (load_report_it == load_report_map_.end()) return;
@@ -1982,12 +2062,41 @@ void XdsClient::RemoveClusterLocalityStats(
1982
2062
  }
1983
2063
 
1984
2064
  void XdsClient::ResetBackoff() {
2065
+ MutexLock lock(&mu_);
1985
2066
  if (chand_ != nullptr) {
1986
2067
  grpc_channel_reset_connect_backoff(chand_->channel());
1987
2068
  }
1988
2069
  }
1989
2070
 
1990
- XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshot(
2071
+ void XdsClient::NotifyOnErrorLocked(grpc_error* error) {
2072
+ for (const auto& p : listener_map_) {
2073
+ const ListenerState& listener_state = p.second;
2074
+ for (const auto& p : listener_state.watchers) {
2075
+ p.first->OnError(GRPC_ERROR_REF(error));
2076
+ }
2077
+ }
2078
+ for (const auto& p : route_config_map_) {
2079
+ const RouteConfigState& route_config_state = p.second;
2080
+ for (const auto& p : route_config_state.watchers) {
2081
+ p.first->OnError(GRPC_ERROR_REF(error));
2082
+ }
2083
+ }
2084
+ for (const auto& p : cluster_map_) {
2085
+ const ClusterState& cluster_state = p.second;
2086
+ for (const auto& p : cluster_state.watchers) {
2087
+ p.first->OnError(GRPC_ERROR_REF(error));
2088
+ }
2089
+ }
2090
+ for (const auto& p : endpoint_map_) {
2091
+ const EndpointState& endpoint_state = p.second;
2092
+ for (const auto& p : endpoint_state.watchers) {
2093
+ p.first->OnError(GRPC_ERROR_REF(error));
2094
+ }
2095
+ }
2096
+ GRPC_ERROR_UNREF(error);
2097
+ }
2098
+
2099
+ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshotLocked(
1991
2100
  bool send_all_clusters, const std::set<std::string>& clusters) {
1992
2101
  XdsApi::ClusterLoadReportMap snapshot_map;
1993
2102
  for (auto load_report_it = load_report_map_.begin();
@@ -2008,9 +2117,8 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshot(
2008
2117
  // Aggregate drop stats.
2009
2118
  snapshot.dropped_requests = std::move(load_report.deleted_drop_stats);
2010
2119
  for (auto& drop_stats : load_report.drop_stats) {
2011
- for (const auto& p : drop_stats->GetSnapshotAndReset()) {
2012
- snapshot.dropped_requests[p.first] += p.second;
2013
- }
2120
+ auto dropped_requests = drop_stats->GetSnapshotAndReset();
2121
+ snapshot.dropped_requests += dropped_requests;
2014
2122
  }
2015
2123
  // Aggregate locality stats.
2016
2124
  for (auto it = load_report.locality_stats.begin();
@@ -2055,60 +2163,40 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshot(
2055
2163
  return snapshot_map;
2056
2164
  }
2057
2165
 
2058
- void XdsClient::NotifyOnError(grpc_error* error) {
2059
- if (listener_watcher_ != nullptr) {
2060
- listener_watcher_->OnError(GRPC_ERROR_REF(error));
2061
- }
2062
- for (const auto& p : cluster_map_) {
2063
- const ClusterState& cluster_state = p.second;
2064
- for (const auto& p : cluster_state.watchers) {
2065
- p.first->OnError(GRPC_ERROR_REF(error));
2066
- }
2067
- }
2068
- for (const auto& p : endpoint_map_) {
2069
- const EndpointState& endpoint_state = p.second;
2070
- for (const auto& p : endpoint_state.watchers) {
2071
- p.first->OnError(GRPC_ERROR_REF(error));
2072
- }
2073
- }
2074
- GRPC_ERROR_UNREF(error);
2075
- }
2166
+ //
2167
+ // accessors for global state
2168
+ //
2076
2169
 
2077
- void* XdsClient::ChannelArgCopy(void* p) {
2078
- XdsClient* xds_client = static_cast<XdsClient*>(p);
2079
- xds_client->Ref(DEBUG_LOCATION, "channel arg").release();
2080
- return p;
2081
- }
2170
+ void XdsClientGlobalInit() { g_mu = new Mutex; }
2082
2171
 
2083
- void XdsClient::ChannelArgDestroy(void* p) {
2084
- XdsClient* xds_client = static_cast<XdsClient*>(p);
2085
- xds_client->Unref(DEBUG_LOCATION, "channel arg");
2172
+ void XdsClientGlobalShutdown() {
2173
+ delete g_mu;
2174
+ g_mu = nullptr;
2086
2175
  }
2087
2176
 
2088
- int XdsClient::ChannelArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
2177
+ RefCountedPtr<XdsClient> XdsClient::GetOrCreate(grpc_error** error) {
2178
+ MutexLock lock(g_mu);
2179
+ if (g_xds_client != nullptr) {
2180
+ auto xds_client = g_xds_client->RefIfNonZero();
2181
+ if (xds_client != nullptr) return xds_client;
2182
+ }
2183
+ auto xds_client = MakeRefCounted<XdsClient>(error);
2184
+ g_xds_client = xds_client.get();
2185
+ return xds_client;
2186
+ }
2089
2187
 
2090
- const grpc_arg_pointer_vtable XdsClient::kXdsClientVtable = {
2091
- XdsClient::ChannelArgCopy, XdsClient::ChannelArgDestroy,
2092
- XdsClient::ChannelArgCmp};
2188
+ namespace internal {
2093
2189
 
2094
- grpc_arg XdsClient::MakeChannelArg() const {
2095
- return grpc_channel_arg_pointer_create(const_cast<char*>(GRPC_ARG_XDS_CLIENT),
2096
- const_cast<XdsClient*>(this),
2097
- &XdsClient::kXdsClientVtable);
2190
+ void SetXdsChannelArgsForTest(grpc_channel_args* args) {
2191
+ MutexLock lock(g_mu);
2192
+ g_channel_args = args;
2098
2193
  }
2099
2194
 
2100
- RefCountedPtr<XdsClient> XdsClient::GetFromChannelArgs(
2101
- const grpc_channel_args& args) {
2102
- XdsClient* xds_client =
2103
- grpc_channel_args_find_pointer<XdsClient>(&args, GRPC_ARG_XDS_CLIENT);
2104
- if (xds_client != nullptr) return xds_client->Ref();
2105
- return nullptr;
2195
+ void UnsetGlobalXdsClientForTest() {
2196
+ MutexLock lock(g_mu);
2197
+ g_xds_client = nullptr;
2106
2198
  }
2107
2199
 
2108
- grpc_channel_args* XdsClient::RemoveFromChannelArgs(
2109
- const grpc_channel_args& args) {
2110
- const char* arg_name = GRPC_ARG_XDS_CLIENT;
2111
- return grpc_channel_args_copy_and_remove(&args, &arg_name, 1);
2112
- }
2200
+ } // namespace internal
2113
2201
 
2114
2202
  } // namespace grpc_core