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
@@ -17,12 +17,8 @@
17
17
  #include <grpc/support/port_platform.h>
18
18
 
19
19
  #include "src/core/ext/filters/client_channel/config_selector.h"
20
-
21
20
  #include "src/core/lib/channel/channel_args.h"
22
21
 
23
- // Channel arg key for ConfigSelector.
24
- #define GRPC_ARG_CONFIG_SELECTOR "grpc.internal.config_selector"
25
-
26
22
  namespace grpc_core {
27
23
 
28
24
  namespace {
@@ -34,6 +34,9 @@
34
34
  #include "src/core/lib/gprpp/ref_counted_ptr.h"
35
35
  #include "src/core/lib/transport/metadata_batch.h"
36
36
 
37
+ // Channel arg key for ConfigSelector.
38
+ #define GRPC_ARG_CONFIG_SELECTOR "grpc.internal.config_selector"
39
+
37
40
  namespace grpc_core {
38
41
 
39
42
  // Internal API used to allow resolver implementations to override
@@ -52,6 +55,9 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
52
55
  // The per-method parsed configs that will be passed to
53
56
  // ServiceConfigCallData.
54
57
  const ServiceConfigParser::ParsedConfigVector* method_configs = nullptr;
58
+ // A ref to the service config that contains method_configs, held by
59
+ // the call to ensure that method_configs lives long enough.
60
+ RefCountedPtr<ServiceConfig> service_config;
55
61
  // Call attributes that will be accessible to LB policy implementations.
56
62
  std::map<const char*, absl::string_view> call_attributes;
57
63
  // A callback that, if set, will be invoked when the call is
@@ -62,6 +68,19 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
62
68
 
63
69
  virtual ~ConfigSelector() = default;
64
70
 
71
+ virtual const char* name() const = 0;
72
+
73
+ // Will be called only if the two objects have the same name, so
74
+ // subclasses can be free to safely down-cast the argument.
75
+ virtual bool Equals(const ConfigSelector* other) const = 0;
76
+
77
+ static bool Equals(const ConfigSelector* cs1, const ConfigSelector* cs2) {
78
+ if (cs1 == nullptr) return cs2 == nullptr;
79
+ if (cs2 == nullptr) return false;
80
+ if (strcmp(cs1->name(), cs2->name()) != 0) return false;
81
+ return cs1->Equals(cs2);
82
+ }
83
+
65
84
  virtual CallConfig GetCallConfig(GetCallConfigArgs args) = 0;
66
85
 
67
86
  grpc_arg MakeChannelArg() const;
@@ -73,14 +92,24 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
73
92
  class DefaultConfigSelector : public ConfigSelector {
74
93
  public:
75
94
  explicit DefaultConfigSelector(RefCountedPtr<ServiceConfig> service_config)
76
- : service_config_(std::move(service_config)) {}
95
+ : service_config_(std::move(service_config)) {
96
+ // The client channel code ensures that this will never be null.
97
+ // If neither the resolver nor the client application provide a
98
+ // config, a default empty config will be used.
99
+ GPR_DEBUG_ASSERT(service_config_ != nullptr);
100
+ }
101
+
102
+ const char* name() const override { return "default"; }
103
+
104
+ // Only comparing the ConfigSelector itself, not the underlying
105
+ // service config, so we always return true.
106
+ bool Equals(const ConfigSelector* other) const override { return true; }
77
107
 
78
108
  CallConfig GetCallConfig(GetCallConfigArgs args) override {
79
109
  CallConfig call_config;
80
- if (service_config_ != nullptr) {
81
- call_config.method_configs =
82
- service_config_->GetMethodParsedConfigVector(*args.path);
83
- }
110
+ call_config.method_configs =
111
+ service_config_->GetMethodParsedConfigVector(*args.path);
112
+ call_config.service_config = service_config_;
84
113
  return call_config;
85
114
  }
86
115
 
@@ -279,7 +279,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
279
279
 
280
280
  /// Creates a new subchannel with the specified channel args.
281
281
  virtual RefCountedPtr<SubchannelInterface> CreateSubchannel(
282
- const grpc_channel_args& args) = 0;
282
+ ServerAddress address, const grpc_channel_args& args) = 0;
283
283
 
284
284
  /// Sets the connectivity state and returns a new picker to be used
285
285
  /// by the client channel.
@@ -18,64 +18,77 @@
18
18
 
19
19
  #include "src/core/ext/filters/client_channel/lb_policy/address_filtering.h"
20
20
 
21
+ #include "absl/strings/str_cat.h"
22
+ #include "absl/strings/str_join.h"
23
+
21
24
  #include "src/core/lib/channel/channel_args.h"
22
25
 
23
26
  #define GRPC_ARG_HIERARCHICAL_PATH "grpc.internal.address.hierarchical_path"
24
27
 
25
28
  namespace grpc_core {
26
29
 
30
+ const char* kHierarchicalPathAttributeKey = "hierarchical_path";
31
+
27
32
  namespace {
28
33
 
29
- void* HierarchicalPathCopy(void* p) {
30
- std::vector<std::string>* path = static_cast<std::vector<std::string>*>(p);
31
- return static_cast<void*>(new std::vector<std::string>(*path));
32
- }
34
+ class HierarchicalPathAttribute : public ServerAddress::AttributeInterface {
35
+ public:
36
+ explicit HierarchicalPathAttribute(std::vector<std::string> path)
37
+ : path_(std::move(path)) {}
33
38
 
34
- void HierarchicalPathDestroy(void* p) {
35
- std::vector<std::string>* path = static_cast<std::vector<std::string>*>(p);
36
- delete path;
37
- }
39
+ std::unique_ptr<AttributeInterface> Copy() const override {
40
+ return absl::make_unique<HierarchicalPathAttribute>(path_);
41
+ }
38
42
 
39
- int HierarchicalPathCompare(void* p1, void* p2) {
40
- std::vector<std::string>* path1 = static_cast<std::vector<std::string>*>(p1);
41
- std::vector<std::string>* path2 = static_cast<std::vector<std::string>*>(p2);
42
- for (size_t i = 0; i < path1->size(); ++i) {
43
- if (path2->size() == i) return 1;
44
- int r = (*path1)[i].compare((*path2)[i]);
45
- if (r != 0) return r;
43
+ int Cmp(const AttributeInterface* other) const override {
44
+ const std::vector<std::string>& other_path =
45
+ static_cast<const HierarchicalPathAttribute*>(other)->path_;
46
+ for (size_t i = 0; i < path_.size(); ++i) {
47
+ if (other_path.size() == i) return 1;
48
+ int r = path_[i].compare(other_path[i]);
49
+ if (r != 0) return r;
50
+ }
51
+ if (other_path.size() > path_.size()) return -1;
52
+ return 0;
46
53
  }
47
- if (path2->size() > path1->size()) return -1;
48
- return 0;
49
- }
50
54
 
51
- const grpc_arg_pointer_vtable hierarchical_path_arg_vtable = {
52
- HierarchicalPathCopy, HierarchicalPathDestroy, HierarchicalPathCompare};
55
+ std::string ToString() const override {
56
+ return absl::StrCat("[", absl::StrJoin(path_, ", "), "]");
57
+ }
58
+
59
+ const std::vector<std::string>& path() const { return path_; }
60
+
61
+ private:
62
+ std::vector<std::string> path_;
63
+ };
53
64
 
54
65
  } // namespace
55
66
 
56
- grpc_arg MakeHierarchicalPathArg(const std::vector<std::string>& path) {
57
- return grpc_channel_arg_pointer_create(
58
- const_cast<char*>(GRPC_ARG_HIERARCHICAL_PATH),
59
- const_cast<std::vector<std::string>*>(&path),
60
- &hierarchical_path_arg_vtable);
67
+ std::unique_ptr<ServerAddress::AttributeInterface>
68
+ MakeHierarchicalPathAttribute(std::vector<std::string> path) {
69
+ return absl::make_unique<HierarchicalPathAttribute>(std::move(path));
61
70
  }
62
71
 
63
72
  HierarchicalAddressMap MakeHierarchicalAddressMap(
64
73
  const ServerAddressList& addresses) {
65
74
  HierarchicalAddressMap result;
66
75
  for (const ServerAddress& address : addresses) {
67
- auto* path = grpc_channel_args_find_pointer<std::vector<std::string>>(
68
- address.args(), GRPC_ARG_HIERARCHICAL_PATH);
69
- if (path == nullptr || path->empty()) continue;
70
- auto it = path->begin();
76
+ const HierarchicalPathAttribute* path_attribute =
77
+ static_cast<const HierarchicalPathAttribute*>(
78
+ address.GetAttribute(kHierarchicalPathAttributeKey));
79
+ if (path_attribute == nullptr) continue;
80
+ const std::vector<std::string>& path = path_attribute->path();
81
+ auto it = path.begin();
71
82
  ServerAddressList& target_list = result[*it];
83
+ std::unique_ptr<HierarchicalPathAttribute> new_attribute;
72
84
  ++it;
73
- std::vector<std::string> remaining_path(it, path->end());
74
- const char* name_to_remove = GRPC_ARG_HIERARCHICAL_PATH;
75
- grpc_arg new_arg = MakeHierarchicalPathArg(remaining_path);
76
- grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
77
- address.args(), &name_to_remove, 1, &new_arg, 1);
78
- target_list.emplace_back(address.address(), new_args);
85
+ if (it != path.end()) {
86
+ std::vector<std::string> remaining_path(it, path.end());
87
+ new_attribute = absl::make_unique<HierarchicalPathAttribute>(
88
+ std::move(remaining_path));
89
+ }
90
+ target_list.emplace_back(address.WithAttribute(
91
+ kHierarchicalPathAttributeKey, std::move(new_attribute)));
79
92
  }
80
93
  return result;
81
94
  }
@@ -23,8 +23,6 @@
23
23
  #include <string>
24
24
  #include <vector>
25
25
 
26
- #include "absl/strings/string_view.h"
27
-
28
26
  #include "src/core/ext/filters/client_channel/server_address.h"
29
27
 
30
28
  // The resolver returns a flat list of addresses. When a hierarchy of
@@ -81,9 +79,13 @@
81
79
 
82
80
  namespace grpc_core {
83
81
 
84
- // Constructs a channel arg containing the hierarchical path
85
- // to be associated with an address.
86
- grpc_arg MakeHierarchicalPathArg(const std::vector<std::string>& path);
82
+ // The attribute key to be used for hierarchical paths in ServerAddress.
83
+ extern const char* kHierarchicalPathAttributeKey;
84
+
85
+ // Constructs an address attribute containing the hierarchical path
86
+ // to be associated with the address.
87
+ std::unique_ptr<ServerAddress::AttributeInterface>
88
+ MakeHierarchicalPathAttribute(std::vector<std::string> path);
87
89
 
88
90
  // A map from the next path element to the addresses that fall under
89
91
  // that path element.
@@ -39,10 +39,11 @@ class ChildPolicyHandler::Helper
39
39
  ~Helper() { parent_.reset(DEBUG_LOCATION, "Helper"); }
40
40
 
41
41
  RefCountedPtr<SubchannelInterface> CreateSubchannel(
42
- const grpc_channel_args& args) override {
42
+ ServerAddress address, const grpc_channel_args& args) override {
43
43
  if (parent_->shutting_down_) return nullptr;
44
44
  if (!CalledByCurrentChild() && !CalledByPendingChild()) return nullptr;
45
- return parent_->channel_control_helper()->CreateSubchannel(args);
45
+ return parent_->channel_control_helper()->CreateSubchannel(
46
+ std::move(address), args);
46
47
  }
47
48
 
48
49
  void UpdateState(grpc_connectivity_state state, const absl::Status& status,
@@ -124,6 +124,8 @@ TraceFlag grpc_lb_glb_trace(false, "glb");
124
124
  const char kGrpcLbClientStatsMetadataKey[] = "grpclb_client_stats";
125
125
  const char kGrpcLbLbTokenMetadataKey[] = "lb-token";
126
126
 
127
+ const char kGrpcLbAddressAttributeKey[] = "grpclb";
128
+
127
129
  namespace {
128
130
 
129
131
  constexpr char kGrpclb[] = "grpclb";
@@ -233,6 +235,40 @@ class GrpcLb : public LoadBalancingPolicy {
233
235
  grpc_closure client_load_report_closure_;
234
236
  };
235
237
 
238
+ class TokenAndClientStatsAttribute
239
+ : public ServerAddress::AttributeInterface {
240
+ public:
241
+ TokenAndClientStatsAttribute(std::string lb_token,
242
+ RefCountedPtr<GrpcLbClientStats> client_stats)
243
+ : lb_token_(std::move(lb_token)),
244
+ client_stats_(std::move(client_stats)) {}
245
+
246
+ std::unique_ptr<AttributeInterface> Copy() const override {
247
+ return absl::make_unique<TokenAndClientStatsAttribute>(lb_token_,
248
+ client_stats_);
249
+ }
250
+
251
+ int Cmp(const AttributeInterface* other_base) const override {
252
+ const TokenAndClientStatsAttribute* other =
253
+ static_cast<const TokenAndClientStatsAttribute*>(other_base);
254
+ int r = lb_token_.compare(other->lb_token_);
255
+ if (r != 0) return r;
256
+ return GPR_ICMP(client_stats_.get(), other->client_stats_.get());
257
+ }
258
+
259
+ std::string ToString() const override {
260
+ return absl::StrFormat("lb_token=\"%s\" client_stats=%p", lb_token_,
261
+ client_stats_.get());
262
+ }
263
+
264
+ const std::string& lb_token() const { return lb_token_; }
265
+ GrpcLbClientStats* client_stats() const { return client_stats_.get(); }
266
+
267
+ private:
268
+ std::string lb_token_;
269
+ RefCountedPtr<GrpcLbClientStats> client_stats_;
270
+ };
271
+
236
272
  class Serverlist : public RefCounted<Serverlist> {
237
273
  public:
238
274
  // Takes ownership of serverlist.
@@ -302,7 +338,7 @@ class GrpcLb : public LoadBalancingPolicy {
302
338
  : parent_(std::move(parent)) {}
303
339
 
304
340
  RefCountedPtr<SubchannelInterface> CreateSubchannel(
305
- const grpc_channel_args& args) override;
341
+ ServerAddress address, const grpc_channel_args& args) override;
306
342
  void UpdateState(grpc_connectivity_state state, const absl::Status& status,
307
343
  std::unique_ptr<SubchannelPicker> picker) override;
308
344
  void RequestReresolution() override;
@@ -352,6 +388,8 @@ class GrpcLb : public LoadBalancingPolicy {
352
388
  // Helper functions used in UpdateLocked().
353
389
  void ProcessAddressesAndChannelArgsLocked(const ServerAddressList& addresses,
354
390
  const grpc_channel_args& args);
391
+ static ServerAddressList AddNullLbTokenToAddresses(
392
+ const ServerAddressList& addresses);
355
393
 
356
394
  void CancelBalancerChannelConnectivityWatchLocked();
357
395
 
@@ -389,6 +427,8 @@ class GrpcLb : public LoadBalancingPolicy {
389
427
  StateWatcher* watcher_ = nullptr;
390
428
  // Response generator to inject address updates into lb_channel_.
391
429
  RefCountedPtr<FakeResolverResponseGenerator> response_generator_;
430
+ // Parent channelz node.
431
+ RefCountedPtr<channelz::ChannelNode> parent_channelz_node_;
392
432
 
393
433
  // The data associated with the current LB call. It holds a ref to this LB
394
434
  // policy. It's initialized every time we query for backends. It's reset to
@@ -473,44 +513,6 @@ std::string GrpcLb::Serverlist::AsText() const {
473
513
  return absl::StrJoin(entries, "");
474
514
  }
475
515
 
476
- // vtables for channel args for LB token and client stats.
477
- void* lb_token_copy(void* token) {
478
- return gpr_strdup(static_cast<char*>(token));
479
- }
480
- void lb_token_destroy(void* token) { gpr_free(token); }
481
- void* client_stats_copy(void* p) {
482
- GrpcLbClientStats* client_stats = static_cast<GrpcLbClientStats*>(p);
483
- client_stats->Ref().release();
484
- return p;
485
- }
486
- void client_stats_destroy(void* p) {
487
- GrpcLbClientStats* client_stats = static_cast<GrpcLbClientStats*>(p);
488
- client_stats->Unref();
489
- }
490
- int equal_cmp(void* /*p1*/, void* /*p2*/) {
491
- // Always indicate a match, since we don't want this channel arg to
492
- // affect the subchannel's key in the index.
493
- // TODO(roth): Is this right? This does prevent us from needlessly
494
- // recreating the subchannel whenever the LB token or client stats
495
- // changes (i.e., when the balancer call is terminated and reestablished).
496
- // However, it means that we don't actually recreate the subchannel,
497
- // which means that we won't ever switch over to using the new LB
498
- // token or client stats. A better approach might be to find somewhere
499
- // other than the subchannel args to store the LB token and client
500
- // stats. They could be stored in a map and then looked up for each
501
- // call. Or we could do something more complicated whereby
502
- // we create our own subchannel wrapper to store them, although that would
503
- // involve a lot of refcounting overhead.
504
- // Given that we're trying to move from grpclb to xds at this point,
505
- // and that no one has actually reported any problems with this, we
506
- // probably won't bother fixing this at this point.
507
- return 0;
508
- }
509
- const grpc_arg_pointer_vtable lb_token_arg_vtable = {
510
- lb_token_copy, lb_token_destroy, equal_cmp};
511
- const grpc_arg_pointer_vtable client_stats_arg_vtable = {
512
- client_stats_copy, client_stats_destroy, equal_cmp};
513
-
514
516
  bool IsServerValid(const GrpcLbServer& server, size_t idx, bool log) {
515
517
  if (server.drop) return false;
516
518
  if (GPR_UNLIKELY(server.port >> 16 != 0)) {
@@ -536,6 +538,8 @@ bool IsServerValid(const GrpcLbServer& server, size_t idx, bool log) {
536
538
  // Returns addresses extracted from the serverlist.
537
539
  ServerAddressList GrpcLb::Serverlist::GetServerAddressList(
538
540
  GrpcLbClientStats* client_stats) const {
541
+ RefCountedPtr<GrpcLbClientStats> stats;
542
+ if (client_stats != nullptr) stats = client_stats->Ref();
539
543
  ServerAddressList addresses;
540
544
  for (size_t i = 0; i < serverlist_.size(); ++i) {
541
545
  const GrpcLbServer& server = serverlist_[i];
@@ -544,34 +548,23 @@ ServerAddressList GrpcLb::Serverlist::GetServerAddressList(
544
548
  grpc_resolved_address addr;
545
549
  ParseServer(server, &addr);
546
550
  // LB token processing.
547
- char lb_token[GPR_ARRAY_SIZE(server.load_balance_token) + 1];
548
- if (server.load_balance_token[0] != 0) {
549
- const size_t lb_token_max_length =
550
- GPR_ARRAY_SIZE(server.load_balance_token);
551
- const size_t lb_token_length =
552
- strnlen(server.load_balance_token, lb_token_max_length);
553
- memcpy(lb_token, server.load_balance_token, lb_token_length);
554
- lb_token[lb_token_length] = '\0';
555
- } else {
551
+ const size_t lb_token_length = strnlen(
552
+ server.load_balance_token, GPR_ARRAY_SIZE(server.load_balance_token));
553
+ std::string lb_token(server.load_balance_token, lb_token_length);
554
+ if (lb_token.empty()) {
556
555
  gpr_log(GPR_INFO,
557
556
  "Missing LB token for backend address '%s'. The empty token will "
558
557
  "be used instead",
559
558
  grpc_sockaddr_to_uri(&addr).c_str());
560
- lb_token[0] = '\0';
561
559
  }
560
+ // Attach attribute to address containing LB token and stats object.
561
+ std::map<const char*, std::unique_ptr<ServerAddress::AttributeInterface>>
562
+ attributes;
563
+ attributes[kGrpcLbAddressAttributeKey] =
564
+ absl::make_unique<TokenAndClientStatsAttribute>(std::move(lb_token),
565
+ stats);
562
566
  // Add address.
563
- absl::InlinedVector<grpc_arg, 2> args_to_add;
564
- args_to_add.emplace_back(grpc_channel_arg_pointer_create(
565
- const_cast<char*>(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN), lb_token,
566
- &lb_token_arg_vtable));
567
- if (client_stats != nullptr) {
568
- args_to_add.emplace_back(grpc_channel_arg_pointer_create(
569
- const_cast<char*>(GRPC_ARG_GRPCLB_ADDRESS_CLIENT_STATS), client_stats,
570
- &client_stats_arg_vtable));
571
- }
572
- grpc_channel_args* args = grpc_channel_args_copy_and_add(
573
- nullptr, args_to_add.data(), args_to_add.size());
574
- addresses.emplace_back(addr, args);
567
+ addresses.emplace_back(addr, /*args=*/nullptr, std::move(attributes));
575
568
  }
576
569
  return addresses;
577
570
  }
@@ -616,15 +609,18 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
616
609
  // If pick succeeded, add LB token to initial metadata.
617
610
  if (result.type == PickResult::PICK_COMPLETE &&
618
611
  result.subchannel != nullptr) {
612
+ const TokenAndClientStatsAttribute* attribute =
613
+ static_cast<const TokenAndClientStatsAttribute*>(
614
+ result.subchannel->GetAttribute(kGrpcLbAddressAttributeKey));
615
+ if (attribute == nullptr) {
616
+ gpr_log(GPR_ERROR, "[grpclb %p picker %p] No LB token for subchannel %p",
617
+ parent_, this, result.subchannel.get());
618
+ abort();
619
+ }
619
620
  // Encode client stats object into metadata for use by
620
621
  // client_load_reporting filter.
621
- const grpc_arg* arg =
622
- grpc_channel_args_find(result.subchannel->channel_args(),
623
- GRPC_ARG_GRPCLB_ADDRESS_CLIENT_STATS);
624
- if (arg != nullptr && arg->type == GRPC_ARG_POINTER &&
625
- arg->value.pointer.p != nullptr) {
626
- GrpcLbClientStats* client_stats =
627
- static_cast<GrpcLbClientStats*>(arg->value.pointer.p);
622
+ GrpcLbClientStats* client_stats = attribute->client_stats();
623
+ if (client_stats != nullptr) {
628
624
  client_stats->Ref().release(); // Ref passed via metadata.
629
625
  // The metadata value is a hack: we pretend the pointer points to
630
626
  // a string and rely on the client_load_reporting filter to know
@@ -636,15 +632,13 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
636
632
  client_stats->AddCallStarted();
637
633
  }
638
634
  // Encode the LB token in metadata.
639
- arg = grpc_channel_args_find(result.subchannel->channel_args(),
640
- GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN);
641
- if (arg == nullptr) {
642
- gpr_log(GPR_ERROR, "[grpclb %p picker %p] No LB token for subchannel %p",
643
- parent_, this, result.subchannel.get());
644
- abort();
645
- }
646
- args.initial_metadata->Add(kGrpcLbLbTokenMetadataKey,
647
- static_cast<char*>(arg->value.pointer.p));
635
+ // Create a new copy on the call arena, since the subchannel list
636
+ // may get refreshed between when we return this pick and when the
637
+ // initial metadata goes out on the wire.
638
+ char* lb_token = static_cast<char*>(
639
+ args.call_state->Alloc(attribute->lb_token().size() + 1));
640
+ strcpy(lb_token, attribute->lb_token().c_str());
641
+ args.initial_metadata->Add(kGrpcLbLbTokenMetadataKey, lb_token);
648
642
  }
649
643
  return result;
650
644
  }
@@ -654,9 +648,10 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
654
648
  //
655
649
 
656
650
  RefCountedPtr<SubchannelInterface> GrpcLb::Helper::CreateSubchannel(
657
- const grpc_channel_args& args) {
651
+ ServerAddress address, const grpc_channel_args& args) {
658
652
  if (parent_->shutting_down_) return nullptr;
659
- return parent_->channel_control_helper()->CreateSubchannel(args);
653
+ return parent_->channel_control_helper()->CreateSubchannel(std::move(address),
654
+ args);
660
655
  }
661
656
 
662
657
  void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
@@ -1287,25 +1282,18 @@ grpc_channel_args* BuildBalancerChannelArgs(
1287
1282
  GRPC_ARG_CHANNELZ_CHANNEL_NODE,
1288
1283
  };
1289
1284
  // Channel args to add.
1290
- absl::InlinedVector<grpc_arg, 3> args_to_add;
1291
- // The fake resolver response generator, which we use to inject
1292
- // address updates into the LB channel.
1293
- args_to_add.emplace_back(
1285
+ absl::InlinedVector<grpc_arg, 3> args_to_add = {
1286
+ // The fake resolver response generator, which we use to inject
1287
+ // address updates into the LB channel.
1294
1288
  grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
1295
- response_generator));
1296
- // A channel arg indicating the target is a grpclb load balancer.
1297
- args_to_add.emplace_back(grpc_channel_arg_integer_create(
1298
- const_cast<char*>(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1));
1299
- // The parent channel's channelz uuid.
1300
- channelz::ChannelNode* channelz_node = nullptr;
1301
- const grpc_arg* arg =
1302
- grpc_channel_args_find(args, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
1303
- if (arg != nullptr && arg->type == GRPC_ARG_POINTER &&
1304
- arg->value.pointer.p != nullptr) {
1305
- channelz_node = static_cast<channelz::ChannelNode*>(arg->value.pointer.p);
1306
- args_to_add.emplace_back(
1307
- channelz::MakeParentUuidArg(channelz_node->uuid()));
1308
- }
1289
+ response_generator),
1290
+ // A channel arg indicating the target is a grpclb load balancer.
1291
+ grpc_channel_arg_integer_create(
1292
+ const_cast<char*>(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1),
1293
+ // Tells channelz that this is an internal channel.
1294
+ grpc_channel_arg_integer_create(
1295
+ const_cast<char*>(GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL), 1),
1296
+ };
1309
1297
  // Construct channel args.
1310
1298
  grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
1311
1299
  args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add.data(),
@@ -1382,6 +1370,12 @@ void GrpcLb::ShutdownLocked() {
1382
1370
  // OnBalancerChannelConnectivityChangedLocked(), and we need to be
1383
1371
  // alive when that callback is invoked.
1384
1372
  if (lb_channel_ != nullptr) {
1373
+ if (parent_channelz_node_ != nullptr) {
1374
+ channelz::ChannelNode* child_channelz_node =
1375
+ grpc_channel_get_channelz_node(lb_channel_);
1376
+ GPR_ASSERT(child_channelz_node != nullptr);
1377
+ parent_channelz_node_->RemoveChildChannel(child_channelz_node->uuid());
1378
+ }
1385
1379
  grpc_channel_destroy(lb_channel_);
1386
1380
  lb_channel_ = nullptr;
1387
1381
  }
@@ -1435,17 +1429,13 @@ void GrpcLb::UpdateLocked(UpdateArgs args) {
1435
1429
  // helpers for UpdateLocked()
1436
1430
  //
1437
1431
 
1438
- ServerAddressList AddNullLbTokenToAddresses(
1432
+ ServerAddressList GrpcLb::AddNullLbTokenToAddresses(
1439
1433
  const ServerAddressList& addresses) {
1440
- static const char* lb_token = "";
1441
- grpc_arg arg = grpc_channel_arg_pointer_create(
1442
- const_cast<char*>(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN),
1443
- const_cast<char*>(lb_token), &lb_token_arg_vtable);
1444
1434
  ServerAddressList addresses_out;
1445
- for (size_t i = 0; i < addresses.size(); ++i) {
1446
- addresses_out.emplace_back(
1447
- addresses[i].address(),
1448
- grpc_channel_args_copy_and_add(addresses[i].args(), &arg, 1));
1435
+ for (const ServerAddress& address : addresses) {
1436
+ addresses_out.emplace_back(address.WithAttribute(
1437
+ kGrpcLbAddressAttributeKey,
1438
+ absl::make_unique<TokenAndClientStatsAttribute>("", nullptr)));
1449
1439
  }
1450
1440
  return addresses_out;
1451
1441
  }
@@ -1472,6 +1462,16 @@ void GrpcLb::ProcessAddressesAndChannelArgsLocked(
1472
1462
  lb_channel_ =
1473
1463
  CreateGrpclbBalancerChannel(uri_str.c_str(), *lb_channel_args);
1474
1464
  GPR_ASSERT(lb_channel_ != nullptr);
1465
+ // Set up channelz linkage.
1466
+ channelz::ChannelNode* child_channelz_node =
1467
+ grpc_channel_get_channelz_node(lb_channel_);
1468
+ channelz::ChannelNode* parent_channelz_node =
1469
+ grpc_channel_args_find_pointer<channelz::ChannelNode>(
1470
+ &args, GRPC_ARG_CHANNELZ_CHANNEL_NODE);
1471
+ if (child_channelz_node != nullptr && parent_channelz_node != nullptr) {
1472
+ parent_channelz_node->AddChildChannel(child_channelz_node->uuid());
1473
+ parent_channelz_node_ = parent_channelz_node->Ref();
1474
+ }
1475
1475
  }
1476
1476
  // Propagate updates to the LB channel (pick_first) through the fake
1477
1477
  // resolver.