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
@@ -23,7 +23,9 @@
23
23
  #include <string.h>
24
24
 
25
25
  #include "absl/container/inlined_vector.h"
26
+ #include "absl/strings/str_cat.h"
26
27
  #include "absl/strings/str_format.h"
28
+ #include "absl/strings/str_join.h"
27
29
 
28
30
  #include "src/core/lib/gpr/string.h"
29
31
 
@@ -126,6 +128,7 @@ grpc_error* ParseLoadBalancingConfigHelper(
126
128
  return GRPC_ERROR_CREATE_FROM_STATIC_STRING("type should be array");
127
129
  }
128
130
  // Find the first LB policy that this client supports.
131
+ std::vector<absl::string_view> policies_tried;
129
132
  for (const Json& lb_config : lb_config_array.array_value()) {
130
133
  if (lb_config.type() != Json::Type::OBJECT) {
131
134
  return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@@ -149,8 +152,12 @@ grpc_error* ParseLoadBalancingConfigHelper(
149
152
  *result = it;
150
153
  return GRPC_ERROR_NONE;
151
154
  }
155
+ policies_tried.push_back(it->first);
152
156
  }
153
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No known policy");
157
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
158
+ absl::StrCat("No known policies in list: ",
159
+ absl::StrJoin(policies_tried, " "))
160
+ .c_str());
154
161
  }
155
162
 
156
163
  } // namespace
@@ -352,7 +352,7 @@ void AresDnsResolver::OnResolvedLocked(grpc_error* error) {
352
352
  GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s",
353
353
  this, service_config_string.c_str());
354
354
  result.service_config = ServiceConfig::Create(
355
- service_config_string, &result.service_config_error);
355
+ channel_args_, service_config_string, &result.service_config_error);
356
356
  }
357
357
  }
358
358
  absl::InlinedVector<grpc_arg, 1> new_args;
@@ -18,18 +18,25 @@
18
18
 
19
19
  #include <grpc/support/port_platform.h>
20
20
 
21
+ #include "absl/strings/match.h"
21
22
  #include "absl/strings/str_join.h"
23
+ #include "absl/strings/str_split.h"
24
+ #include "re2/re2.h"
22
25
 
23
26
  #include "src/core/ext/filters/client_channel/config_selector.h"
24
27
  #include "src/core/ext/filters/client_channel/resolver_registry.h"
25
28
  #include "src/core/ext/xds/xds_client.h"
26
29
  #include "src/core/lib/channel/channel_args.h"
30
+ #include "src/core/lib/iomgr/closure.h"
31
+ #include "src/core/lib/iomgr/exec_ctx.h"
27
32
  #include "src/core/lib/transport/timeout_encoding.h"
28
33
 
29
34
  namespace grpc_core {
30
35
 
31
36
  TraceFlag grpc_xds_resolver_trace(false, "xds_resolver");
32
37
 
38
+ const char* kXdsClusterAttribute = "xds_cluster_name";
39
+
33
40
  namespace {
34
41
 
35
42
  //
@@ -42,8 +49,7 @@ class XdsResolver : public Resolver {
42
49
  : Resolver(std::move(args.work_serializer),
43
50
  std::move(args.result_handler)),
44
51
  args_(grpc_channel_args_copy(args.args)),
45
- interested_parties_(args.pollset_set),
46
- config_selector_(MakeRefCounted<XdsConfigSelector>()) {
52
+ interested_parties_(args.pollset_set) {
47
53
  char* path = args.uri->path;
48
54
  if (path[0] == '/') ++path;
49
55
  server_name_ = path;
@@ -62,124 +68,443 @@ class XdsResolver : public Resolver {
62
68
 
63
69
  void StartLocked() override;
64
70
 
65
- void ShutdownLocked() override {
66
- if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
67
- gpr_log(GPR_INFO, "[xds_resolver %p] shutting down", this);
68
- }
69
- xds_client_.reset();
70
- }
71
+ void ShutdownLocked() override;
71
72
 
72
73
  private:
74
+ class Notifier {
75
+ public:
76
+ Notifier(RefCountedPtr<XdsResolver> resolver, XdsApi::LdsUpdate update);
77
+ Notifier(RefCountedPtr<XdsResolver> resolver, XdsApi::RdsUpdate update);
78
+ Notifier(RefCountedPtr<XdsResolver> resolver, grpc_error* error);
79
+ explicit Notifier(RefCountedPtr<XdsResolver> resolver);
80
+
81
+ private:
82
+ enum Type { kLdsUpdate, kRdsUpdate, kError, kDoesNotExist };
83
+
84
+ static void RunInExecCtx(void* arg, grpc_error* error);
85
+ void RunInWorkSerializer(grpc_error* error);
86
+
87
+ RefCountedPtr<XdsResolver> resolver_;
88
+ grpc_closure closure_;
89
+ XdsApi::LdsUpdate update_;
90
+ Type type_;
91
+ };
92
+
73
93
  class ListenerWatcher : public XdsClient::ListenerWatcherInterface {
74
94
  public:
75
95
  explicit ListenerWatcher(RefCountedPtr<XdsResolver> resolver)
76
96
  : resolver_(std::move(resolver)) {}
77
- void OnListenerChanged(std::vector<XdsApi::Route> routes) override;
78
- void OnError(grpc_error* error) override;
79
- void OnResourceDoesNotExist() override;
97
+ void OnListenerChanged(XdsApi::LdsUpdate listener) override {
98
+ new Notifier(resolver_, std::move(listener));
99
+ }
100
+ void OnError(grpc_error* error) override { new Notifier(resolver_, error); }
101
+ void OnResourceDoesNotExist() override { new Notifier(resolver_); }
80
102
 
81
103
  private:
82
104
  RefCountedPtr<XdsResolver> resolver_;
83
105
  };
84
106
 
85
- class XdsConfigSelector : public ConfigSelector {
107
+ class RouteConfigWatcher : public XdsClient::RouteConfigWatcherInterface {
86
108
  public:
87
- CallConfig GetCallConfig(GetCallConfigArgs args) override {
88
- return CallConfig();
109
+ explicit RouteConfigWatcher(RefCountedPtr<XdsResolver> resolver)
110
+ : resolver_(std::move(resolver)) {}
111
+ void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) override {
112
+ new Notifier(resolver_, std::move(route_config));
89
113
  }
114
+ void OnError(grpc_error* error) override { new Notifier(resolver_, error); }
115
+ void OnResourceDoesNotExist() override { new Notifier(resolver_); }
116
+
117
+ private:
118
+ RefCountedPtr<XdsResolver> resolver_;
119
+ };
120
+
121
+ class ClusterState
122
+ : public RefCounted<ClusterState, PolymorphicRefCount, false> {
123
+ public:
124
+ using ClusterStateMap =
125
+ std::map<std::string, std::unique_ptr<ClusterState>>;
126
+
127
+ ClusterState(const std::string& cluster_name,
128
+ ClusterStateMap* cluster_state_map)
129
+ : it_(cluster_state_map
130
+ ->emplace(cluster_name, std::unique_ptr<ClusterState>(this))
131
+ .first) {}
132
+ const std::string& cluster() const { return it_->first; }
133
+
134
+ private:
135
+ ClusterStateMap::iterator it_;
90
136
  };
91
137
 
92
- // Returns the weighted_clusters action name to use from
93
- // weighted_cluster_index_map_ for a WeightedClusters route action.
94
- std::string WeightedClustersActionName(
95
- const std::vector<XdsApi::Route::ClusterWeight>& weighted_clusters);
138
+ class XdsConfigSelector : public ConfigSelector {
139
+ public:
140
+ XdsConfigSelector(RefCountedPtr<XdsResolver> resolver,
141
+ const std::vector<XdsApi::Route>& routes);
142
+ ~XdsConfigSelector();
143
+
144
+ const char* name() const override { return "XdsConfigSelector"; }
145
+
146
+ bool Equals(const ConfigSelector* other) const override {
147
+ const auto* other_xds = static_cast<const XdsConfigSelector*>(other);
148
+ // Don't need to compare resolver_, since that will always be the same.
149
+ return route_table_ == other_xds->route_table_ &&
150
+ clusters_ == other_xds->clusters_;
151
+ }
152
+
153
+ CallConfig GetCallConfig(GetCallConfigArgs args) override;
154
+
155
+ private:
156
+ struct Route {
157
+ XdsApi::Route route;
158
+ absl::InlinedVector<std::pair<uint32_t, absl::string_view>, 2>
159
+ weighted_cluster_state;
160
+ bool operator==(const Route& other) const {
161
+ return route == other.route &&
162
+ weighted_cluster_state == other.weighted_cluster_state;
163
+ }
164
+ };
165
+ using RouteTable = std::vector<Route>;
166
+
167
+ void MaybeAddCluster(const std::string& name);
168
+
169
+ RefCountedPtr<XdsResolver> resolver_;
170
+ RouteTable route_table_;
171
+ std::map<absl::string_view, RefCountedPtr<ClusterState>> clusters_;
172
+ };
96
173
 
97
- // Updates weighted_cluster_index_map_ that will
98
- // determine the names of the WeightedCluster actions for the current update.
99
- void UpdateWeightedClusterIndexMap(const std::vector<XdsApi::Route>& routes);
174
+ void OnListenerUpdate(XdsApi::LdsUpdate listener);
175
+ void OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update);
176
+ void OnError(grpc_error* error);
177
+ void OnResourceDoesNotExist();
100
178
 
101
- // Create the service config generated by the list of routes.
102
- grpc_error* CreateServiceConfig(const std::vector<XdsApi::Route>& routes,
103
- RefCountedPtr<ServiceConfig>* service_config);
179
+ grpc_error* CreateServiceConfig(RefCountedPtr<ServiceConfig>* service_config);
180
+ void GenerateResult();
181
+ void MaybeRemoveUnusedClusters();
104
182
 
105
183
  std::string server_name_;
106
184
  const grpc_channel_args* args_;
107
185
  grpc_pollset_set* interested_parties_;
108
- OrphanablePtr<XdsClient> xds_client_;
109
- RefCountedPtr<XdsConfigSelector> config_selector_;
110
-
111
- // 2-level map to store WeightedCluster action names.
112
- // Top level map is keyed by cluster names without weight like a_b_c; bottom
113
- // level map is keyed by cluster names + weights like a10_b50_c40.
114
- struct ClusterNamesInfo {
115
- uint64_t next_index = 0;
116
- std::map<std::string /*cluster names + weights*/,
117
- uint64_t /*policy index number*/>
118
- cluster_weights_map;
119
- };
120
- using WeightedClusterIndexMap =
121
- std::map<std::string /*cluster names*/, ClusterNamesInfo>;
122
-
123
- // Cache of action names for WeightedCluster targets in the current
124
- // service config.
125
- WeightedClusterIndexMap weighted_cluster_index_map_;
186
+ RefCountedPtr<XdsClient> xds_client_;
187
+ XdsClient::ListenerWatcherInterface* listener_watcher_ = nullptr;
188
+ std::string route_config_name_;
189
+ XdsClient::RouteConfigWatcherInterface* route_config_watcher_ = nullptr;
190
+ ClusterState::ClusterStateMap cluster_state_map_;
191
+ std::vector<XdsApi::Route> current_update_;
126
192
  };
127
193
 
128
194
  //
129
- // XdsResolver::ListenerWatcher
195
+ // XdsResolver::Notifier
130
196
  //
131
197
 
132
- void XdsResolver::ListenerWatcher::OnListenerChanged(
133
- std::vector<XdsApi::Route> routes) {
134
- if (resolver_->xds_client_ == nullptr) return;
198
+ XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver,
199
+ XdsApi::LdsUpdate update)
200
+ : resolver_(std::move(resolver)),
201
+ update_(std::move(update)),
202
+ type_(kLdsUpdate) {
203
+ GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
204
+ ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
205
+ }
206
+
207
+ XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver,
208
+ XdsApi::RdsUpdate update)
209
+ : resolver_(std::move(resolver)), type_(kRdsUpdate) {
210
+ update_.rds_update = std::move(update);
211
+ GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
212
+ ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
213
+ }
214
+
215
+ XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver,
216
+ grpc_error* error)
217
+ : resolver_(std::move(resolver)), type_(kError) {
218
+ GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
219
+ ExecCtx::Run(DEBUG_LOCATION, &closure_, error);
220
+ }
221
+
222
+ XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver)
223
+ : resolver_(std::move(resolver)), type_(kDoesNotExist) {
224
+ GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
225
+ ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
226
+ }
227
+
228
+ void XdsResolver::Notifier::RunInExecCtx(void* arg, grpc_error* error) {
229
+ Notifier* self = static_cast<Notifier*>(arg);
230
+ GRPC_ERROR_REF(error);
231
+ self->resolver_->work_serializer()->Run(
232
+ [self, error]() { self->RunInWorkSerializer(error); }, DEBUG_LOCATION);
233
+ }
234
+
235
+ void XdsResolver::Notifier::RunInWorkSerializer(grpc_error* error) {
236
+ if (resolver_->xds_client_ == nullptr) {
237
+ GRPC_ERROR_UNREF(error);
238
+ delete this;
239
+ return;
240
+ }
241
+ switch (type_) {
242
+ case kLdsUpdate:
243
+ resolver_->OnListenerUpdate(std::move(update_));
244
+ break;
245
+ case kRdsUpdate:
246
+ resolver_->OnRouteConfigUpdate(std::move(*update_.rds_update));
247
+ break;
248
+ case kError:
249
+ resolver_->OnError(error);
250
+ break;
251
+ case kDoesNotExist:
252
+ resolver_->OnResourceDoesNotExist();
253
+ break;
254
+ };
255
+ delete this;
256
+ }
257
+
258
+ //
259
+ // XdsResolver::XdsConfigSelector
260
+ //
261
+
262
+ XdsResolver::XdsConfigSelector::XdsConfigSelector(
263
+ RefCountedPtr<XdsResolver> resolver,
264
+ const std::vector<XdsApi::Route>& routes)
265
+ : resolver_(std::move(resolver)) {
135
266
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
136
- gpr_log(GPR_INFO, "[xds_resolver %p] received updated listener data",
137
- resolver_.get());
267
+ gpr_log(GPR_INFO, "[xds_resolver %p] creating XdsConfigSelector %p",
268
+ resolver_.get(), this);
138
269
  }
139
- Result result;
140
- grpc_error* error =
141
- resolver_->CreateServiceConfig(routes, &result.service_config);
142
- if (error != GRPC_ERROR_NONE) {
143
- OnError(error);
144
- return;
270
+ // 1. Construct the route table
271
+ // 2 Update resolver's cluster state map
272
+ // 3. Construct cluster list to hold on to entries in the cluster state
273
+ // map.
274
+ // Reserve the necessary entries up-front to avoid reallocation as we add
275
+ // elements. This is necessary because the string_view in the entry's
276
+ // weighted_cluster_state field points to the memory in the route field, so
277
+ // moving the entry in a reallocation will cause the string_view to point to
278
+ // invalid data.
279
+ route_table_.reserve(routes.size());
280
+ for (auto& route : routes) {
281
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
282
+ gpr_log(GPR_INFO, "[xds_resolver %p] XdsConfigSelector %p: route: %s",
283
+ resolver_.get(), this, route.ToString().c_str());
284
+ }
285
+ route_table_.emplace_back();
286
+ auto& route_entry = route_table_.back();
287
+ route_entry.route = route;
288
+ if (route.weighted_clusters.empty()) {
289
+ MaybeAddCluster(route.cluster_name);
290
+ } else {
291
+ uint32_t end = 0;
292
+ for (const auto& weighted_cluster : route_entry.route.weighted_clusters) {
293
+ MaybeAddCluster(weighted_cluster.name);
294
+ end += weighted_cluster.weight;
295
+ route_entry.weighted_cluster_state.emplace_back(end,
296
+ weighted_cluster.name);
297
+ }
298
+ }
145
299
  }
300
+ }
301
+
302
+ XdsResolver::XdsConfigSelector::~XdsConfigSelector() {
146
303
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
147
- gpr_log(GPR_INFO, "[xds_resolver %p] generated service config: %s",
148
- resolver_.get(), result.service_config->json_string().c_str());
304
+ gpr_log(GPR_INFO, "[xds_resolver %p] destroying XdsConfigSelector %p",
305
+ resolver_.get(), this);
149
306
  }
150
- grpc_arg new_args[] = {
151
- resolver_->xds_client_->MakeChannelArg(),
152
- resolver_->config_selector_->MakeChannelArg(),
153
- };
154
- result.args = grpc_channel_args_copy_and_add(resolver_->args_, new_args,
155
- GPR_ARRAY_SIZE(new_args));
156
- resolver_->result_handler()->ReturnResult(std::move(result));
307
+ clusters_.clear();
308
+ resolver_->MaybeRemoveUnusedClusters();
157
309
  }
158
310
 
159
- void XdsResolver::ListenerWatcher::OnError(grpc_error* error) {
160
- if (resolver_->xds_client_ == nullptr) return;
161
- gpr_log(GPR_ERROR, "[xds_resolver %p] received error: %s", resolver_.get(),
162
- grpc_error_string(error));
163
- grpc_arg xds_client_arg = resolver_->xds_client_->MakeChannelArg();
164
- Result result;
165
- result.args =
166
- grpc_channel_args_copy_and_add(resolver_->args_, &xds_client_arg, 1);
167
- result.service_config_error = error;
168
- resolver_->result_handler()->ReturnResult(std::move(result));
311
+ void XdsResolver::XdsConfigSelector::MaybeAddCluster(const std::string& name) {
312
+ if (clusters_.find(name) == clusters_.end()) {
313
+ auto it = resolver_->cluster_state_map_.find(name);
314
+ if (it == resolver_->cluster_state_map_.end()) {
315
+ auto new_cluster_state =
316
+ MakeRefCounted<ClusterState>(name, &resolver_->cluster_state_map_);
317
+ clusters_[new_cluster_state->cluster()] = std::move(new_cluster_state);
318
+ } else {
319
+ clusters_[it->second->cluster()] = it->second->Ref();
320
+ }
321
+ }
169
322
  }
170
323
 
171
- void XdsResolver::ListenerWatcher::OnResourceDoesNotExist() {
172
- if (resolver_->xds_client_ == nullptr) return;
173
- gpr_log(GPR_ERROR,
174
- "[xds_resolver %p] LDS/RDS resource does not exist -- returning "
175
- "empty service config",
176
- resolver_.get());
177
- Result result;
178
- result.service_config =
179
- ServiceConfig::Create("{}", &result.service_config_error);
180
- GPR_ASSERT(result.service_config != nullptr);
181
- result.args = grpc_channel_args_copy(resolver_->args_);
182
- resolver_->result_handler()->ReturnResult(std::move(result));
324
+ bool PathMatch(const absl::string_view& path,
325
+ const XdsApi::Route::Matchers::PathMatcher& path_matcher) {
326
+ switch (path_matcher.type) {
327
+ case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PREFIX:
328
+ return absl::StartsWith(path, path_matcher.string_matcher);
329
+ case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PATH:
330
+ return path == path_matcher.string_matcher;
331
+ case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::REGEX:
332
+ return RE2::FullMatch(path.data(), *path_matcher.regex_matcher);
333
+ default:
334
+ return false;
335
+ }
336
+ }
337
+
338
+ absl::optional<absl::string_view> GetMetadataValue(
339
+ const std::string& target_key, grpc_metadata_batch* initial_metadata,
340
+ std::string* concatenated_value) {
341
+ // Find all values for the specified key.
342
+ GPR_DEBUG_ASSERT(initial_metadata != nullptr);
343
+ absl::InlinedVector<absl::string_view, 1> values;
344
+ for (grpc_linked_mdelem* md = initial_metadata->list.head; md != nullptr;
345
+ md = md->next) {
346
+ absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md));
347
+ absl::string_view value = StringViewFromSlice(GRPC_MDVALUE(md->md));
348
+ if (target_key == key) values.push_back(value);
349
+ }
350
+ // If none found, no match.
351
+ if (values.empty()) return absl::nullopt;
352
+ // If exactly one found, return it as-is.
353
+ if (values.size() == 1) return values.front();
354
+ // If more than one found, concatenate the values, using
355
+ // *concatenated_values as a temporary holding place for the
356
+ // concatenated string.
357
+ *concatenated_value = absl::StrJoin(values, ",");
358
+ return *concatenated_value;
359
+ }
360
+
361
+ bool HeaderMatchHelper(
362
+ const XdsApi::Route::Matchers::HeaderMatcher& header_matcher,
363
+ grpc_metadata_batch* initial_metadata) {
364
+ std::string concatenated_value;
365
+ absl::optional<absl::string_view> value;
366
+ // Note: If we ever allow binary headers here, we still need to
367
+ // special-case ignore "grpc-tags-bin" and "grpc-trace-bin", since
368
+ // they are not visible to the LB policy in grpc-go.
369
+ if (absl::EndsWith(header_matcher.name, "-bin") ||
370
+ header_matcher.name == "grpc-previous-rpc-attempts") {
371
+ value = absl::nullopt;
372
+ } else if (header_matcher.name == "content-type") {
373
+ value = "application/grpc";
374
+ } else {
375
+ value = GetMetadataValue(header_matcher.name, initial_metadata,
376
+ &concatenated_value);
377
+ }
378
+ if (!value.has_value()) {
379
+ if (header_matcher.type ==
380
+ XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PRESENT) {
381
+ return !header_matcher.present_match;
382
+ } else {
383
+ // For all other header matcher types, we need the header value to
384
+ // exist to consider matches.
385
+ return false;
386
+ }
387
+ }
388
+ switch (header_matcher.type) {
389
+ case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::EXACT:
390
+ return value.value() == header_matcher.string_matcher;
391
+ case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::REGEX:
392
+ return RE2::FullMatch(value.value().data(), *header_matcher.regex_match);
393
+ case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::RANGE:
394
+ int64_t int_value;
395
+ if (!absl::SimpleAtoi(value.value(), &int_value)) {
396
+ return false;
397
+ }
398
+ return int_value >= header_matcher.range_start &&
399
+ int_value < header_matcher.range_end;
400
+ case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PREFIX:
401
+ return absl::StartsWith(value.value(), header_matcher.string_matcher);
402
+ case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::SUFFIX:
403
+ return absl::EndsWith(value.value(), header_matcher.string_matcher);
404
+ default:
405
+ return false;
406
+ }
407
+ }
408
+
409
+ bool HeadersMatch(
410
+ const std::vector<XdsApi::Route::Matchers::HeaderMatcher>& header_matchers,
411
+ grpc_metadata_batch* initial_metadata) {
412
+ for (const auto& header_matcher : header_matchers) {
413
+ bool match = HeaderMatchHelper(header_matcher, initial_metadata);
414
+ if (header_matcher.invert_match) match = !match;
415
+ if (!match) return false;
416
+ }
417
+ return true;
418
+ }
419
+
420
+ bool UnderFraction(const uint32_t fraction_per_million) {
421
+ // Generate a random number in [0, 1000000).
422
+ const uint32_t random_number = rand() % 1000000;
423
+ return random_number < fraction_per_million;
424
+ }
425
+
426
+ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
427
+ GetCallConfigArgs args) {
428
+ for (const auto& entry : route_table_) {
429
+ // Path matching.
430
+ if (!PathMatch(StringViewFromSlice(*args.path),
431
+ entry.route.matchers.path_matcher)) {
432
+ continue;
433
+ }
434
+ // Header Matching.
435
+ if (!HeadersMatch(entry.route.matchers.header_matchers,
436
+ args.initial_metadata)) {
437
+ continue;
438
+ }
439
+ // Match fraction check
440
+ if (entry.route.matchers.fraction_per_million.has_value() &&
441
+ !UnderFraction(entry.route.matchers.fraction_per_million.value())) {
442
+ continue;
443
+ }
444
+ // Found a route match
445
+ absl::string_view cluster_name;
446
+ if (entry.route.weighted_clusters.empty()) {
447
+ cluster_name = entry.route.cluster_name;
448
+ } else {
449
+ const uint32_t key =
450
+ rand() %
451
+ entry.weighted_cluster_state[entry.weighted_cluster_state.size() - 1]
452
+ .first;
453
+ // Find the index in weighted clusters corresponding to key.
454
+ size_t mid = 0;
455
+ size_t start_index = 0;
456
+ size_t end_index = entry.weighted_cluster_state.size() - 1;
457
+ size_t index = 0;
458
+ while (end_index > start_index) {
459
+ mid = (start_index + end_index) / 2;
460
+ if (entry.weighted_cluster_state[mid].first > key) {
461
+ end_index = mid;
462
+ } else if (entry.weighted_cluster_state[mid].first < key) {
463
+ start_index = mid + 1;
464
+ } else {
465
+ index = mid + 1;
466
+ break;
467
+ }
468
+ }
469
+ if (index == 0) index = start_index;
470
+ GPR_ASSERT(entry.weighted_cluster_state[index].first > key);
471
+ cluster_name = entry.weighted_cluster_state[index].second;
472
+ }
473
+ auto it = clusters_.find(cluster_name);
474
+ GPR_ASSERT(it != clusters_.end());
475
+ XdsResolver* resolver =
476
+ static_cast<XdsResolver*>(resolver_->Ref().release());
477
+ ClusterState* cluster_state = it->second->Ref().release();
478
+ CallConfig call_config;
479
+ call_config.call_attributes[kXdsClusterAttribute] = it->first;
480
+ call_config.on_call_committed = [resolver, cluster_state]() {
481
+ cluster_state->Unref();
482
+ ExecCtx::Run(
483
+ // TODO(roth): This hop into the ExecCtx is being done to avoid
484
+ // entering the WorkSerializer while holding the client channel data
485
+ // plane mutex, since that can lead to deadlocks. However, we should
486
+ // not have to solve this problem in each individual ConfigSelector
487
+ // implementation. When we have time, we should fix the client channel
488
+ // code to avoid this by not invoking the
489
+ // CallConfig::on_call_committed callback until after it has released
490
+ // the data plane mutex.
491
+ DEBUG_LOCATION,
492
+ GRPC_CLOSURE_CREATE(
493
+ [](void* arg, grpc_error* /*error*/) {
494
+ auto* resolver = static_cast<XdsResolver*>(arg);
495
+ resolver->work_serializer()->Run(
496
+ [resolver]() {
497
+ resolver->MaybeRemoveUnusedClusters();
498
+ resolver->Unref();
499
+ },
500
+ DEBUG_LOCATION);
501
+ },
502
+ resolver, nullptr),
503
+ GRPC_ERROR_NONE);
504
+ };
505
+ return call_config;
506
+ }
507
+ return CallConfig();
183
508
  }
184
509
 
185
510
  //
@@ -188,320 +513,190 @@ void XdsResolver::ListenerWatcher::OnResourceDoesNotExist() {
188
513
 
189
514
  void XdsResolver::StartLocked() {
190
515
  grpc_error* error = GRPC_ERROR_NONE;
191
- xds_client_ = MakeOrphanable<XdsClient>(
192
- work_serializer(), interested_parties_, server_name_,
193
- absl::make_unique<ListenerWatcher>(Ref()), *args_, &error);
516
+ xds_client_ = XdsClient::GetOrCreate(&error);
194
517
  if (error != GRPC_ERROR_NONE) {
195
518
  gpr_log(GPR_ERROR,
196
519
  "Failed to create xds client -- channel will remain in "
197
520
  "TRANSIENT_FAILURE: %s",
198
521
  grpc_error_string(error));
199
522
  result_handler()->ReturnError(error);
523
+ return;
524
+ }
525
+ grpc_pollset_set_add_pollset_set(xds_client_->interested_parties(),
526
+ interested_parties_);
527
+ channelz::ChannelNode* parent_channelz_node =
528
+ grpc_channel_args_find_pointer<channelz::ChannelNode>(
529
+ args_, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
530
+ if (parent_channelz_node != nullptr) {
531
+ xds_client_->AddChannelzLinkage(parent_channelz_node);
200
532
  }
533
+ auto watcher = absl::make_unique<ListenerWatcher>(Ref());
534
+ listener_watcher_ = watcher.get();
535
+ xds_client_->WatchListenerData(server_name_, std::move(watcher));
201
536
  }
202
537
 
203
- std::string CreateServiceConfigActionCluster(const std::string& cluster_name) {
204
- return absl::StrFormat(
205
- " \"cds:%s\":{\n"
206
- " \"childPolicy\":[ {\n"
207
- " \"cds_experimental\":{\n"
208
- " \"cluster\": \"%s\"\n"
209
- " }\n"
210
- " } ]\n"
211
- " }",
212
- cluster_name, cluster_name);
538
+ void XdsResolver::ShutdownLocked() {
539
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
540
+ gpr_log(GPR_INFO, "[xds_resolver %p] shutting down", this);
541
+ }
542
+ if (xds_client_ != nullptr) {
543
+ if (listener_watcher_ != nullptr) {
544
+ xds_client_->CancelListenerDataWatch(server_name_, listener_watcher_,
545
+ /*delay_unsubscription=*/false);
546
+ }
547
+ if (route_config_watcher_ != nullptr) {
548
+ xds_client_->CancelRouteConfigDataWatch(
549
+ server_name_, route_config_watcher_, /*delay_unsubscription=*/false);
550
+ }
551
+ channelz::ChannelNode* parent_channelz_node =
552
+ grpc_channel_args_find_pointer<channelz::ChannelNode>(
553
+ args_, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
554
+ if (parent_channelz_node != nullptr) {
555
+ xds_client_->RemoveChannelzLinkage(parent_channelz_node);
556
+ }
557
+ grpc_pollset_set_del_pollset_set(xds_client_->interested_parties(),
558
+ interested_parties_);
559
+ xds_client_.reset();
560
+ }
213
561
  }
214
562
 
215
- std::string CreateServiceConfigRoute(const std::string& action_name,
216
- const XdsApi::Route& route) {
217
- std::vector<std::string> headers;
218
- for (const auto& header : route.matchers.header_matchers) {
219
- std::string header_matcher;
220
- switch (header.type) {
221
- case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::EXACT:
222
- header_matcher = absl::StrFormat(" \"exact_match\": \"%s\"",
223
- header.string_matcher);
224
- break;
225
- case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::REGEX:
226
- header_matcher = absl::StrFormat(" \"regex_match\": \"%s\"",
227
- header.regex_match->pattern());
228
- break;
229
- case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::RANGE:
230
- header_matcher = absl::StrFormat(
231
- " \"range_match\":{\n"
232
- " \"start\":%d,\n"
233
- " \"end\":%d\n"
234
- " }",
235
- header.range_start, header.range_end);
236
- break;
237
- case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PRESENT:
238
- header_matcher =
239
- absl::StrFormat(" \"present_match\": %s",
240
- header.present_match ? "true" : "false");
241
- break;
242
- case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::PREFIX:
243
- header_matcher = absl::StrFormat(
244
- " \"prefix_match\": \"%s\"", header.string_matcher);
245
- break;
246
- case XdsApi::Route::Matchers::HeaderMatcher::HeaderMatcherType::SUFFIX:
247
- header_matcher = absl::StrFormat(
248
- " \"suffix_match\": \"%s\"", header.string_matcher);
249
- break;
250
- default:
251
- break;
563
+ void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) {
564
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
565
+ gpr_log(GPR_INFO, "[xds_resolver %p] received updated listener data", this);
566
+ }
567
+ if (listener.route_config_name != route_config_name_) {
568
+ if (route_config_watcher_ != nullptr) {
569
+ xds_client_->CancelRouteConfigDataWatch(
570
+ route_config_name_, route_config_watcher_,
571
+ /*delay_unsubscription=*/!listener.route_config_name.empty());
572
+ route_config_watcher_ = nullptr;
252
573
  }
253
- std::vector<std::string> header_parts;
254
- header_parts.push_back(
255
- absl::StrFormat(" { \n"
256
- " \"name\": \"%s\",\n",
257
- header.name));
258
- header_parts.push_back(header_matcher);
259
- if (header.invert_match) {
260
- header_parts.push_back(
261
- absl::StrFormat(",\n"
262
- " \"invert_match\": true"));
574
+ route_config_name_ = std::move(listener.route_config_name);
575
+ if (!route_config_name_.empty()) {
576
+ auto watcher = absl::make_unique<RouteConfigWatcher>(Ref());
577
+ route_config_watcher_ = watcher.get();
578
+ xds_client_->WatchRouteConfigData(route_config_name_, std::move(watcher));
263
579
  }
264
- header_parts.push_back(
265
- absl::StrFormat("\n"
266
- " }"));
267
- headers.push_back(absl::StrJoin(header_parts, ""));
268
580
  }
269
- std::vector<std::string> headers_service_config;
270
- if (!headers.empty()) {
271
- headers_service_config.push_back("\"headers\":[\n");
272
- headers_service_config.push_back(absl::StrJoin(headers, ","));
273
- headers_service_config.push_back(" ],\n");
581
+ if (route_config_name_.empty()) {
582
+ GPR_ASSERT(listener.rds_update.has_value());
583
+ OnRouteConfigUpdate(std::move(*listener.rds_update));
274
584
  }
275
- std::string path_match_str;
276
- switch (route.matchers.path_matcher.type) {
277
- case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PREFIX:
278
- path_match_str = absl::StrFormat(
279
- "\"prefix\": \"%s\",\n", route.matchers.path_matcher.string_matcher);
280
- break;
281
- case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::PATH:
282
- path_match_str = absl::StrFormat(
283
- "\"path\": \"%s\",\n", route.matchers.path_matcher.string_matcher);
284
- break;
285
- case XdsApi::Route::Matchers::PathMatcher::PathMatcherType::REGEX:
286
- path_match_str =
287
- absl::StrFormat("\"regex\": \"%s\",\n",
288
- route.matchers.path_matcher.regex_matcher->pattern());
289
- break;
290
- }
291
- return absl::StrFormat(
292
- " { \n"
293
- " %s"
294
- " %s"
295
- " %s"
296
- " \"action\": \"%s\"\n"
297
- " }",
298
- path_match_str, absl::StrJoin(headers_service_config, ""),
299
- route.matchers.fraction_per_million.has_value()
300
- ? absl::StrFormat("\"match_fraction\":%d,\n",
301
- route.matchers.fraction_per_million.value())
302
- : "",
303
- action_name);
304
585
  }
305
586
 
306
- // Create the service config for one weighted cluster.
307
- std::string CreateServiceConfigActionWeightedCluster(
308
- const std::string& name,
309
- const std::vector<XdsApi::Route::ClusterWeight>& clusters) {
310
- std::vector<std::string> config_parts;
311
- config_parts.push_back(
312
- absl::StrFormat(" \"weighted:%s\":{\n"
313
- " \"childPolicy\":[ {\n"
314
- " \"weighted_target_experimental\":{\n"
315
- " \"targets\":{\n",
316
- name));
317
- std::vector<std::string> weighted_targets;
318
- weighted_targets.reserve(clusters.size());
319
- for (const auto& cluster_weight : clusters) {
320
- weighted_targets.push_back(absl::StrFormat(
321
- " \"%s\":{\n"
322
- " \"weight\":%d,\n"
323
- " \"childPolicy\":[ {\n"
324
- " \"cds_experimental\":{\n"
325
- " \"cluster\": \"%s\"\n"
326
- " }\n"
327
- " } ]\n"
328
- " }",
329
- cluster_weight.name, cluster_weight.weight, cluster_weight.name));
587
+ void XdsResolver::OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update) {
588
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
589
+ gpr_log(GPR_INFO, "[xds_resolver %p] received updated route config", this);
330
590
  }
331
- config_parts.push_back(absl::StrJoin(weighted_targets, ",\n"));
332
- config_parts.push_back(
333
- " }\n"
334
- " }\n"
335
- " } ]\n"
336
- " }");
337
- return absl::StrJoin(config_parts, "");
338
- }
339
-
340
- struct WeightedClustersKeys {
341
- std::string cluster_names_key;
342
- std::string cluster_weights_key;
343
- };
344
-
345
- // Returns the cluster names and weights key or the cluster names only key.
346
- WeightedClustersKeys GetWeightedClustersKey(
347
- const std::vector<XdsApi::Route::ClusterWeight>& weighted_clusters) {
348
- std::set<std::string> cluster_names;
349
- std::set<std::string> cluster_weights;
350
- for (const auto& cluster_weight : weighted_clusters) {
351
- cluster_names.emplace(absl::StrFormat("%s", cluster_weight.name));
352
- cluster_weights.emplace(
353
- absl::StrFormat("%s_%d", cluster_weight.name, cluster_weight.weight));
591
+ // Find the relevant VirtualHost from the RouteConfiguration.
592
+ XdsApi::RdsUpdate::VirtualHost* vhost =
593
+ rds_update.FindVirtualHostForDomain(server_name_);
594
+ if (vhost == nullptr) {
595
+ OnError(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
596
+ absl::StrCat("could not find VirtualHost for ", server_name_,
597
+ " in RouteConfiguration")
598
+ .c_str()));
599
+ return;
354
600
  }
355
- return {absl::StrJoin(cluster_names, "_"),
356
- absl::StrJoin(cluster_weights, "_")};
601
+ // Save the list of routes in the resolver.
602
+ current_update_ = std::move(vhost->routes);
603
+ // Send a new result to the channel.
604
+ GenerateResult();
357
605
  }
358
606
 
359
- std::string XdsResolver::WeightedClustersActionName(
360
- const std::vector<XdsApi::Route::ClusterWeight>& weighted_clusters) {
361
- WeightedClustersKeys keys = GetWeightedClustersKey(weighted_clusters);
362
- auto cluster_names_map_it =
363
- weighted_cluster_index_map_.find(keys.cluster_names_key);
364
- GPR_ASSERT(cluster_names_map_it != weighted_cluster_index_map_.end());
365
- const auto& cluster_weights_map =
366
- cluster_names_map_it->second.cluster_weights_map;
367
- auto cluster_weights_map_it =
368
- cluster_weights_map.find(keys.cluster_weights_key);
369
- GPR_ASSERT(cluster_weights_map_it != cluster_weights_map.end());
370
- return absl::StrFormat("%s_%d", keys.cluster_names_key,
371
- cluster_weights_map_it->second);
607
+ void XdsResolver::OnError(grpc_error* error) {
608
+ gpr_log(GPR_ERROR, "[xds_resolver %p] received error from XdsClient: %s",
609
+ this, grpc_error_string(error));
610
+ Result result;
611
+ result.args = grpc_channel_args_copy(args_);
612
+ result.service_config_error = error;
613
+ result_handler()->ReturnResult(std::move(result));
372
614
  }
373
615
 
374
- void XdsResolver::UpdateWeightedClusterIndexMap(
375
- const std::vector<XdsApi::Route>& routes) {
376
- // Construct a list of unique WeightedCluster
377
- // actions which we need to process: to find action names
378
- std::map<std::string /* cluster_weights_key */,
379
- std::string /* cluster_names_key */>
380
- actions_to_process;
381
- for (const auto& route : routes) {
382
- if (!route.weighted_clusters.empty()) {
383
- WeightedClustersKeys keys =
384
- GetWeightedClustersKey(route.weighted_clusters);
385
- auto action_it = actions_to_process.find(keys.cluster_weights_key);
386
- if (action_it == actions_to_process.end()) {
387
- actions_to_process[std::move(keys.cluster_weights_key)] =
388
- std::move(keys.cluster_names_key);
389
- }
390
- }
391
- }
392
- // First pass of all unique WeightedCluster actions: if the exact same
393
- // weighted target policy (same clusters and weights) appears in the old map,
394
- // then that old action name is taken again and should be moved to the new
395
- // map; any other action names from the old set of actions are candidates for
396
- // reuse.
397
- XdsResolver::WeightedClusterIndexMap new_weighted_cluster_index_map;
398
- for (auto action_it = actions_to_process.begin();
399
- action_it != actions_to_process.end();) {
400
- const std::string& cluster_names_key = action_it->second;
401
- const std::string& cluster_weights_key = action_it->first;
402
- auto old_cluster_names_map_it =
403
- weighted_cluster_index_map_.find(cluster_names_key);
404
- if (old_cluster_names_map_it != weighted_cluster_index_map_.end()) {
405
- // Add cluster_names_key to the new map and copy next_index.
406
- auto& new_cluster_names_info =
407
- new_weighted_cluster_index_map[cluster_names_key];
408
- new_cluster_names_info.next_index =
409
- old_cluster_names_map_it->second.next_index;
410
- // Lookup cluster_weights_key in old map.
411
- auto& old_cluster_weights_map =
412
- old_cluster_names_map_it->second.cluster_weights_map;
413
- auto old_cluster_weights_map_it =
414
- old_cluster_weights_map.find(cluster_weights_key);
415
- if (old_cluster_weights_map_it != old_cluster_weights_map.end()) {
416
- // same policy found, move from old map to new map.
417
- new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
418
- old_cluster_weights_map_it->second;
419
- old_cluster_weights_map.erase(old_cluster_weights_map_it);
420
- // This action has been added to new map, so no need to process it
421
- // again.
422
- action_it = actions_to_process.erase(action_it);
423
- continue;
424
- }
425
- }
426
- ++action_it;
427
- }
428
- // Second pass of all remaining unique WeightedCluster actions: if clusters
429
- // for a new action are the same as an old unused action, reuse the name. If
430
- // clusters differ, use a brand new name.
431
- for (const auto& action : actions_to_process) {
432
- const std::string& cluster_names_key = action.second;
433
- const std::string& cluster_weights_key = action.first;
434
- auto& new_cluster_names_info =
435
- new_weighted_cluster_index_map[cluster_names_key];
436
- auto& old_cluster_weights_map =
437
- weighted_cluster_index_map_[cluster_names_key].cluster_weights_map;
438
- auto old_cluster_weights_it = old_cluster_weights_map.begin();
439
- if (old_cluster_weights_it != old_cluster_weights_map.end()) {
440
- // There is something to reuse: this action uses the same set
441
- // of clusters as a previous action and that action name is not
442
- // already taken.
443
- new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
444
- old_cluster_weights_it->second;
445
- // Remove the name from being able to reuse again.
446
- old_cluster_weights_map.erase(old_cluster_weights_it);
447
- } else {
448
- // There is nothing to reuse, take the next index to use and
449
- // increment.
450
- new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
451
- new_cluster_names_info.next_index++;
452
- }
453
- }
454
- weighted_cluster_index_map_ = std::move(new_weighted_cluster_index_map);
616
+ void XdsResolver::OnResourceDoesNotExist() {
617
+ gpr_log(GPR_ERROR,
618
+ "[xds_resolver %p] LDS/RDS resource does not exist -- clearing "
619
+ "update and returning empty service config",
620
+ this);
621
+ current_update_.clear();
622
+ Result result;
623
+ result.service_config =
624
+ ServiceConfig::Create(args_, "{}", &result.service_config_error);
625
+ GPR_ASSERT(result.service_config != nullptr);
626
+ result.args = grpc_channel_args_copy(args_);
627
+ result_handler()->ReturnResult(std::move(result));
455
628
  }
456
629
 
457
630
  grpc_error* XdsResolver::CreateServiceConfig(
458
- const std::vector<XdsApi::Route>& routes,
459
631
  RefCountedPtr<ServiceConfig>* service_config) {
460
- UpdateWeightedClusterIndexMap(routes);
461
- std::vector<std::string> actions_vector;
462
- std::vector<std::string> route_table;
463
- std::set<std::string> actions_set;
464
- for (const auto& route : routes) {
465
- const std::string action_name =
466
- route.weighted_clusters.empty()
467
- ? route.cluster_name
468
- : WeightedClustersActionName(route.weighted_clusters);
469
- if (actions_set.find(action_name) == actions_set.end()) {
470
- actions_set.emplace(action_name);
471
- actions_vector.push_back(
472
- route.weighted_clusters.empty()
473
- ? CreateServiceConfigActionCluster(action_name)
474
- : CreateServiceConfigActionWeightedCluster(
475
- action_name, route.weighted_clusters));
476
- }
477
- route_table.push_back(CreateServiceConfigRoute(
478
- absl::StrFormat("%s:%s",
479
- route.weighted_clusters.empty() ? "cds" : "weighted",
480
- action_name),
481
- route));
632
+ std::vector<std::string> clusters;
633
+ for (const auto& cluster : cluster_state_map_) {
634
+ clusters.push_back(
635
+ absl::StrFormat(" \"%s\":{\n"
636
+ " \"childPolicy\":[ {\n"
637
+ " \"cds_experimental\":{\n"
638
+ " \"cluster\": \"%s\"\n"
639
+ " }\n"
640
+ " } ]\n"
641
+ " }",
642
+ cluster.first, cluster.first));
482
643
  }
483
644
  std::vector<std::string> config_parts;
484
645
  config_parts.push_back(
485
646
  "{\n"
486
647
  " \"loadBalancingConfig\":[\n"
487
- " { \"xds_routing_experimental\":{\n"
488
- " \"actions\":{\n");
489
- config_parts.push_back(absl::StrJoin(actions_vector, ",\n"));
490
- config_parts.push_back(
491
- " },\n"
492
- " \"routes\":[\n");
493
- config_parts.push_back(absl::StrJoin(route_table, ",\n"));
648
+ " { \"xds_cluster_manager_experimental\":{\n"
649
+ " \"children\":{\n");
650
+ config_parts.push_back(absl::StrJoin(clusters, ",\n"));
494
651
  config_parts.push_back(
495
- " ]\n"
652
+ " }\n"
496
653
  " } }\n"
497
654
  " ]\n"
498
655
  "}");
499
656
  std::string json = absl::StrJoin(config_parts, "");
500
657
  grpc_error* error = GRPC_ERROR_NONE;
501
- *service_config = ServiceConfig::Create(json.c_str(), &error);
658
+ *service_config = ServiceConfig::Create(args_, json.c_str(), &error);
502
659
  return error;
503
660
  }
504
661
 
662
+ void XdsResolver::GenerateResult() {
663
+ if (current_update_.empty()) return;
664
+ // First create XdsConfigSelector, which may add new entries to the cluster
665
+ // state map, and then CreateServiceConfig for LB policies.
666
+ auto config_selector =
667
+ MakeRefCounted<XdsConfigSelector>(Ref(), current_update_);
668
+ Result result;
669
+ grpc_error* error = CreateServiceConfig(&result.service_config);
670
+ if (error != GRPC_ERROR_NONE) {
671
+ OnError(error);
672
+ return;
673
+ }
674
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
675
+ gpr_log(GPR_INFO, "[xds_resolver %p] generated service config: %s", this,
676
+ result.service_config->json_string().c_str());
677
+ }
678
+ grpc_arg new_arg = config_selector->MakeChannelArg();
679
+ result.args = grpc_channel_args_copy_and_add(args_, &new_arg, 1);
680
+ result_handler()->ReturnResult(std::move(result));
681
+ }
682
+
683
+ void XdsResolver::MaybeRemoveUnusedClusters() {
684
+ bool update_needed = false;
685
+ for (auto it = cluster_state_map_.begin(); it != cluster_state_map_.end();) {
686
+ RefCountedPtr<ClusterState> cluster_state = it->second->RefIfNonZero();
687
+ if (cluster_state != nullptr) {
688
+ ++it;
689
+ } else {
690
+ update_needed = true;
691
+ it = cluster_state_map_.erase(it);
692
+ }
693
+ }
694
+ if (update_needed && xds_client_ != nullptr) {
695
+ // Send a new result to the channel.
696
+ GenerateResult();
697
+ }
698
+ }
699
+
505
700
  //
506
701
  // Factory
507
702
  //