Merge pull request #20544 from markdroth/xds_cds_policy

CDS LB policy
pull/20865/head
Mark D. Roth 5 years ago committed by GitHub
commit fa6920f601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      BUILD
  2. 1
      BUILD.gn
  3. 4
      CMakeLists.txt
  4. 4
      Makefile
  5. 18
      build.yaml
  6. 3
      config.m4
  7. 3
      config.w32
  8. 1
      gRPC-Core.podspec
  9. 3
      grpc.gemspec
  10. 4
      grpc.gyp
  11. 3
      package.xml
  12. 3
      src/core/ext/filters/client_channel/lb_policy.h
  13. 368
      src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
  14. 12
      src/core/ext/filters/client_channel/xds/xds_api.h
  15. 44
      src/core/ext/filters/client_channel/xds/xds_client.cc
  16. 4
      src/core/plugin_registry/grpc_plugin_registry.cc
  17. 4
      src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
  18. 3
      src/python/grpcio/grpc_core_dependencies.py
  19. 6
      test/cpp/end2end/xds_end2end_test.cc
  20. 1
      tools/doxygen/Doxyfile.core.internal

28
BUILD

@ -320,6 +320,7 @@ grpc_cc_library(
"grpc_common",
"grpc_lb_policy_grpclb",
"grpc_lb_policy_xds",
"grpc_lb_policy_cds",
"grpc_resolver_xds",
],
)
@ -337,6 +338,7 @@ grpc_cc_library(
"grpc_common",
"grpc_lb_policy_grpclb_secure",
"grpc_lb_policy_xds_secure",
"grpc_lb_policy_cds_secure",
"grpc_resolver_xds_secure",
"grpc_secure",
"grpc_transport_chttp2_client_secure",
@ -1336,6 +1338,32 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "grpc_lb_policy_cds",
srcs = [
"src/core/ext/filters/client_channel/lb_policy/xds/cds.cc",
],
language = "c++",
deps = [
"grpc_base",
"grpc_client_channel",
"grpc_xds_client",
],
)
grpc_cc_library(
name = "grpc_lb_policy_cds_secure",
srcs = [
"src/core/ext/filters/client_channel/lb_policy/xds/cds.cc",
],
language = "c++",
deps = [
"grpc_base",
"grpc_client_channel",
"grpc_xds_client_secure",
],
)
grpc_cc_library(
name = "grpc_lb_subchannel_list",
hdrs = [

@ -244,6 +244,7 @@ config("grpc_config") {
"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc",
"src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc",
"src/core/ext/filters/client_channel/lb_policy/subchannel_list.h",
"src/core/ext/filters/client_channel/lb_policy/xds/cds.cc",
"src/core/ext/filters/client_channel/lb_policy/xds/xds.cc",
"src/core/ext/filters/client_channel/lb_policy/xds/xds.h",
"src/core/ext/filters/client_channel/lb_policy_factory.h",

@ -1403,7 +1403,7 @@ add_library(grpc
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
src/core/ext/filters/client_channel/xds/xds_api.cc
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
@ -1430,6 +1430,7 @@ add_library(grpc
src/core/ext/upb-generated/envoy/type/http.upb.c
src/core/ext/upb-generated/envoy/type/percent.upb.c
src/core/ext/upb-generated/envoy/type/range.upb.c
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
@ -2964,6 +2965,7 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc

@ -3856,7 +3856,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc \
src/core/ext/filters/client_channel/xds/xds_channel_secure.cc \
@ -3883,6 +3883,7 @@ LIBGRPC_SRC = \
src/core/ext/upb-generated/envoy/type/http.upb.c \
src/core/ext/upb-generated/envoy/type/percent.upb.c \
src/core/ext/upb-generated/envoy/type/range.upb.c \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
@ -5353,6 +5354,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \

@ -1067,6 +1067,22 @@ filegroups:
plugin: grpc_http_filters
uses:
- grpc_base
- name: grpc_lb_policy_cds
src:
- src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
plugin: grpc_lb_policy_cds
uses:
- grpc_base
- grpc_client_channel
- grpc_xds_client
- name: grpc_lb_policy_cds_secure
src:
- src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
plugin: grpc_lb_policy_cds
uses:
- grpc_base
- grpc_client_channel
- grpc_xds_client_secure
- name: grpc_lb_policy_grpclb
headers:
- src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h
@ -1683,6 +1699,7 @@ libs:
- grpc_transport_chttp2_client_insecure
- grpc_transport_inproc
- grpc_lb_policy_grpclb_secure
- grpc_lb_policy_cds_secure
- grpc_lb_policy_xds_secure
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin
@ -1764,6 +1781,7 @@ libs:
- grpc_resolver_fake
- grpc_resolver_xds
- grpc_lb_policy_grpclb
- grpc_lb_policy_cds
- grpc_lb_policy_xds
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin

@ -416,7 +416,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc \
src/core/ext/filters/client_channel/xds/xds_channel_secure.cc \
@ -443,6 +443,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/upb-generated/envoy/type/http.upb.c \
src/core/ext/upb-generated/envoy/type/percent.upb.c \
src/core/ext/upb-generated/envoy/type/range.upb.c \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \

@ -386,7 +386,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\load_balancer_api.cc " +
"src\\core\\ext\\upb-generated\\src\\proto\\grpc\\lb\\v1\\load_balancer.upb.c " +
"src\\core\\ext\\filters\\client_channel\\resolver\\fake\\fake_resolver.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\xds.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\cds.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_api.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_bootstrap.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_channel_secure.cc " +
@ -413,6 +413,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\upb-generated\\envoy\\type\\http.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\type\\percent.upb.c " +
"src\\core\\ext\\upb-generated\\envoy\\type\\range.upb.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\xds.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first\\pick_first.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin\\round_robin.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.cc " +

@ -226,6 +226,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.h',
'src/core/ext/filters/client_channel/lb_policy_factory.h',

@ -848,7 +848,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc )
s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c )
s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/xds/xds.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/xds/cds.cc )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_api.cc )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_bootstrap.cc )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_channel_secure.cc )
@ -875,6 +875,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upb-generated/envoy/type/http.upb.c )
s.files += %w( src/core/ext/upb-generated/envoy/type/percent.upb.c )
s.files += %w( src/core/ext/upb-generated/envoy/type/range.upb.c )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/xds/xds.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc )

@ -554,7 +554,7 @@
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',
'src/core/ext/filters/client_channel/xds/xds_bootstrap.cc',
'src/core/ext/filters/client_channel/xds/xds_channel_secure.cc',
@ -581,6 +581,7 @@
'src/core/ext/upb-generated/envoy/type/http.upb.c',
'src/core/ext/upb-generated/envoy/type/percent.upb.c',
'src/core/ext/upb-generated/envoy/type/range.upb.c',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
@ -1449,6 +1450,7 @@
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',

@ -853,7 +853,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/xds/xds.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/xds/cds.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_api.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_bootstrap.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_channel_secure.cc" role="src" />
@ -880,6 +880,7 @@
<file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/http.upb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/percent.upb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/upb-generated/envoy/type/range.upb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/xds/xds.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc" role="src" />

@ -320,6 +320,9 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
UniquePtr<ChannelControlHelper> channel_control_helper;
/// Channel args.
// TODO(roth): Find a better channel args representation for this API.
// TODO(roth): Clarify ownership semantics here -- currently, this
// does not take ownership of args, which is the opposite of how we
// handle them in UpdateArgs.
const grpc_channel_args* args = nullptr;
};

@ -0,0 +1,368 @@
//
// Copyright 2019 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <grpc/support/port_platform.h>
#include <string.h>
#include "src/core/ext/filters/client_channel/lb_policy.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/xds/xds_client.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
namespace grpc_core {
TraceFlag grpc_cds_lb_trace(false, "cds_lb");
namespace {
constexpr char kCds[] = "cds_experimental";
// Parsed config for this LB policy.
class ParsedCdsConfig : public LoadBalancingPolicy::Config {
public:
explicit ParsedCdsConfig(UniquePtr<char> cluster)
: cluster_(std::move(cluster)) {}
const char* cluster() const { return cluster_.get(); }
const char* name() const override { return kCds; }
private:
UniquePtr<char> cluster_;
};
// CDS LB policy.
class CdsLb : public LoadBalancingPolicy {
public:
explicit CdsLb(Args args);
const char* name() const override { return kCds; }
void UpdateLocked(UpdateArgs args) override;
void ResetBackoffLocked() override;
private:
// Watcher for getting cluster data from XdsClient.
class ClusterWatcher : public XdsClient::ClusterWatcherInterface {
public:
explicit ClusterWatcher(RefCountedPtr<CdsLb> parent)
: parent_(std::move(parent)) {}
void OnClusterChanged(CdsUpdate cluster_data) override;
void OnError(grpc_error* error) override;
private:
RefCountedPtr<CdsLb> parent_;
};
// Delegating helper to be passed to child policy.
class Helper : public ChannelControlHelper {
public:
explicit Helper(RefCountedPtr<CdsLb> parent) : parent_(std::move(parent)) {}
RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
UniquePtr<SubchannelPicker> picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, StringView message) override;
private:
RefCountedPtr<CdsLb> parent_;
};
~CdsLb();
void ShutdownLocked() override;
RefCountedPtr<ParsedCdsConfig> config_;
// Current channel args from the resolver.
const grpc_channel_args* args_ = nullptr;
// The xds client.
RefCountedPtr<XdsClient> xds_client_;
// A pointer to the cluster watcher, to be used when cancelling the watch.
// Note that this is not owned, so this pointer must never be derefernced.
ClusterWatcher* cluster_watcher_ = nullptr;
// Child LB policy.
OrphanablePtr<LoadBalancingPolicy> child_policy_;
// Internal state.
bool shutting_down_ = false;
};
//
// CdsLb::ClusterWatcher
//
void CdsLb::ClusterWatcher::OnClusterChanged(CdsUpdate cluster_data) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] received CDS update from xds client",
parent_.get());
}
// Construct config for child policy.
char* lrs_str = nullptr;
if (cluster_data.lrs_load_reporting_server_name != nullptr) {
gpr_asprintf(&lrs_str, " \"lrsLoadReportingServerName\": \"%s\",\n",
cluster_data.lrs_load_reporting_server_name.get());
}
char* json_str;
gpr_asprintf(&json_str,
"[{\n"
" \"xds_experimental\": {\n"
"%s"
" \"edsServiceName\": \"%s\"\n"
" }\n"
"}]",
(lrs_str == nullptr ? "" : lrs_str),
(cluster_data.eds_service_name == nullptr
? parent_->config_->cluster()
: cluster_data.eds_service_name.get()));
gpr_free(lrs_str);
UniquePtr<char> json_str_deleter(json_str);
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] generated config for child policy: %s",
parent_.get(), json_str);
}
grpc_json* json = grpc_json_parse_string(json_str);
if (json == nullptr) {
char* msg;
gpr_asprintf(&msg, "Could not parse LB config: %s", json_str);
OnError(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
gpr_free(msg);
return;
}
grpc_error* error = GRPC_ERROR_NONE;
RefCountedPtr<LoadBalancingPolicy::Config> config =
LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(json, &error);
grpc_json_destroy(json);
if (error != GRPC_ERROR_NONE) {
OnError(error);
return;
}
// Create child policy if not already present.
if (parent_->child_policy_ == nullptr) {
LoadBalancingPolicy::Args args;
args.combiner = parent_->combiner();
args.args = parent_->args_;
args.channel_control_helper = MakeUnique<Helper>(parent_->Ref());
parent_->child_policy_ =
LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
"xds_experimental", std::move(args));
grpc_pollset_set_add_pollset_set(
parent_->child_policy_->interested_parties(),
parent_->interested_parties());
}
// Update child policy.
UpdateArgs args;
args.config = std::move(config);
args.args = grpc_channel_args_copy(parent_->args_);
parent_->child_policy_->UpdateLocked(std::move(args));
}
void CdsLb::ClusterWatcher::OnError(grpc_error* error) {
gpr_log(GPR_ERROR, "[cdslb %p] xds error obtaining data for cluster %s: %s",
parent_.get(), parent_->config_->cluster(), grpc_error_string(error));
// Go into TRANSIENT_FAILURE if we have not yet created the child
// policy (i.e., we have not yet received data from xds). Otherwise,
// we keep running with the data we had previously.
if (parent_->child_policy_ == nullptr) {
parent_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE,
MakeUnique<TransientFailurePicker>(error));
} else {
GRPC_ERROR_UNREF(error);
}
}
//
// CdsLb::Helper
//
RefCountedPtr<SubchannelInterface> CdsLb::Helper::CreateSubchannel(
const grpc_channel_args& args) {
if (parent_->shutting_down_) return nullptr;
return parent_->channel_control_helper()->CreateSubchannel(args);
}
void CdsLb::Helper::UpdateState(grpc_connectivity_state state,
UniquePtr<SubchannelPicker> picker) {
if (parent_->shutting_down_) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] state updated by child: %s", this,
ConnectivityStateName(state));
}
parent_->channel_control_helper()->UpdateState(state, std::move(picker));
}
void CdsLb::Helper::RequestReresolution() {
if (parent_->shutting_down_) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] Re-resolution requested from child policy.",
parent_.get());
}
parent_->channel_control_helper()->RequestReresolution();
}
void CdsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
if (parent_->shutting_down_) return;
parent_->channel_control_helper()->AddTraceEvent(severity, message);
}
//
// CdsLb
//
CdsLb::CdsLb(Args args)
: LoadBalancingPolicy(std::move(args)),
xds_client_(XdsClient::GetFromChannelArgs(*args.args)) {
if (xds_client_ != nullptr && GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] Using xds client %p from channel", this,
xds_client_.get());
}
}
CdsLb::~CdsLb() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] destroying cds LB policy", this);
}
grpc_channel_args_destroy(args_);
}
void CdsLb::ShutdownLocked() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] shutting down", this);
}
shutting_down_ = true;
if (child_policy_ != nullptr) {
grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
interested_parties());
child_policy_.reset();
}
if (xds_client_ != nullptr) {
if (cluster_watcher_ != nullptr) {
xds_client_->CancelClusterDataWatch(StringView(config_->cluster()),
cluster_watcher_);
}
xds_client_.reset();
}
}
void CdsLb::ResetBackoffLocked() {
if (child_policy_ != nullptr) child_policy_->ResetBackoffLocked();
}
void CdsLb::UpdateLocked(UpdateArgs args) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] received update", this);
}
// Update config.
auto old_config = std::move(config_);
config_ = std::move(args.config);
// Update args.
grpc_channel_args_destroy(args_);
args_ = args.args;
args.args = nullptr;
// If cluster name changed, cancel watcher and restart.
if (old_config == nullptr ||
strcmp(old_config->cluster(), config_->cluster()) != 0) {
if (old_config != nullptr) {
xds_client_->CancelClusterDataWatch(StringView(old_config->cluster()),
cluster_watcher_);
}
auto watcher = MakeUnique<ClusterWatcher>(Ref());
cluster_watcher_ = watcher.get();
xds_client_->WatchClusterData(StringView(config_->cluster()),
std::move(watcher));
}
}
//
// factory
//
class CdsFactory : public LoadBalancingPolicyFactory {
public:
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
LoadBalancingPolicy::Args args) const override {
return MakeOrphanable<CdsLb>(std::move(args));
}
const char* name() const override { return kCds; }
RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
const grpc_json* json, grpc_error** error) const override {
GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
if (json == nullptr) {
// xds was mentioned as a policy in the deprecated loadBalancingPolicy
// field or in the client API.
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:loadBalancingPolicy error:cds policy requires configuration. "
"Please use loadBalancingConfig field of service config instead.");
return nullptr;
}
GPR_DEBUG_ASSERT(strcmp(json->key, name()) == 0);
InlinedVector<grpc_error*, 3> error_list;
const char* cluster = nullptr;
for (const grpc_json* field = json->child; field != nullptr;
field = field->next) {
if (field->key == nullptr) continue;
if (strcmp(field->key, "cluster") == 0) {
if (cluster != nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:cluster error:Duplicate entry"));
}
if (field->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:cluster error:type should be string"));
continue;
}
cluster = field->value;
}
}
if (cluster == nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"required field 'cluster' not present"));
}
if (error_list.empty()) {
return MakeRefCounted<ParsedCdsConfig>(
UniquePtr<char>(gpr_strdup(cluster)));
} else {
*error = GRPC_ERROR_CREATE_FROM_VECTOR("Cds Parser", &error_list);
return nullptr;
}
}
};
} // namespace
} // namespace grpc_core
//
// Plugin registration
//
void grpc_lb_policy_cds_init() {
grpc_core::LoadBalancingPolicyRegistry::Builder::
RegisterLoadBalancingPolicyFactory(
grpc_core::MakeUnique<grpc_core::CdsFactory>());
}
void grpc_lb_policy_cds_shutdown() {}

@ -136,8 +136,16 @@ struct EdsUpdate {
bool drop_all = false;
};
// TODO(juanlishen): Add fields as part of implementing CDS support.
struct CdsUpdate {};
struct CdsUpdate {
// The name to use in the EDS request.
// If null, the cluster name will be used.
UniquePtr<char> eds_service_name;
// The LRS server to use for load reporting.
// If null, load reporting will be disabled.
// If set to the empty string, will use the same server we obtained
// the CDS data from.
UniquePtr<char> lrs_load_reporting_server_name;
};
// Creates an EDS request querying \a service_name.
grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name,

@ -1289,14 +1289,27 @@ void XdsClient::Orphan() {
Unref(DEBUG_LOCATION, "XdsClient::Orphan()");
}
void XdsClient::WatchClusterData(
StringView /*cluster*/, UniquePtr<ClusterWatcherInterface> /*watcher*/) {
// TODO(juanlishen): Implement.
void XdsClient::WatchClusterData(StringView cluster,
UniquePtr<ClusterWatcherInterface> watcher) {
ClusterWatcherInterface* w = watcher.get();
cluster_state_.cluster_watchers[w] = std::move(watcher);
// TODO(juanlishen): Start CDS call if not already started and return
// real data via watcher.
CdsUpdate update;
update.eds_service_name = cluster.dup();
update.lrs_load_reporting_server_name.reset(gpr_strdup(""));
w->OnClusterChanged(std::move(update));
}
void XdsClient::CancelClusterDataWatch(StringView /*cluster*/,
ClusterWatcherInterface* /*watcher*/) {
// TODO(juanlishen): Implement.
void XdsClient::CancelClusterDataWatch(StringView cluster,
ClusterWatcherInterface* watcher) {
auto it = cluster_state_.cluster_watchers.find(watcher);
if (it != cluster_state_.cluster_watchers.end()) {
cluster_state_.cluster_watchers.erase(it);
}
if (chand_ != nullptr && cluster_state_.cluster_watchers.empty()) {
// TODO(juanlishen): Stop CDS call.
}
}
void XdsClient::WatchEndpointData(StringView /*cluster*/,
@ -1371,16 +1384,19 @@ void XdsClient::NotifyOnServiceConfig(void* arg, grpc_error* error) {
XdsClient* self = static_cast<XdsClient*>(arg);
// TODO(roth): When we add support for WeightedClusters, select the
// LB policy based on that functionality.
static const char* json =
"{\n"
" \"loadBalancingConfig\":[\n"
" { \"xds_experimental\":{\n"
" \"lrsLoadReportingServerName\": \"\"\n"
" } }\n"
" ]\n"
"}";
char* json;
gpr_asprintf(&json,
"{\n"
" \"loadBalancingConfig\":[\n"
" { \"cds_experimental\":{\n"
" \"cluster\": \"%s\"\n"
" } }\n"
" ]\n"
"}",
self->server_name_.get());
RefCountedPtr<ServiceConfig> service_config =
ServiceConfig::Create(json, &error);
gpr_free(json);
if (error != GRPC_ERROR_NONE) {
self->service_config_watcher_->OnError(error);
} else {

@ -34,6 +34,8 @@ void grpc_resolver_fake_init(void);
void grpc_resolver_fake_shutdown(void);
void grpc_lb_policy_grpclb_init(void);
void grpc_lb_policy_grpclb_shutdown(void);
void grpc_lb_policy_cds_init(void);
void grpc_lb_policy_cds_shutdown(void);
void grpc_lb_policy_xds_init(void);
void grpc_lb_policy_xds_shutdown(void);
void grpc_lb_policy_pick_first_init(void);
@ -74,6 +76,8 @@ void grpc_register_built_in_plugins(void) {
grpc_resolver_fake_shutdown);
grpc_register_plugin(grpc_lb_policy_grpclb_init,
grpc_lb_policy_grpclb_shutdown);
grpc_register_plugin(grpc_lb_policy_cds_init,
grpc_lb_policy_cds_shutdown);
grpc_register_plugin(grpc_lb_policy_xds_init,
grpc_lb_policy_xds_shutdown);
grpc_register_plugin(grpc_lb_policy_pick_first_init,

@ -42,6 +42,8 @@ void grpc_resolver_xds_init(void);
void grpc_resolver_xds_shutdown(void);
void grpc_lb_policy_grpclb_init(void);
void grpc_lb_policy_grpclb_shutdown(void);
void grpc_lb_policy_cds_init(void);
void grpc_lb_policy_cds_shutdown(void);
void grpc_lb_policy_xds_init(void);
void grpc_lb_policy_xds_shutdown(void);
void grpc_lb_policy_pick_first_init(void);
@ -82,6 +84,8 @@ void grpc_register_built_in_plugins(void) {
grpc_resolver_xds_shutdown);
grpc_register_plugin(grpc_lb_policy_grpclb_init,
grpc_lb_policy_grpclb_shutdown);
grpc_register_plugin(grpc_lb_policy_cds_init,
grpc_lb_policy_cds_shutdown);
grpc_register_plugin(grpc_lb_policy_xds_init,
grpc_lb_policy_xds_shutdown);
grpc_register_plugin(grpc_lb_policy_pick_first_init,

@ -385,7 +385,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',
'src/core/ext/filters/client_channel/xds/xds_bootstrap.cc',
'src/core/ext/filters/client_channel/xds/xds_channel_secure.cc',
@ -412,6 +412,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/upb-generated/envoy/type/http.upb.c',
'src/core/ext/upb-generated/envoy/type/percent.upb.c',
'src/core/ext/upb-generated/envoy/type/range.upb.c',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',

@ -1069,7 +1069,9 @@ TEST_P(BasicTest, Vanilla) {
EXPECT_EQ(1U, balancers_[0]->ads_service()->request_count());
EXPECT_EQ(1U, balancers_[0]->ads_service()->response_count());
// Check LB policy name for the channel.
EXPECT_EQ("xds_experimental", channel_->GetLoadBalancingPolicyName());
EXPECT_EQ(
(GetParam().use_xds_resolver() ? "cds_experimental" : "xds_experimental"),
channel_->GetLoadBalancingPolicyName());
}
TEST_P(BasicTest, IgnoresUnhealthyEndpoints) {
@ -1098,8 +1100,6 @@ TEST_P(BasicTest, IgnoresUnhealthyEndpoints) {
// The ADS service got a single request, and sent a single response.
EXPECT_EQ(1U, balancers_[0]->ads_service()->request_count());
EXPECT_EQ(1U, balancers_[0]->ads_service()->response_count());
// Check LB policy name for the channel.
EXPECT_EQ("xds_experimental", channel_->GetLoadBalancingPolicyName());
}
// Tests that subchannel sharing works when the same backend is listed multiple

@ -913,6 +913,7 @@ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
src/core/ext/filters/client_channel/lb_policy/subchannel_list.h \
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds.h \
src/core/ext/filters/client_channel/lb_policy_factory.h \

Loading…
Cancel
Save