grpc 1.26.0 → 1.27.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.
- checksums.yaml +4 -4
- data/Makefile +1654 -1519
- data/etc/roots.pem +44 -0
- data/include/grpc/grpc_security.h +37 -15
- data/include/grpc/grpc_security_constants.h +27 -0
- data/include/grpc/impl/codegen/grpc_types.h +14 -0
- data/include/grpc/impl/codegen/port_platform.h +1 -1
- data/src/core/ext/filters/client_channel/client_channel.cc +0 -20
- data/src/core/ext/filters/client_channel/http_proxy.cc +4 -4
- data/src/core/ext/filters/client_channel/lb_policy.cc +4 -3
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +191 -201
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +89 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +40 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +3 -2
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +88 -121
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +28 -57
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +0 -7
- data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +8 -9
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +53 -34
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +18 -5
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +24 -19
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +2 -1
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +4 -2
- data/src/core/ext/filters/client_channel/server_address.cc +6 -9
- data/src/core/ext/filters/client_channel/server_address.h +3 -10
- data/src/core/ext/filters/client_channel/xds/xds_api.cc +394 -150
- data/src/core/ext/filters/client_channel/xds/xds_api.h +75 -35
- data/src/core/ext/filters/client_channel/xds/xds_bootstrap.cc +59 -22
- data/src/core/ext/filters/client_channel/xds/xds_bootstrap.h +13 -9
- data/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc +8 -6
- data/src/core/ext/filters/client_channel/xds/xds_client.cc +456 -175
- data/src/core/ext/filters/client_channel/xds/xds_client.h +33 -21
- data/src/core/ext/filters/client_channel/xds/xds_client_stats.cc +5 -8
- data/src/core/ext/filters/client_channel/xds/xds_client_stats.h +18 -24
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +2 -2
- data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c +13 -5
- data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h +34 -0
- data/src/core/lib/channel/channelz.h +11 -1
- data/src/core/lib/gpr/time_precise.cc +1 -1
- data/src/core/lib/gprpp/optional.h +26 -0
- data/src/core/lib/gprpp/string_view.h +14 -10
- data/src/core/lib/iomgr/executor.cc +1 -1
- data/src/core/lib/iomgr/fork_posix.cc +4 -0
- data/src/core/lib/iomgr/poller/eventmanager_libuv.cc +87 -0
- data/src/core/lib/iomgr/poller/eventmanager_libuv.h +88 -0
- data/src/core/lib/iomgr/socket_utils_common_posix.cc +14 -0
- data/src/core/lib/iomgr/socket_utils_posix.h +12 -0
- data/src/core/lib/iomgr/tcp_custom.h +3 -0
- data/src/core/lib/iomgr/tcp_posix.cc +607 -56
- data/src/core/lib/iomgr/tcp_server_custom.cc +15 -2
- data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +8 -0
- data/src/core/lib/json/json.h +11 -1
- data/src/core/lib/json/json_reader.cc +206 -28
- data/src/core/lib/json/json_writer.cc +111 -24
- data/src/core/lib/security/credentials/composite/composite_credentials.cc +7 -0
- data/src/core/lib/security/credentials/composite/composite_credentials.h +5 -1
- data/src/core/lib/security/credentials/credentials.h +10 -1
- data/src/core/lib/security/credentials/fake/fake_credentials.h +2 -1
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
- data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +6 -4
- data/src/core/lib/security/credentials/plugin/plugin_credentials.h +2 -1
- data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +20 -0
- data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +8 -0
- data/src/core/lib/security/credentials/tls/{spiffe_credentials.cc → tls_credentials.cc} +23 -24
- data/src/core/lib/security/credentials/tls/{spiffe_credentials.h → tls_credentials.h} +9 -9
- data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +13 -0
- data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +22 -2
- data/src/core/lib/security/security_connector/load_system_roots_fallback.cc +2 -2
- data/src/core/lib/security/security_connector/load_system_roots_linux.cc +2 -2
- data/src/core/lib/security/security_connector/local/local_security_connector.cc +30 -3
- data/src/core/lib/security/security_connector/ssl_utils.cc +45 -3
- data/src/core/lib/security/security_connector/ssl_utils.h +12 -0
- data/src/core/lib/security/security_connector/tls/{spiffe_security_connector.cc → tls_security_connector.cc} +82 -69
- data/src/core/lib/security/security_connector/tls/{spiffe_security_connector.h → tls_security_connector.h} +17 -18
- data/src/core/lib/security/transport/client_auth_filter.cc +33 -0
- data/src/core/lib/surface/completion_queue.cc +22 -1
- data/src/core/lib/surface/version.cc +1 -1
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +11 -1
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +1 -1
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +3 -3
- data/src/core/tsi/fake_transport_security.cc +7 -3
- data/src/core/tsi/fake_transport_security.h +2 -0
- data/src/core/tsi/ssl_transport_security.cc +144 -8
- data/src/core/tsi/ssl_transport_security.h +15 -1
- data/src/core/tsi/transport_security.cc +13 -0
- data/src/core/tsi/transport_security_grpc.cc +2 -2
- data/src/core/tsi/transport_security_grpc.h +2 -2
- data/src/core/tsi/transport_security_interface.h +12 -0
- data/src/ruby/bin/math_pb.rb +5 -5
- data/src/ruby/ext/grpc/rb_call_credentials.c +4 -1
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/pb/grpc/health/v1/health_pb.rb +3 -3
- data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +1 -1
- data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +23 -13
- data/third_party/abseil-cpp/absl/algorithm/algorithm.h +159 -0
- data/third_party/abseil-cpp/absl/base/attributes.h +609 -0
- data/third_party/abseil-cpp/absl/base/call_once.h +226 -0
- data/third_party/abseil-cpp/absl/base/casts.h +184 -0
- data/third_party/abseil-cpp/absl/base/config.h +622 -0
- data/third_party/abseil-cpp/absl/base/const_init.h +76 -0
- data/third_party/abseil-cpp/absl/base/dynamic_annotations.cc +129 -0
- data/third_party/abseil-cpp/absl/base/dynamic_annotations.h +389 -0
- data/third_party/abseil-cpp/absl/base/internal/atomic_hook.h +179 -0
- data/third_party/abseil-cpp/absl/base/internal/bits.h +218 -0
- data/third_party/abseil-cpp/absl/base/internal/cycleclock.cc +107 -0
- data/third_party/abseil-cpp/absl/base/internal/cycleclock.h +94 -0
- data/third_party/abseil-cpp/absl/base/internal/endian.h +266 -0
- data/third_party/abseil-cpp/absl/base/internal/hide_ptr.h +51 -0
- data/third_party/abseil-cpp/absl/base/internal/identity.h +37 -0
- data/third_party/abseil-cpp/absl/base/internal/inline_variable.h +107 -0
- data/third_party/abseil-cpp/absl/base/internal/invoke.h +187 -0
- data/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h +107 -0
- data/third_party/abseil-cpp/absl/base/internal/per_thread_tls.h +52 -0
- data/third_party/abseil-cpp/absl/base/internal/raw_logging.cc +237 -0
- data/third_party/abseil-cpp/absl/base/internal/raw_logging.h +179 -0
- data/third_party/abseil-cpp/absl/base/internal/scheduling_mode.h +58 -0
- data/third_party/abseil-cpp/absl/base/internal/spinlock.cc +233 -0
- data/third_party/abseil-cpp/absl/base/internal/spinlock.h +243 -0
- data/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc +35 -0
- data/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc +67 -0
- data/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc +46 -0
- data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc +81 -0
- data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h +93 -0
- data/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc +37 -0
- data/third_party/abseil-cpp/absl/base/internal/sysinfo.cc +414 -0
- data/third_party/abseil-cpp/absl/base/internal/sysinfo.h +66 -0
- data/third_party/abseil-cpp/absl/base/internal/thread_annotations.h +271 -0
- data/third_party/abseil-cpp/absl/base/internal/thread_identity.cc +140 -0
- data/third_party/abseil-cpp/absl/base/internal/thread_identity.h +250 -0
- data/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc +108 -0
- data/third_party/abseil-cpp/absl/base/internal/throw_delegate.h +75 -0
- data/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h +66 -0
- data/third_party/abseil-cpp/absl/base/internal/unaligned_access.h +158 -0
- data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc +103 -0
- data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h +124 -0
- data/third_party/abseil-cpp/absl/base/log_severity.cc +27 -0
- data/third_party/abseil-cpp/absl/base/log_severity.h +121 -0
- data/third_party/abseil-cpp/absl/base/macros.h +220 -0
- data/third_party/abseil-cpp/absl/base/optimization.h +181 -0
- data/third_party/abseil-cpp/absl/base/options.h +214 -0
- data/third_party/abseil-cpp/absl/base/policy_checks.h +111 -0
- data/third_party/abseil-cpp/absl/base/port.h +26 -0
- data/third_party/abseil-cpp/absl/base/thread_annotations.h +280 -0
- data/third_party/abseil-cpp/absl/container/inlined_vector.h +848 -0
- data/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h +265 -0
- data/third_party/abseil-cpp/absl/container/internal/inlined_vector.h +892 -0
- data/third_party/abseil-cpp/absl/memory/memory.h +695 -0
- data/third_party/abseil-cpp/absl/meta/type_traits.h +759 -0
- data/third_party/abseil-cpp/absl/numeric/int128.cc +404 -0
- data/third_party/abseil-cpp/absl/numeric/int128.h +1091 -0
- data/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc +302 -0
- data/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc +308 -0
- data/third_party/abseil-cpp/absl/strings/ascii.cc +200 -0
- data/third_party/abseil-cpp/absl/strings/ascii.h +241 -0
- data/third_party/abseil-cpp/absl/strings/charconv.cc +985 -0
- data/third_party/abseil-cpp/absl/strings/charconv.h +119 -0
- data/third_party/abseil-cpp/absl/strings/escaping.cc +949 -0
- data/third_party/abseil-cpp/absl/strings/escaping.h +164 -0
- data/third_party/abseil-cpp/absl/strings/internal/char_map.h +156 -0
- data/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc +359 -0
- data/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h +421 -0
- data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc +504 -0
- data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.h +99 -0
- data/third_party/abseil-cpp/absl/strings/internal/escaping.cc +180 -0
- data/third_party/abseil-cpp/absl/strings/internal/escaping.h +58 -0
- data/third_party/abseil-cpp/absl/strings/internal/memutil.cc +112 -0
- data/third_party/abseil-cpp/absl/strings/internal/memutil.h +148 -0
- data/third_party/abseil-cpp/absl/strings/internal/ostringstream.cc +36 -0
- data/third_party/abseil-cpp/absl/strings/internal/ostringstream.h +89 -0
- data/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h +73 -0
- data/third_party/abseil-cpp/absl/strings/internal/stl_type_traits.h +248 -0
- data/third_party/abseil-cpp/absl/strings/internal/str_join_internal.h +314 -0
- data/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h +455 -0
- data/third_party/abseil-cpp/absl/strings/internal/utf8.cc +53 -0
- data/third_party/abseil-cpp/absl/strings/internal/utf8.h +50 -0
- data/third_party/abseil-cpp/absl/strings/match.cc +40 -0
- data/third_party/abseil-cpp/absl/strings/match.h +90 -0
- data/third_party/abseil-cpp/absl/strings/numbers.cc +916 -0
- data/third_party/abseil-cpp/absl/strings/numbers.h +263 -0
- data/third_party/abseil-cpp/absl/strings/str_cat.cc +246 -0
- data/third_party/abseil-cpp/absl/strings/str_cat.h +408 -0
- data/third_party/abseil-cpp/absl/strings/str_join.h +293 -0
- data/third_party/abseil-cpp/absl/strings/str_replace.cc +82 -0
- data/third_party/abseil-cpp/absl/strings/str_replace.h +219 -0
- data/third_party/abseil-cpp/absl/strings/str_split.cc +139 -0
- data/third_party/abseil-cpp/absl/strings/str_split.h +513 -0
- data/third_party/abseil-cpp/absl/strings/string_view.cc +235 -0
- data/third_party/abseil-cpp/absl/strings/string_view.h +615 -0
- data/third_party/abseil-cpp/absl/strings/strip.h +91 -0
- data/third_party/abseil-cpp/absl/strings/substitute.cc +171 -0
- data/third_party/abseil-cpp/absl/strings/substitute.h +693 -0
- data/third_party/abseil-cpp/absl/types/bad_optional_access.cc +48 -0
- data/third_party/abseil-cpp/absl/types/bad_optional_access.h +78 -0
- data/third_party/abseil-cpp/absl/types/internal/optional.h +396 -0
- data/third_party/abseil-cpp/absl/types/internal/span.h +128 -0
- data/third_party/abseil-cpp/absl/types/optional.h +776 -0
- data/third_party/abseil-cpp/absl/types/span.h +713 -0
- data/third_party/abseil-cpp/absl/utility/utility.h +350 -0
- data/third_party/upb/upb/decode.c +4 -0
- data/third_party/upb/upb/port.c +0 -1
- data/third_party/upb/upb/port_def.inc +1 -3
- data/third_party/upb/upb/table.c +2 -1
- metadata +147 -43
- data/src/core/lib/json/json_common.h +0 -34
- data/src/core/lib/json/json_reader.h +0 -146
- data/src/core/lib/json/json_string.cc +0 -367
- data/src/core/lib/json/json_writer.h +0 -84
@@ -23,14 +23,47 @@
|
|
23
23
|
|
24
24
|
#include <stdint.h>
|
25
25
|
|
26
|
+
#include <set>
|
27
|
+
|
26
28
|
#include <grpc/slice_buffer.h>
|
27
29
|
|
28
30
|
#include "src/core/ext/filters/client_channel/server_address.h"
|
29
31
|
#include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
|
30
32
|
#include "src/core/ext/filters/client_channel/xds/xds_client_stats.h"
|
33
|
+
#include "src/core/lib/gprpp/optional.h"
|
31
34
|
|
32
35
|
namespace grpc_core {
|
33
36
|
|
37
|
+
constexpr char kCdsTypeUrl[] = "type.googleapis.com/envoy.api.v2.Cluster";
|
38
|
+
constexpr char kEdsTypeUrl[] =
|
39
|
+
"type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
|
40
|
+
|
41
|
+
// The version state for each specific ADS resource type.
|
42
|
+
struct VersionState {
|
43
|
+
// The version of the latest response that is accepted and used.
|
44
|
+
std::string version_info;
|
45
|
+
// The nonce of the latest response.
|
46
|
+
std::string nonce;
|
47
|
+
// The error message to be included in a NACK with the nonce. Consumed when a
|
48
|
+
// nonce is NACK'ed for the first time.
|
49
|
+
grpc_error* error = GRPC_ERROR_NONE;
|
50
|
+
|
51
|
+
~VersionState() { GRPC_ERROR_UNREF(error); }
|
52
|
+
};
|
53
|
+
|
54
|
+
struct CdsUpdate {
|
55
|
+
// The name to use in the EDS request.
|
56
|
+
// If empty, the cluster name will be used.
|
57
|
+
std::string eds_service_name;
|
58
|
+
// The LRS server to use for load reporting.
|
59
|
+
// If not set, load reporting will be disabled.
|
60
|
+
// If set to the empty string, will use the same server we obtained the CDS
|
61
|
+
// data from.
|
62
|
+
Optional<std::string> lrs_load_reporting_server_name;
|
63
|
+
};
|
64
|
+
|
65
|
+
using CdsUpdateMap = std::map<std::string /*cluster_name*/, CdsUpdate>;
|
66
|
+
|
34
67
|
class XdsPriorityListUpdate {
|
35
68
|
public:
|
36
69
|
struct LocalityMap {
|
@@ -97,24 +130,22 @@ class XdsDropConfig : public RefCounted<XdsDropConfig> {
|
|
97
130
|
public:
|
98
131
|
struct DropCategory {
|
99
132
|
bool operator==(const DropCategory& other) const {
|
100
|
-
return
|
101
|
-
parts_per_million == other.parts_per_million;
|
133
|
+
return name == other.name && parts_per_million == other.parts_per_million;
|
102
134
|
}
|
103
135
|
|
104
|
-
|
136
|
+
std::string name;
|
105
137
|
const uint32_t parts_per_million;
|
106
138
|
};
|
107
139
|
|
108
140
|
using DropCategoryList = InlinedVector<DropCategory, 2>;
|
109
141
|
|
110
|
-
void AddCategory(
|
111
|
-
uint32_t parts_per_million) {
|
142
|
+
void AddCategory(std::string name, uint32_t parts_per_million) {
|
112
143
|
drop_category_list_.emplace_back(
|
113
144
|
DropCategory{std::move(name), parts_per_million});
|
114
145
|
}
|
115
146
|
|
116
147
|
// The only method invoked from the data plane combiner.
|
117
|
-
bool ShouldDrop(const
|
148
|
+
bool ShouldDrop(const std::string** category_name) const;
|
118
149
|
|
119
150
|
const DropCategoryList& drop_category_list() const {
|
120
151
|
return drop_category_list_;
|
@@ -137,44 +168,53 @@ struct EdsUpdate {
|
|
137
168
|
bool drop_all = false;
|
138
169
|
};
|
139
170
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
171
|
+
using EdsUpdateMap = std::map<std::string /*eds_service_name*/, EdsUpdate>;
|
172
|
+
|
173
|
+
// Creates a request to nack an unsupported resource type.
|
174
|
+
// Takes ownership of \a error.
|
175
|
+
grpc_slice XdsUnsupportedTypeNackRequestCreateAndEncode(
|
176
|
+
const std::string& type_url, const std::string& nonce, grpc_error* error);
|
177
|
+
|
178
|
+
// Creates a CDS request querying \a cluster_names.
|
179
|
+
// Takes ownership of \a error.
|
180
|
+
grpc_slice XdsCdsRequestCreateAndEncode(
|
181
|
+
const std::set<StringView>& cluster_names, const XdsBootstrap::Node* node,
|
182
|
+
const char* build_version, const std::string& version,
|
183
|
+
const std::string& nonce, grpc_error* error);
|
184
|
+
|
185
|
+
// Creates an EDS request querying \a eds_service_names.
|
186
|
+
// Takes ownership of \a error.
|
187
|
+
grpc_slice XdsEdsRequestCreateAndEncode(
|
188
|
+
const std::set<StringView>& eds_service_names,
|
189
|
+
const XdsBootstrap::Node* node, const char* build_version,
|
190
|
+
const std::string& version, const std::string& nonce, grpc_error* error);
|
191
|
+
|
192
|
+
// Parses the ADS response and outputs the validated update for either CDS or
|
193
|
+
// EDS. If the response can't be parsed at the top level, \a type_url will point
|
194
|
+
// to an empty string; otherwise, it will point to the received data.
|
195
|
+
grpc_error* XdsAdsResponseDecodeAndParse(
|
196
|
+
const grpc_slice& encoded_response,
|
197
|
+
const std::set<StringView>& expected_eds_service_names,
|
198
|
+
CdsUpdateMap* cds_update_map, EdsUpdateMap* eds_update_map,
|
199
|
+
std::string* version, std::string* nonce, std::string* type_url);
|
160
200
|
|
161
201
|
// Creates an LRS request querying \a server_name.
|
162
|
-
grpc_slice XdsLrsRequestCreateAndEncode(const
|
202
|
+
grpc_slice XdsLrsRequestCreateAndEncode(const std::string& server_name,
|
163
203
|
const XdsBootstrap::Node* node,
|
164
204
|
const char* build_version);
|
165
205
|
|
166
206
|
// Creates an LRS request sending client-side load reports. If all the counters
|
167
|
-
//
|
168
|
-
grpc_slice XdsLrsRequestCreateAndEncode(
|
169
|
-
|
207
|
+
// are zero, returns empty slice.
|
208
|
+
grpc_slice XdsLrsRequestCreateAndEncode(
|
209
|
+
std::map<StringView /*cluster_name*/, std::set<XdsClientStats*>>
|
210
|
+
client_stats_map);
|
170
211
|
|
171
|
-
// Parses the LRS response and returns \a
|
212
|
+
// Parses the LRS response and returns \a
|
172
213
|
// load_reporting_interval for client-side load reporting. If there is any
|
173
214
|
// error, the output config is invalid.
|
174
|
-
grpc_error* XdsLrsResponseDecodeAndParse(
|
175
|
-
|
176
|
-
|
177
|
-
grpc_millis* load_reporting_interval);
|
215
|
+
grpc_error* XdsLrsResponseDecodeAndParse(const grpc_slice& encoded_response,
|
216
|
+
std::set<std::string>* cluster_names,
|
217
|
+
grpc_millis* load_reporting_interval);
|
178
218
|
|
179
219
|
} // namespace grpc_core
|
180
220
|
|
@@ -58,23 +58,23 @@ XdsBootstrap::XdsBootstrap(grpc_slice contents, grpc_error** error)
|
|
58
58
|
return;
|
59
59
|
}
|
60
60
|
InlinedVector<grpc_error*, 1> error_list;
|
61
|
-
bool
|
61
|
+
bool seen_xds_servers = false;
|
62
62
|
bool seen_node = false;
|
63
63
|
for (grpc_json* child = tree_->child; child != nullptr; child = child->next) {
|
64
64
|
if (child->key == nullptr) {
|
65
65
|
error_list.push_back(
|
66
66
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null"));
|
67
|
-
} else if (strcmp(child->key, "
|
68
|
-
if (child->type !=
|
67
|
+
} else if (strcmp(child->key, "xds_servers") == 0) {
|
68
|
+
if (child->type != GRPC_JSON_ARRAY) {
|
69
69
|
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
70
|
-
"\"
|
70
|
+
"\"xds_servers\" field is not an array"));
|
71
71
|
}
|
72
|
-
if (
|
72
|
+
if (seen_xds_servers) {
|
73
73
|
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
74
|
-
"duplicate \"
|
74
|
+
"duplicate \"xds_servers\" field"));
|
75
75
|
}
|
76
|
-
|
77
|
-
grpc_error* parse_error =
|
76
|
+
seen_xds_servers = true;
|
77
|
+
grpc_error* parse_error = ParseXdsServerList(child);
|
78
78
|
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
|
79
79
|
} else if (strcmp(child->key, "node") == 0) {
|
80
80
|
if (child->type != GRPC_JSON_OBJECT) {
|
@@ -90,9 +90,9 @@ XdsBootstrap::XdsBootstrap(grpc_slice contents, grpc_error** error)
|
|
90
90
|
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
|
91
91
|
}
|
92
92
|
}
|
93
|
-
if (!
|
93
|
+
if (!seen_xds_servers) {
|
94
94
|
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
95
|
-
"\"
|
95
|
+
"\"xds_servers\" field not present"));
|
96
96
|
}
|
97
97
|
*error = GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing xds bootstrap file",
|
98
98
|
&error_list);
|
@@ -103,9 +103,33 @@ XdsBootstrap::~XdsBootstrap() {
|
|
103
103
|
grpc_slice_unref_internal(contents_);
|
104
104
|
}
|
105
105
|
|
106
|
-
grpc_error* XdsBootstrap::
|
106
|
+
grpc_error* XdsBootstrap::ParseXdsServerList(grpc_json* json) {
|
107
107
|
InlinedVector<grpc_error*, 1> error_list;
|
108
|
-
|
108
|
+
size_t idx = 0;
|
109
|
+
for (grpc_json *child = json->child; child != nullptr;
|
110
|
+
child = child->next, ++idx) {
|
111
|
+
if (child->key != nullptr) {
|
112
|
+
char* msg;
|
113
|
+
gpr_asprintf(&msg, "array element %" PRIuPTR " key is not null", idx);
|
114
|
+
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
|
115
|
+
}
|
116
|
+
if (child->type != GRPC_JSON_OBJECT) {
|
117
|
+
char* msg;
|
118
|
+
gpr_asprintf(&msg, "array element %" PRIuPTR " is not an object", idx);
|
119
|
+
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
|
120
|
+
} else {
|
121
|
+
grpc_error* parse_error = ParseXdsServer(child, idx);
|
122
|
+
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"xds_servers\" array",
|
126
|
+
&error_list);
|
127
|
+
}
|
128
|
+
|
129
|
+
grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json, size_t idx) {
|
130
|
+
InlinedVector<grpc_error*, 1> error_list;
|
131
|
+
servers_.emplace_back();
|
132
|
+
XdsServer& server = servers_[servers_.size() - 1];
|
109
133
|
bool seen_channel_creds = false;
|
110
134
|
for (grpc_json* child = json->child; child != nullptr; child = child->next) {
|
111
135
|
if (child->key == nullptr) {
|
@@ -116,11 +140,11 @@ grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json) {
|
|
116
140
|
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
117
141
|
"\"server_uri\" field is not a string"));
|
118
142
|
}
|
119
|
-
if (
|
143
|
+
if (server.server_uri != nullptr) {
|
120
144
|
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
121
145
|
"duplicate \"server_uri\" field"));
|
122
146
|
}
|
123
|
-
|
147
|
+
server.server_uri = child->value;
|
124
148
|
} else if (strcmp(child->key, "channel_creds") == 0) {
|
125
149
|
if (child->type != GRPC_JSON_ARRAY) {
|
126
150
|
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
@@ -131,19 +155,29 @@ grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json) {
|
|
131
155
|
"duplicate \"channel_creds\" field"));
|
132
156
|
}
|
133
157
|
seen_channel_creds = true;
|
134
|
-
grpc_error* parse_error = ParseChannelCredsArray(child);
|
158
|
+
grpc_error* parse_error = ParseChannelCredsArray(child, &server);
|
135
159
|
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
|
136
160
|
}
|
137
161
|
}
|
138
|
-
if (
|
162
|
+
if (server.server_uri == nullptr) {
|
139
163
|
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
140
164
|
"\"server_uri\" field not present"));
|
141
165
|
}
|
142
|
-
|
143
|
-
|
166
|
+
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
|
167
|
+
// string is not static in this case.
|
168
|
+
if (error_list.empty()) return GRPC_ERROR_NONE;
|
169
|
+
char* msg;
|
170
|
+
gpr_asprintf(&msg, "errors parsing index %" PRIuPTR, idx);
|
171
|
+
grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
|
172
|
+
gpr_free(msg);
|
173
|
+
for (size_t i = 0; i < error_list.size(); ++i) {
|
174
|
+
error = grpc_error_add_child(error, error_list[i]);
|
175
|
+
}
|
176
|
+
return error;
|
144
177
|
}
|
145
178
|
|
146
|
-
grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json
|
179
|
+
grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json,
|
180
|
+
XdsServer* server) {
|
147
181
|
InlinedVector<grpc_error*, 1> error_list;
|
148
182
|
size_t idx = 0;
|
149
183
|
for (grpc_json *child = json->child; child != nullptr;
|
@@ -158,7 +192,7 @@ grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json) {
|
|
158
192
|
gpr_asprintf(&msg, "array element %" PRIuPTR " is not an object", idx);
|
159
193
|
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
|
160
194
|
} else {
|
161
|
-
grpc_error* parse_error = ParseChannelCreds(child, idx);
|
195
|
+
grpc_error* parse_error = ParseChannelCreds(child, idx, server);
|
162
196
|
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
|
163
197
|
}
|
164
198
|
}
|
@@ -166,7 +200,8 @@ grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json) {
|
|
166
200
|
&error_list);
|
167
201
|
}
|
168
202
|
|
169
|
-
grpc_error* XdsBootstrap::ParseChannelCreds(grpc_json* json, size_t idx
|
203
|
+
grpc_error* XdsBootstrap::ParseChannelCreds(grpc_json* json, size_t idx,
|
204
|
+
XdsServer* server) {
|
170
205
|
InlinedVector<grpc_error*, 1> error_list;
|
171
206
|
ChannelCreds channel_creds;
|
172
207
|
for (grpc_json* child = json->child; child != nullptr; child = child->next) {
|
@@ -195,7 +230,9 @@ grpc_error* XdsBootstrap::ParseChannelCreds(grpc_json* json, size_t idx) {
|
|
195
230
|
channel_creds.config = child;
|
196
231
|
}
|
197
232
|
}
|
198
|
-
if (channel_creds.type != nullptr)
|
233
|
+
if (channel_creds.type != nullptr) {
|
234
|
+
server->channel_creds.push_back(channel_creds);
|
235
|
+
}
|
199
236
|
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
|
200
237
|
// string is not static in this case.
|
201
238
|
if (error_list.empty()) return GRPC_ERROR_NONE;
|
@@ -58,6 +58,11 @@ class XdsBootstrap {
|
|
58
58
|
grpc_json* config = nullptr;
|
59
59
|
};
|
60
60
|
|
61
|
+
struct XdsServer {
|
62
|
+
const char* server_uri = nullptr;
|
63
|
+
InlinedVector<ChannelCreds, 1> channel_creds;
|
64
|
+
};
|
65
|
+
|
61
66
|
// If *error is not GRPC_ERROR_NONE after returning, then there was an
|
62
67
|
// error reading the file.
|
63
68
|
static std::unique_ptr<XdsBootstrap> ReadFromFile(grpc_error** error);
|
@@ -66,16 +71,16 @@ class XdsBootstrap {
|
|
66
71
|
XdsBootstrap(grpc_slice contents, grpc_error** error);
|
67
72
|
~XdsBootstrap();
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
}
|
74
|
+
// TODO(roth): We currently support only one server. Fix this when we
|
75
|
+
// add support for fallback for the xds channel.
|
76
|
+
const XdsServer& server() const { return servers_[0]; }
|
73
77
|
const Node* node() const { return node_.get(); }
|
74
78
|
|
75
79
|
private:
|
76
|
-
grpc_error*
|
77
|
-
grpc_error*
|
78
|
-
grpc_error*
|
80
|
+
grpc_error* ParseXdsServerList(grpc_json* json);
|
81
|
+
grpc_error* ParseXdsServer(grpc_json* json, size_t idx);
|
82
|
+
grpc_error* ParseChannelCredsArray(grpc_json* json, XdsServer* server);
|
83
|
+
grpc_error* ParseChannelCreds(grpc_json* json, size_t idx, XdsServer* server);
|
79
84
|
grpc_error* ParseNode(grpc_json* json);
|
80
85
|
grpc_error* ParseLocality(grpc_json* json);
|
81
86
|
|
@@ -90,8 +95,7 @@ class XdsBootstrap {
|
|
90
95
|
grpc_slice contents_;
|
91
96
|
grpc_json* tree_ = nullptr;
|
92
97
|
|
93
|
-
|
94
|
-
InlinedVector<ChannelCreds, 1> channel_creds_;
|
98
|
+
InlinedVector<XdsServer, 1> servers_;
|
95
99
|
std::unique_ptr<Node> node_;
|
96
100
|
};
|
97
101
|
|
@@ -67,12 +67,14 @@ grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
|
|
67
67
|
const grpc_channel_args& args) {
|
68
68
|
grpc_channel_credentials* creds = nullptr;
|
69
69
|
RefCountedPtr<grpc_channel_credentials> creds_to_unref;
|
70
|
-
if (!bootstrap.
|
71
|
-
for (size_t i = 0; i < bootstrap.
|
72
|
-
if (strcmp(bootstrap.
|
70
|
+
if (!bootstrap.server().channel_creds.empty()) {
|
71
|
+
for (size_t i = 0; i < bootstrap.server().channel_creds.size(); ++i) {
|
72
|
+
if (strcmp(bootstrap.server().channel_creds[i].type, "google_default") ==
|
73
|
+
0) {
|
73
74
|
creds = grpc_google_default_credentials_create();
|
74
75
|
break;
|
75
|
-
} else if (strcmp(bootstrap.
|
76
|
+
} else if (strcmp(bootstrap.server().channel_creds[i].type, "fake") ==
|
77
|
+
0) {
|
76
78
|
creds = grpc_fake_transport_security_credentials_create();
|
77
79
|
break;
|
78
80
|
}
|
@@ -83,7 +85,7 @@ grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
|
|
83
85
|
creds = grpc_channel_credentials_find_in_args(&args);
|
84
86
|
if (creds == nullptr) {
|
85
87
|
// Built with security but parent channel is insecure.
|
86
|
-
return grpc_insecure_channel_create(bootstrap.
|
88
|
+
return grpc_insecure_channel_create(bootstrap.server().server_uri, &args,
|
87
89
|
nullptr);
|
88
90
|
}
|
89
91
|
}
|
@@ -91,7 +93,7 @@ grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
|
|
91
93
|
grpc_channel_args* new_args =
|
92
94
|
grpc_channel_args_copy_and_remove(&args, &arg_to_remove, 1);
|
93
95
|
grpc_channel* channel = grpc_secure_channel_create(
|
94
|
-
creds, bootstrap.
|
96
|
+
creds, bootstrap.server().server_uri, new_args, nullptr);
|
95
97
|
grpc_channel_args_destroy(new_args);
|
96
98
|
return channel;
|
97
99
|
}
|
@@ -125,10 +125,35 @@ class XdsClient::ChannelState::AdsCallState
|
|
125
125
|
XdsClient* xds_client() const { return chand()->xds_client(); }
|
126
126
|
bool seen_response() const { return seen_response_; }
|
127
127
|
|
128
|
+
// If \a type_url is an unsupported type, \a nonce_for_unsupported_type and
|
129
|
+
// \a error_for_unsupported_type will be used in the request; otherwise, the
|
130
|
+
// nonce and error stored in each ADS call state will be used. Takes ownership
|
131
|
+
// of \a error_for_unsupported_type.
|
132
|
+
void SendMessageLocked(const std::string& type_url,
|
133
|
+
const std::string& nonce_for_unsupported_type,
|
134
|
+
grpc_error* error_for_unsupported_type,
|
135
|
+
bool is_first_message);
|
136
|
+
|
128
137
|
private:
|
138
|
+
struct BufferedRequest {
|
139
|
+
std::string nonce;
|
140
|
+
grpc_error* error;
|
141
|
+
|
142
|
+
// Takes ownership of \a error.
|
143
|
+
BufferedRequest(std::string nonce, grpc_error* error)
|
144
|
+
: nonce(std::move(nonce)), error(error) {}
|
145
|
+
|
146
|
+
~BufferedRequest() { GRPC_ERROR_UNREF(error); }
|
147
|
+
};
|
148
|
+
|
149
|
+
void AcceptCdsUpdate(CdsUpdateMap cds_update_map, std::string new_version);
|
150
|
+
void AcceptEdsUpdate(EdsUpdateMap eds_update_map, std::string new_version);
|
151
|
+
|
152
|
+
static void OnRequestSent(void* arg, grpc_error* error);
|
153
|
+
static void OnRequestSentLocked(void* arg, grpc_error* error);
|
129
154
|
static void OnResponseReceived(void* arg, grpc_error* error);
|
130
|
-
static void OnStatusReceived(void* arg, grpc_error* error);
|
131
155
|
static void OnResponseReceivedLocked(void* arg, grpc_error* error);
|
156
|
+
static void OnStatusReceived(void* arg, grpc_error* error);
|
132
157
|
static void OnStatusReceivedLocked(void* arg, grpc_error* error);
|
133
158
|
|
134
159
|
bool IsCurrentCallOnChannel() const;
|
@@ -145,6 +170,7 @@ class XdsClient::ChannelState::AdsCallState
|
|
145
170
|
|
146
171
|
// send_message
|
147
172
|
grpc_byte_buffer* send_message_payload_ = nullptr;
|
173
|
+
grpc_closure on_request_sent_;
|
148
174
|
|
149
175
|
// recv_message
|
150
176
|
grpc_byte_buffer* recv_message_payload_ = nullptr;
|
@@ -155,6 +181,14 @@ class XdsClient::ChannelState::AdsCallState
|
|
155
181
|
grpc_status_code status_code_;
|
156
182
|
grpc_slice status_details_;
|
157
183
|
grpc_closure on_status_received_;
|
184
|
+
|
185
|
+
// Version state.
|
186
|
+
VersionState cds_version_;
|
187
|
+
VersionState eds_version_;
|
188
|
+
|
189
|
+
// Buffered requests.
|
190
|
+
std::map<std::string /*type_url*/, std::unique_ptr<BufferedRequest>>
|
191
|
+
buffered_request_map_;
|
158
192
|
};
|
159
193
|
|
160
194
|
// Contains an LRS call to the xds server.
|
@@ -168,6 +202,7 @@ class XdsClient::ChannelState::LrsCallState
|
|
168
202
|
void Orphan() override;
|
169
203
|
|
170
204
|
void MaybeStartReportingLocked();
|
205
|
+
bool ShouldSendLoadReports(const StringView& cluster_name) const;
|
171
206
|
|
172
207
|
RetryableCall<LrsCallState>* parent() { return parent_.get(); }
|
173
208
|
ChannelState* chand() const { return parent_->chand(); }
|
@@ -244,7 +279,7 @@ class XdsClient::ChannelState::LrsCallState
|
|
244
279
|
grpc_closure on_status_received_;
|
245
280
|
|
246
281
|
// Load reporting state.
|
247
|
-
|
282
|
+
std::set<std::string> cluster_names_; // Asked for by the LRS server.
|
248
283
|
grpc_millis load_reporting_interval_ = 0;
|
249
284
|
OrphanablePtr<Reporter> reporter_;
|
250
285
|
};
|
@@ -376,14 +411,6 @@ bool XdsClient::ChannelState::HasActiveAdsCall() const {
|
|
376
411
|
return ads_calld_->calld() != nullptr;
|
377
412
|
}
|
378
413
|
|
379
|
-
void XdsClient::ChannelState::MaybeStartAdsCall() {
|
380
|
-
if (ads_calld_ != nullptr) return;
|
381
|
-
ads_calld_.reset(
|
382
|
-
new RetryableCall<AdsCallState>(Ref(DEBUG_LOCATION, "ChannelState+ads")));
|
383
|
-
}
|
384
|
-
|
385
|
-
void XdsClient::ChannelState::StopAdsCall() { ads_calld_.reset(); }
|
386
|
-
|
387
414
|
void XdsClient::ChannelState::MaybeStartLrsCall() {
|
388
415
|
if (lrs_calld_ != nullptr) return;
|
389
416
|
lrs_calld_.reset(
|
@@ -409,6 +436,33 @@ void XdsClient::ChannelState::CancelConnectivityWatchLocked() {
|
|
409
436
|
grpc_client_channel_stop_connectivity_watch(client_channel_elem, watcher_);
|
410
437
|
}
|
411
438
|
|
439
|
+
void XdsClient::ChannelState::OnResourceNamesChanged(
|
440
|
+
const std::string& type_url) {
|
441
|
+
if (ads_calld_ == nullptr) {
|
442
|
+
// Start the ADS call if this is the first request.
|
443
|
+
ads_calld_.reset(new RetryableCall<AdsCallState>(
|
444
|
+
Ref(DEBUG_LOCATION, "ChannelState+ads")));
|
445
|
+
// Note: AdsCallState's ctor will automatically send necessary messages, so
|
446
|
+
// we can return here.
|
447
|
+
return;
|
448
|
+
}
|
449
|
+
// If the ADS call is in backoff state, we don't need to do anything now
|
450
|
+
// because when the call is restarted it will resend all necessary requests.
|
451
|
+
if (ads_calld() == nullptr) return;
|
452
|
+
// Send the message if the ADS call is active.
|
453
|
+
ads_calld()->SendMessageLocked(type_url, "", nullptr, false);
|
454
|
+
}
|
455
|
+
|
456
|
+
void XdsClient::ChannelState::OnWatcherRemoved() {
|
457
|
+
// Keep the ADS call if there are watcher(s).
|
458
|
+
for (const auto& p : xds_client()->cluster_map_) {
|
459
|
+
const ClusterState& cluster_state = p.second;
|
460
|
+
if (!cluster_state.watchers.empty()) return;
|
461
|
+
}
|
462
|
+
if (!xds_client()->endpoint_map_.empty()) return;
|
463
|
+
ads_calld_.reset();
|
464
|
+
}
|
465
|
+
|
412
466
|
//
|
413
467
|
// XdsClient::ChannelState::RetryableCall<>
|
414
468
|
//
|
@@ -522,8 +576,7 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
|
|
522
576
|
// activity in xds_client()->interested_parties_, which is comprised of
|
523
577
|
// the polling entities from client_channel.
|
524
578
|
GPR_ASSERT(xds_client() != nullptr);
|
525
|
-
GPR_ASSERT(xds_client()->server_name_
|
526
|
-
GPR_ASSERT(*xds_client()->server_name_.get() != '\0');
|
579
|
+
GPR_ASSERT(!xds_client()->server_name_.empty());
|
527
580
|
// Create a call with the specified method name.
|
528
581
|
call_ = grpc_channel_create_pollset_set_call(
|
529
582
|
chand()->channel_, nullptr, GRPC_PROPAGATE_DEFAULTS,
|
@@ -531,14 +584,7 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
|
|
531
584
|
GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V2_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES,
|
532
585
|
nullptr, GRPC_MILLIS_INF_FUTURE, nullptr);
|
533
586
|
GPR_ASSERT(call_ != nullptr);
|
534
|
-
// Init the
|
535
|
-
grpc_slice request_payload_slice = XdsEdsRequestCreateAndEncode(
|
536
|
-
xds_client()->server_name_.get(), xds_client()->bootstrap_->node(),
|
537
|
-
xds_client()->build_version_.get());
|
538
|
-
send_message_payload_ =
|
539
|
-
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
|
540
|
-
grpc_slice_unref_internal(request_payload_slice);
|
541
|
-
// Init other data associated with the call.
|
587
|
+
// Init data associated with the call.
|
542
588
|
grpc_metadata_array_init(&initial_metadata_recv_);
|
543
589
|
grpc_metadata_array_init(&trailing_metadata_recv_);
|
544
590
|
// Start the call.
|
@@ -559,16 +605,20 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
|
|
559
605
|
op->flags = 0;
|
560
606
|
op->reserved = nullptr;
|
561
607
|
op++;
|
562
|
-
// Op: send request message.
|
563
|
-
GPR_ASSERT(send_message_payload_ != nullptr);
|
564
|
-
op->op = GRPC_OP_SEND_MESSAGE;
|
565
|
-
op->data.send_message.send_message = send_message_payload_;
|
566
|
-
op->flags = 0;
|
567
|
-
op->reserved = nullptr;
|
568
|
-
op++;
|
569
608
|
call_error = grpc_call_start_batch_and_execute(call_, ops, (size_t)(op - ops),
|
570
609
|
nullptr);
|
571
610
|
GPR_ASSERT(GRPC_CALL_OK == call_error);
|
611
|
+
// Op: send request message.
|
612
|
+
GRPC_CLOSURE_INIT(&on_request_sent_, OnRequestSent, this,
|
613
|
+
grpc_schedule_on_exec_ctx);
|
614
|
+
bool initial_message = true;
|
615
|
+
if (!xds_client()->cluster_map_.empty()) {
|
616
|
+
SendMessageLocked(kCdsTypeUrl, "", nullptr, initial_message);
|
617
|
+
initial_message = false;
|
618
|
+
}
|
619
|
+
if (!xds_client()->endpoint_map_.empty()) {
|
620
|
+
SendMessageLocked(kEdsTypeUrl, "", nullptr, initial_message);
|
621
|
+
}
|
572
622
|
// Op: recv initial metadata.
|
573
623
|
op = ops;
|
574
624
|
op->op = GRPC_OP_RECV_INITIAL_METADATA;
|
@@ -629,86 +679,126 @@ void XdsClient::ChannelState::AdsCallState::Orphan() {
|
|
629
679
|
// corresponding unref happens in on_status_received_ instead of here.
|
630
680
|
}
|
631
681
|
|
632
|
-
void XdsClient::ChannelState::AdsCallState::
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
}
|
640
|
-
|
641
|
-
void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked(
|
642
|
-
void* arg, grpc_error* /*error*/) {
|
643
|
-
AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
|
644
|
-
XdsClient* xds_client = ads_calld->xds_client();
|
645
|
-
// Empty payload means the call was cancelled.
|
646
|
-
if (!ads_calld->IsCurrentCallOnChannel() ||
|
647
|
-
ads_calld->recv_message_payload_ == nullptr) {
|
648
|
-
ads_calld->Unref(DEBUG_LOCATION, "ADS+OnResponseReceivedLocked");
|
682
|
+
void XdsClient::ChannelState::AdsCallState::SendMessageLocked(
|
683
|
+
const std::string& type_url, const std::string& nonce_for_unsupported_type,
|
684
|
+
grpc_error* error_for_unsupported_type, bool is_first_message) {
|
685
|
+
// Buffer message sending if an existing message is in flight.
|
686
|
+
if (send_message_payload_ != nullptr) {
|
687
|
+
buffered_request_map_[type_url].reset(new BufferedRequest(
|
688
|
+
nonce_for_unsupported_type, error_for_unsupported_type));
|
649
689
|
return;
|
650
690
|
}
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
691
|
+
grpc_slice request_payload_slice;
|
692
|
+
const XdsBootstrap::Node* node =
|
693
|
+
is_first_message ? xds_client()->bootstrap_->node() : nullptr;
|
694
|
+
const char* build_version =
|
695
|
+
is_first_message ? xds_client()->build_version_.get() : nullptr;
|
696
|
+
if (type_url == kCdsTypeUrl) {
|
697
|
+
request_payload_slice = XdsCdsRequestCreateAndEncode(
|
698
|
+
xds_client()->WatchedClusterNames(), node, build_version,
|
699
|
+
cds_version_.version_info, cds_version_.nonce, cds_version_.error);
|
700
|
+
cds_version_.error = GRPC_ERROR_NONE;
|
701
|
+
GRPC_ERROR_UNREF(error_for_unsupported_type);
|
702
|
+
} else if (type_url == kEdsTypeUrl) {
|
703
|
+
request_payload_slice = XdsEdsRequestCreateAndEncode(
|
704
|
+
xds_client()->EdsServiceNames(), node, build_version,
|
705
|
+
eds_version_.version_info, eds_version_.nonce, eds_version_.error);
|
706
|
+
eds_version_.error = GRPC_ERROR_NONE;
|
707
|
+
GRPC_ERROR_UNREF(error_for_unsupported_type);
|
708
|
+
} else {
|
709
|
+
request_payload_slice = XdsUnsupportedTypeNackRequestCreateAndEncode(
|
710
|
+
type_url, nonce_for_unsupported_type, error_for_unsupported_type);
|
711
|
+
}
|
712
|
+
// Create message payload.
|
713
|
+
send_message_payload_ =
|
714
|
+
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
|
715
|
+
grpc_slice_unref_internal(request_payload_slice);
|
716
|
+
// Send the message.
|
717
|
+
grpc_op op;
|
718
|
+
memset(&op, 0, sizeof(op));
|
719
|
+
op.op = GRPC_OP_SEND_MESSAGE;
|
720
|
+
op.data.send_message.send_message = send_message_payload_;
|
721
|
+
Ref(DEBUG_LOCATION, "ADS+OnRequestSentLocked").release();
|
722
|
+
GRPC_CLOSURE_INIT(&on_request_sent_, OnRequestSent, this,
|
723
|
+
grpc_schedule_on_exec_ctx);
|
724
|
+
grpc_call_error call_error =
|
725
|
+
grpc_call_start_batch_and_execute(call_, &op, 1, &on_request_sent_);
|
726
|
+
if (GPR_UNLIKELY(call_error != GRPC_CALL_OK)) {
|
727
|
+
gpr_log(GPR_ERROR,
|
728
|
+
"[xds_client %p] calld=%p call_error=%d sending ADS message",
|
729
|
+
xds_client(), this, call_error);
|
730
|
+
GPR_ASSERT(GRPC_CALL_OK == call_error);
|
731
|
+
}
|
732
|
+
}
|
733
|
+
|
734
|
+
void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
|
735
|
+
CdsUpdateMap cds_update_map, std::string new_version) {
|
736
|
+
for (auto& p : cds_update_map) {
|
737
|
+
const char* cluster_name = p.first.c_str();
|
738
|
+
CdsUpdate& cds_update = p.second;
|
739
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
|
740
|
+
gpr_log(GPR_INFO,
|
741
|
+
"[xds_client %p] CDS update (cluster=%s) received: "
|
742
|
+
"eds_service_name=%s, "
|
743
|
+
"lrs_load_reporting_server_name=%s",
|
744
|
+
xds_client(), cluster_name, cds_update.eds_service_name.c_str(),
|
745
|
+
cds_update.lrs_load_reporting_server_name.has_value()
|
746
|
+
? cds_update.lrs_load_reporting_server_name.value().c_str()
|
747
|
+
: "(N/A)");
|
678
748
|
}
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
749
|
+
ClusterState& cluster_state = xds_client()->cluster_map_[cluster_name];
|
750
|
+
// Ignore identical update.
|
751
|
+
if (cluster_state.update.has_value() &&
|
752
|
+
cds_update.eds_service_name ==
|
753
|
+
cluster_state.update.value().eds_service_name &&
|
754
|
+
cds_update.lrs_load_reporting_server_name.value() ==
|
755
|
+
cluster_state.update.value()
|
756
|
+
.lrs_load_reporting_server_name.value()) {
|
757
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
|
758
|
+
gpr_log(GPR_INFO,
|
759
|
+
"[xds_client %p] CDS update identical to current, ignoring.",
|
760
|
+
xds_client());
|
761
|
+
}
|
762
|
+
continue;
|
763
|
+
}
|
764
|
+
// Update the cluster state.
|
765
|
+
cluster_state.update.set(std::move(cds_update));
|
766
|
+
// Notify all watchers.
|
767
|
+
for (const auto& p : cluster_state.watchers) {
|
768
|
+
p.first->OnClusterChanged(cluster_state.update.value());
|
688
769
|
}
|
689
|
-
|
770
|
+
}
|
771
|
+
cds_version_.version_info = std::move(new_version);
|
772
|
+
}
|
773
|
+
|
774
|
+
void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate(
|
775
|
+
EdsUpdateMap eds_update_map, std::string new_version) {
|
776
|
+
for (auto& p : eds_update_map) {
|
777
|
+
const char* eds_service_name = p.first.c_str();
|
778
|
+
EdsUpdate& eds_update = p.second;
|
690
779
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
|
691
780
|
gpr_log(GPR_INFO,
|
692
|
-
"[xds_client %p]
|
781
|
+
"[xds_client %p] EDS response with %" PRIuPTR
|
693
782
|
" priorities and %" PRIuPTR
|
694
783
|
" drop categories received (drop_all=%d)",
|
695
|
-
xds_client,
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
784
|
+
xds_client(), eds_update.priority_list_update.size(),
|
785
|
+
eds_update.drop_config->drop_category_list().size(),
|
786
|
+
eds_update.drop_all);
|
787
|
+
for (size_t priority = 0;
|
788
|
+
priority < eds_update.priority_list_update.size(); ++priority) {
|
789
|
+
const auto* locality_map_update = eds_update.priority_list_update.Find(
|
790
|
+
static_cast<uint32_t>(priority));
|
701
791
|
gpr_log(GPR_INFO,
|
702
792
|
"[xds_client %p] Priority %" PRIuPTR " contains %" PRIuPTR
|
703
793
|
" localities",
|
704
|
-
xds_client, priority, locality_map_update->size());
|
794
|
+
xds_client(), priority, locality_map_update->size());
|
705
795
|
size_t locality_count = 0;
|
706
796
|
for (const auto& p : locality_map_update->localities) {
|
707
797
|
const auto& locality = p.second;
|
708
798
|
gpr_log(GPR_INFO,
|
709
799
|
"[xds_client %p] Priority %" PRIuPTR ", locality %" PRIuPTR
|
710
800
|
" %s contains %" PRIuPTR " server addresses",
|
711
|
-
xds_client, priority, locality_count,
|
801
|
+
xds_client(), priority, locality_count,
|
712
802
|
locality.name->AsHumanReadableString(),
|
713
803
|
locality.serverlist.size());
|
714
804
|
for (size_t i = 0; i < locality.serverlist.size(); ++i) {
|
@@ -718,59 +808,184 @@ void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked(
|
|
718
808
|
gpr_log(GPR_INFO,
|
719
809
|
"[xds_client %p] Priority %" PRIuPTR ", locality %" PRIuPTR
|
720
810
|
" %s, server address %" PRIuPTR ": %s",
|
721
|
-
xds_client, priority, locality_count,
|
811
|
+
xds_client(), priority, locality_count,
|
722
812
|
locality.name->AsHumanReadableString(), i, ipport);
|
723
813
|
gpr_free(ipport);
|
724
814
|
}
|
725
815
|
++locality_count;
|
726
816
|
}
|
727
817
|
}
|
728
|
-
for (size_t i = 0;
|
729
|
-
++i) {
|
818
|
+
for (size_t i = 0;
|
819
|
+
i < eds_update.drop_config->drop_category_list().size(); ++i) {
|
730
820
|
const XdsDropConfig::DropCategory& drop_category =
|
731
|
-
|
821
|
+
eds_update.drop_config->drop_category_list()[i];
|
732
822
|
gpr_log(GPR_INFO,
|
733
823
|
"[xds_client %p] Drop category %s has drop rate %d per million",
|
734
|
-
xds_client, drop_category.name.
|
824
|
+
xds_client(), drop_category.name.c_str(),
|
735
825
|
drop_category.parts_per_million);
|
736
826
|
}
|
737
827
|
}
|
738
|
-
|
739
|
-
|
740
|
-
if (lrs_call != nullptr) {
|
741
|
-
LrsCallState* lrs_calld = lrs_call->calld();
|
742
|
-
if (lrs_calld != nullptr) lrs_calld->MaybeStartReportingLocked();
|
743
|
-
}
|
828
|
+
EndpointState& endpoint_state =
|
829
|
+
xds_client()->endpoint_map_[eds_service_name];
|
744
830
|
// Ignore identical update.
|
745
|
-
const EdsUpdate& prev_update =
|
831
|
+
const EdsUpdate& prev_update = endpoint_state.update;
|
746
832
|
const bool priority_list_changed =
|
747
|
-
prev_update.priority_list_update !=
|
833
|
+
prev_update.priority_list_update != eds_update.priority_list_update;
|
748
834
|
const bool drop_config_changed =
|
749
835
|
prev_update.drop_config == nullptr ||
|
750
|
-
*prev_update.drop_config != *
|
836
|
+
*prev_update.drop_config != *eds_update.drop_config;
|
751
837
|
if (!priority_list_changed && !drop_config_changed) {
|
752
838
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
|
753
839
|
gpr_log(GPR_INFO,
|
754
840
|
"[xds_client %p] EDS update identical to current, ignoring.",
|
755
|
-
xds_client);
|
841
|
+
xds_client());
|
756
842
|
}
|
757
|
-
|
843
|
+
continue;
|
758
844
|
}
|
759
845
|
// Update the cluster state.
|
760
|
-
|
761
|
-
cluster_state.eds_update = std::move(update);
|
846
|
+
endpoint_state.update = std::move(eds_update);
|
762
847
|
// Notify all watchers.
|
763
|
-
for (const auto& p :
|
764
|
-
p.first->OnEndpointChanged(
|
848
|
+
for (const auto& p : endpoint_state.watchers) {
|
849
|
+
p.first->OnEndpointChanged(endpoint_state.update);
|
765
850
|
}
|
766
|
-
}
|
851
|
+
}
|
852
|
+
eds_version_.version_info = std::move(new_version);
|
853
|
+
}
|
854
|
+
|
855
|
+
void XdsClient::ChannelState::AdsCallState::OnRequestSent(void* arg,
|
856
|
+
grpc_error* error) {
|
857
|
+
AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
|
858
|
+
ads_calld->xds_client()->combiner_->Run(
|
859
|
+
GRPC_CLOSURE_INIT(&ads_calld->on_request_sent_, OnRequestSentLocked,
|
860
|
+
ads_calld, nullptr),
|
861
|
+
GRPC_ERROR_REF(error));
|
862
|
+
}
|
863
|
+
|
864
|
+
void XdsClient::ChannelState::AdsCallState::OnRequestSentLocked(
|
865
|
+
void* arg, grpc_error* error) {
|
866
|
+
AdsCallState* self = static_cast<AdsCallState*>(arg);
|
867
|
+
if (self->IsCurrentCallOnChannel() && error == GRPC_ERROR_NONE) {
|
868
|
+
// Clean up the sent message.
|
869
|
+
grpc_byte_buffer_destroy(self->send_message_payload_);
|
870
|
+
self->send_message_payload_ = nullptr;
|
871
|
+
// Continue to send another pending message if any.
|
872
|
+
// TODO(roth): The current code to handle buffered messages has the
|
873
|
+
// advantage of sending only the most recent list of resource names for each
|
874
|
+
// resource type (no matter how many times that resource type has been
|
875
|
+
// requested to send while the current message sending is still pending).
|
876
|
+
// But its disadvantage is that we send the requests in fixed order of
|
877
|
+
// resource types. We need to fix this if we are seeing some resource
|
878
|
+
// type(s) starved due to frequent requests of other resource type(s).
|
879
|
+
for (auto& p : self->buffered_request_map_) {
|
880
|
+
const std::string& type_url = p.first;
|
881
|
+
std::unique_ptr<BufferedRequest>& buffered_request = p.second;
|
882
|
+
if (buffered_request != nullptr) {
|
883
|
+
self->SendMessageLocked(type_url, buffered_request->nonce,
|
884
|
+
buffered_request->error, false);
|
885
|
+
buffered_request->error = GRPC_ERROR_NONE;
|
886
|
+
buffered_request.reset();
|
887
|
+
break;
|
888
|
+
}
|
889
|
+
}
|
890
|
+
}
|
891
|
+
self->Unref(DEBUG_LOCATION, "ADS+OnRequestSentLocked");
|
892
|
+
}
|
893
|
+
|
894
|
+
void XdsClient::ChannelState::AdsCallState::OnResponseReceived(
|
895
|
+
void* arg, grpc_error* error) {
|
896
|
+
AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
|
897
|
+
ads_calld->xds_client()->combiner_->Run(
|
898
|
+
GRPC_CLOSURE_INIT(&ads_calld->on_response_received_,
|
899
|
+
OnResponseReceivedLocked, ads_calld, nullptr),
|
900
|
+
GRPC_ERROR_REF(error));
|
901
|
+
}
|
902
|
+
|
903
|
+
void XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked(
|
904
|
+
void* arg, grpc_error* /*error*/) {
|
905
|
+
AdsCallState* ads_calld = static_cast<AdsCallState*>(arg);
|
906
|
+
XdsClient* xds_client = ads_calld->xds_client();
|
907
|
+
// Empty payload means the call was cancelled.
|
908
|
+
if (!ads_calld->IsCurrentCallOnChannel() ||
|
909
|
+
ads_calld->recv_message_payload_ == nullptr) {
|
910
|
+
ads_calld->Unref(DEBUG_LOCATION, "ADS+OnResponseReceivedLocked");
|
911
|
+
return;
|
912
|
+
}
|
913
|
+
// Read the response.
|
914
|
+
grpc_byte_buffer_reader bbr;
|
915
|
+
grpc_byte_buffer_reader_init(&bbr, ads_calld->recv_message_payload_);
|
916
|
+
grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
|
917
|
+
grpc_byte_buffer_reader_destroy(&bbr);
|
918
|
+
grpc_byte_buffer_destroy(ads_calld->recv_message_payload_);
|
919
|
+
ads_calld->recv_message_payload_ = nullptr;
|
920
|
+
// TODO(juanlishen): When we convert this to use the xds protocol, the
|
921
|
+
// balancer will send us a fallback timeout such that we should go into
|
922
|
+
// fallback mode if we have lost contact with the balancer after a certain
|
923
|
+
// period of time. We will need to save the timeout value here, and then
|
924
|
+
// when the balancer call ends, we will need to start a timer for the
|
925
|
+
// specified period of time, and if the timer fires, we go into fallback
|
926
|
+
// mode. We will also need to cancel the timer when we receive a serverlist
|
927
|
+
// from the balancer.
|
928
|
+
// Parse the response.
|
929
|
+
CdsUpdateMap cds_update_map;
|
930
|
+
EdsUpdateMap eds_update_map;
|
931
|
+
std::string version;
|
932
|
+
std::string nonce;
|
933
|
+
std::string type_url;
|
934
|
+
// Note that XdsAdsResponseDecodeAndParse() also validate the response.
|
935
|
+
grpc_error* parse_error = XdsAdsResponseDecodeAndParse(
|
936
|
+
response_slice, xds_client->EdsServiceNames(), &cds_update_map,
|
937
|
+
&eds_update_map, &version, &nonce, &type_url);
|
767
938
|
grpc_slice_unref_internal(response_slice);
|
939
|
+
if (type_url.empty()) {
|
940
|
+
// Ignore unparsable response.
|
941
|
+
gpr_log(GPR_ERROR, "[xds_client %p] No type_url found. error=%s",
|
942
|
+
xds_client, grpc_error_string(parse_error));
|
943
|
+
GRPC_ERROR_UNREF(parse_error);
|
944
|
+
} else {
|
945
|
+
// Update nonce and error.
|
946
|
+
if (type_url == kCdsTypeUrl) {
|
947
|
+
ads_calld->cds_version_.nonce = nonce;
|
948
|
+
GRPC_ERROR_UNREF(ads_calld->cds_version_.error);
|
949
|
+
ads_calld->cds_version_.error = GRPC_ERROR_REF(parse_error);
|
950
|
+
} else if (type_url == kEdsTypeUrl) {
|
951
|
+
ads_calld->eds_version_.nonce = nonce;
|
952
|
+
GRPC_ERROR_UNREF(ads_calld->eds_version_.error);
|
953
|
+
ads_calld->eds_version_.error = GRPC_ERROR_REF(parse_error);
|
954
|
+
}
|
955
|
+
// NACK or ACK the response.
|
956
|
+
if (parse_error != GRPC_ERROR_NONE) {
|
957
|
+
// NACK unacceptable update.
|
958
|
+
gpr_log(
|
959
|
+
GPR_ERROR,
|
960
|
+
"[xds_client %p] ADS response can't be accepted, NACKing. error=%s",
|
961
|
+
xds_client, grpc_error_string(parse_error));
|
962
|
+
ads_calld->SendMessageLocked(type_url, nonce, parse_error, false);
|
963
|
+
} else {
|
964
|
+
ads_calld->seen_response_ = true;
|
965
|
+
// Accept the (CDS or EDS) response.
|
966
|
+
if (type_url == kCdsTypeUrl) {
|
967
|
+
ads_calld->AcceptCdsUpdate(std::move(cds_update_map),
|
968
|
+
std::move(version));
|
969
|
+
} else if (type_url == kEdsTypeUrl) {
|
970
|
+
ads_calld->AcceptEdsUpdate(std::move(eds_update_map),
|
971
|
+
std::move(version));
|
972
|
+
}
|
973
|
+
// ACK the update.
|
974
|
+
ads_calld->SendMessageLocked(type_url, "", nullptr, false);
|
975
|
+
// Start load reporting if needed.
|
976
|
+
auto& lrs_call = ads_calld->chand()->lrs_calld_;
|
977
|
+
if (lrs_call != nullptr) {
|
978
|
+
LrsCallState* lrs_calld = lrs_call->calld();
|
979
|
+
if (lrs_calld != nullptr) lrs_calld->MaybeStartReportingLocked();
|
980
|
+
}
|
981
|
+
}
|
982
|
+
}
|
768
983
|
if (xds_client->shutting_down_) {
|
769
984
|
ads_calld->Unref(DEBUG_LOCATION,
|
770
985
|
"ADS+OnResponseReceivedLocked+xds_shutdown");
|
771
986
|
return;
|
772
987
|
}
|
773
|
-
// Keep listening for
|
988
|
+
// Keep listening for updates.
|
774
989
|
grpc_op op;
|
775
990
|
memset(&op, 0, sizeof(op));
|
776
991
|
op.op = GRPC_OP_RECV_MESSAGE;
|
@@ -869,15 +1084,8 @@ void XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimerLocked(
|
|
869
1084
|
|
870
1085
|
void XdsClient::ChannelState::LrsCallState::Reporter::SendReportLocked() {
|
871
1086
|
// Create a request that contains the load report.
|
872
|
-
// TODO(roth): Currently, it is not possible to have multiple client
|
873
|
-
// stats objects for a given cluster. However, in the future, we may
|
874
|
-
// run into cases where this happens (e.g., due to graceful LB policy
|
875
|
-
// switching). If/when this becomes a problem, replace this assertion
|
876
|
-
// with code to merge data from multiple client stats objects.
|
877
|
-
GPR_ASSERT(xds_client()->cluster_state_.client_stats.size() == 1);
|
878
|
-
auto* client_stats = *xds_client()->cluster_state_.client_stats.begin();
|
879
1087
|
grpc_slice request_payload_slice =
|
880
|
-
XdsLrsRequestCreateAndEncode(
|
1088
|
+
XdsLrsRequestCreateAndEncode(xds_client()->ClientStatsMap());
|
881
1089
|
// Skip client load report if the counters were all zero in the last
|
882
1090
|
// report and they are still zero in this one.
|
883
1091
|
const bool old_val = last_report_counters_were_zero_;
|
@@ -945,8 +1153,7 @@ XdsClient::ChannelState::LrsCallState::LrsCallState(
|
|
945
1153
|
// activity in xds_client()->interested_parties_, which is comprised of
|
946
1154
|
// the polling entities from client_channel.
|
947
1155
|
GPR_ASSERT(xds_client() != nullptr);
|
948
|
-
GPR_ASSERT(xds_client()->server_name_
|
949
|
-
GPR_ASSERT(*xds_client()->server_name_.get() != '\0');
|
1156
|
+
GPR_ASSERT(!xds_client()->server_name_.empty());
|
950
1157
|
call_ = grpc_channel_create_pollset_set_call(
|
951
1158
|
chand()->channel_, nullptr, GRPC_PROPAGATE_DEFAULTS,
|
952
1159
|
xds_client()->interested_parties_,
|
@@ -955,7 +1162,7 @@ XdsClient::ChannelState::LrsCallState::LrsCallState(
|
|
955
1162
|
GPR_ASSERT(call_ != nullptr);
|
956
1163
|
// Init the request payload.
|
957
1164
|
grpc_slice request_payload_slice = XdsLrsRequestCreateAndEncode(
|
958
|
-
xds_client()->server_name_
|
1165
|
+
xds_client()->server_name_, xds_client()->bootstrap_->node(),
|
959
1166
|
xds_client()->build_version_.get());
|
960
1167
|
send_message_payload_ =
|
961
1168
|
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
|
@@ -1069,13 +1276,22 @@ void XdsClient::ChannelState::LrsCallState::MaybeStartReportingLocked() {
|
|
1069
1276
|
AdsCallState* ads_calld = chand()->ads_calld_->calld();
|
1070
1277
|
if (ads_calld == nullptr || !ads_calld->seen_response()) return;
|
1071
1278
|
// Start reporting.
|
1072
|
-
for (auto
|
1073
|
-
client_stats
|
1279
|
+
for (auto& p : chand()->xds_client_->endpoint_map_) {
|
1280
|
+
for (auto* client_stats : p.second.client_stats) {
|
1281
|
+
client_stats->MaybeInitLastReportTime();
|
1282
|
+
}
|
1074
1283
|
}
|
1075
1284
|
reporter_ = MakeOrphanable<Reporter>(
|
1076
1285
|
Ref(DEBUG_LOCATION, "LRS+load_report+start"), load_reporting_interval_);
|
1077
1286
|
}
|
1078
1287
|
|
1288
|
+
bool XdsClient::ChannelState::LrsCallState::ShouldSendLoadReports(
|
1289
|
+
const StringView& cluster_name) const {
|
1290
|
+
// Only send load reports for the clusters that are asked for by the LRS
|
1291
|
+
// server.
|
1292
|
+
return cluster_names_.find(std::string(cluster_name)) != cluster_names_.end();
|
1293
|
+
}
|
1294
|
+
|
1079
1295
|
void XdsClient::ChannelState::LrsCallState::OnInitialRequestSent(
|
1080
1296
|
void* arg, grpc_error* error) {
|
1081
1297
|
LrsCallState* lrs_calld = static_cast<LrsCallState*>(arg);
|
@@ -1124,10 +1340,10 @@ void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked(
|
|
1124
1340
|
// This anonymous lambda is a hack to avoid the usage of goto.
|
1125
1341
|
[&]() {
|
1126
1342
|
// Parse the response.
|
1127
|
-
|
1343
|
+
std::set<std::string> new_cluster_names;
|
1128
1344
|
grpc_millis new_load_reporting_interval;
|
1129
1345
|
grpc_error* parse_error = XdsLrsResponseDecodeAndParse(
|
1130
|
-
response_slice, &
|
1346
|
+
response_slice, &new_cluster_names, &new_load_reporting_interval);
|
1131
1347
|
if (parse_error != GRPC_ERROR_NONE) {
|
1132
1348
|
gpr_log(GPR_ERROR,
|
1133
1349
|
"[xds_client %p] LRS response parsing failed. error=%s",
|
@@ -1138,9 +1354,15 @@ void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked(
|
|
1138
1354
|
lrs_calld->seen_response_ = true;
|
1139
1355
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
|
1140
1356
|
gpr_log(GPR_INFO,
|
1141
|
-
"[xds_client %p] LRS response received,
|
1142
|
-
"load_report_interval=%" PRId64 "ms",
|
1143
|
-
xds_client,
|
1357
|
+
"[xds_client %p] LRS response received, %" PRIuPTR
|
1358
|
+
" cluster names, load_report_interval=%" PRId64 "ms",
|
1359
|
+
xds_client, new_cluster_names.size(),
|
1360
|
+
new_load_reporting_interval);
|
1361
|
+
size_t i = 0;
|
1362
|
+
for (const auto& name : new_cluster_names) {
|
1363
|
+
gpr_log(GPR_INFO, "[xds_client %p] cluster_name %" PRIuPTR ": %s",
|
1364
|
+
xds_client, i++, name.c_str());
|
1365
|
+
}
|
1144
1366
|
}
|
1145
1367
|
if (new_load_reporting_interval <
|
1146
1368
|
GRPC_XDS_MIN_CLIENT_LOAD_REPORTING_INTERVAL_MS) {
|
@@ -1154,8 +1376,8 @@ void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked(
|
|
1154
1376
|
}
|
1155
1377
|
}
|
1156
1378
|
// Ignore identical update.
|
1157
|
-
if (lrs_calld->
|
1158
|
-
|
1379
|
+
if (lrs_calld->cluster_names_ == new_cluster_names &&
|
1380
|
+
lrs_calld->load_reporting_interval_ == new_load_reporting_interval) {
|
1159
1381
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
|
1160
1382
|
gpr_log(GPR_INFO,
|
1161
1383
|
"[xds_client %p] Incoming LRS response identical to current, "
|
@@ -1167,7 +1389,7 @@ void XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked(
|
|
1167
1389
|
// Stop current load reporting (if any) to adopt the new config.
|
1168
1390
|
lrs_calld->reporter_.reset();
|
1169
1391
|
// Record the new config.
|
1170
|
-
lrs_calld->
|
1392
|
+
lrs_calld->cluster_names_ = std::move(new_cluster_names);
|
1171
1393
|
lrs_calld->load_reporting_interval_ = new_load_reporting_interval;
|
1172
1394
|
// Try starting sending load report.
|
1173
1395
|
lrs_calld->MaybeStartReportingLocked();
|
@@ -1253,11 +1475,12 @@ XdsClient::XdsClient(Combiner* combiner, grpc_pollset_set* interested_parties,
|
|
1253
1475
|
StringView server_name,
|
1254
1476
|
std::unique_ptr<ServiceConfigWatcherInterface> watcher,
|
1255
1477
|
const grpc_channel_args& channel_args, grpc_error** error)
|
1256
|
-
:
|
1478
|
+
: InternallyRefCounted<XdsClient>(&grpc_xds_client_trace),
|
1479
|
+
build_version_(GenerateBuildVersionString()),
|
1257
1480
|
combiner_(GRPC_COMBINER_REF(combiner, "xds_client")),
|
1258
1481
|
interested_parties_(interested_parties),
|
1259
1482
|
bootstrap_(XdsBootstrap::ReadFromFile(error)),
|
1260
|
-
server_name_(
|
1483
|
+
server_name_(server_name),
|
1261
1484
|
service_config_watcher_(std::move(watcher)) {
|
1262
1485
|
if (*error != GRPC_ERROR_NONE) {
|
1263
1486
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
|
@@ -1268,7 +1491,7 @@ XdsClient::XdsClient(Combiner* combiner, grpc_pollset_set* interested_parties,
|
|
1268
1491
|
}
|
1269
1492
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
|
1270
1493
|
gpr_log(GPR_INFO, "[xds_client %p: creating channel to %s", this,
|
1271
|
-
bootstrap_->
|
1494
|
+
bootstrap_->server().server_uri);
|
1272
1495
|
}
|
1273
1496
|
chand_ = MakeOrphanable<ChannelState>(
|
1274
1497
|
Ref(DEBUG_LOCATION, "XdsClient+ChannelState"), channel_args);
|
@@ -1286,77 +1509,95 @@ XdsClient::~XdsClient() { GRPC_COMBINER_UNREF(combiner_, "xds_client"); }
|
|
1286
1509
|
void XdsClient::Orphan() {
|
1287
1510
|
shutting_down_ = true;
|
1288
1511
|
chand_.reset();
|
1512
|
+
cluster_map_.clear();
|
1513
|
+
endpoint_map_.clear();
|
1289
1514
|
Unref(DEBUG_LOCATION, "XdsClient::Orphan()");
|
1290
1515
|
}
|
1291
1516
|
|
1292
1517
|
void XdsClient::WatchClusterData(
|
1293
|
-
StringView
|
1518
|
+
StringView cluster_name, std::unique_ptr<ClusterWatcherInterface> watcher) {
|
1519
|
+
const bool new_name = cluster_map_.find(cluster_name) == cluster_map_.end();
|
1520
|
+
ClusterState& cluster_state = cluster_map_[cluster_name];
|
1294
1521
|
ClusterWatcherInterface* w = watcher.get();
|
1295
|
-
|
1296
|
-
//
|
1297
|
-
//
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1522
|
+
cluster_state.watchers[w] = std::move(watcher);
|
1523
|
+
// If we've already received an CDS update, notify the new watcher
|
1524
|
+
// immediately.
|
1525
|
+
if (cluster_state.update.has_value()) {
|
1526
|
+
w->OnClusterChanged(cluster_state.update.value());
|
1527
|
+
}
|
1528
|
+
if (new_name) chand_->OnResourceNamesChanged(kCdsTypeUrl);
|
1302
1529
|
}
|
1303
1530
|
|
1304
|
-
void XdsClient::CancelClusterDataWatch(StringView
|
1531
|
+
void XdsClient::CancelClusterDataWatch(StringView cluster_name,
|
1305
1532
|
ClusterWatcherInterface* watcher) {
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1533
|
+
if (shutting_down_) return;
|
1534
|
+
ClusterState& cluster_state = cluster_map_[cluster_name];
|
1535
|
+
auto it = cluster_state.watchers.find(watcher);
|
1536
|
+
if (it != cluster_state.watchers.end()) {
|
1537
|
+
cluster_state.watchers.erase(it);
|
1538
|
+
if (cluster_state.watchers.empty()) {
|
1539
|
+
cluster_map_.erase(cluster_name);
|
1540
|
+
chand_->OnResourceNamesChanged(kCdsTypeUrl);
|
1541
|
+
}
|
1312
1542
|
}
|
1543
|
+
chand_->OnWatcherRemoved();
|
1313
1544
|
}
|
1314
1545
|
|
1315
1546
|
void XdsClient::WatchEndpointData(
|
1316
|
-
StringView
|
1547
|
+
StringView eds_service_name,
|
1548
|
+
std::unique_ptr<EndpointWatcherInterface> watcher) {
|
1549
|
+
const bool new_name =
|
1550
|
+
endpoint_map_.find(eds_service_name) == endpoint_map_.end();
|
1551
|
+
EndpointState& endpoint_state = endpoint_map_[eds_service_name];
|
1317
1552
|
EndpointWatcherInterface* w = watcher.get();
|
1318
|
-
|
1553
|
+
endpoint_state.watchers[w] = std::move(watcher);
|
1319
1554
|
// If we've already received an EDS update, notify the new watcher
|
1320
1555
|
// immediately.
|
1321
|
-
if (!
|
1322
|
-
w->OnEndpointChanged(
|
1556
|
+
if (!endpoint_state.update.priority_list_update.empty()) {
|
1557
|
+
w->OnEndpointChanged(endpoint_state.update);
|
1323
1558
|
}
|
1324
|
-
chand_->
|
1559
|
+
if (new_name) chand_->OnResourceNamesChanged(kEdsTypeUrl);
|
1325
1560
|
}
|
1326
1561
|
|
1327
|
-
void XdsClient::CancelEndpointDataWatch(StringView
|
1562
|
+
void XdsClient::CancelEndpointDataWatch(StringView eds_service_name,
|
1328
1563
|
EndpointWatcherInterface* watcher) {
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1564
|
+
if (shutting_down_) return;
|
1565
|
+
EndpointState& endpoint_state = endpoint_map_[eds_service_name];
|
1566
|
+
auto it = endpoint_state.watchers.find(watcher);
|
1567
|
+
if (it != endpoint_state.watchers.end()) {
|
1568
|
+
endpoint_state.watchers.erase(it);
|
1569
|
+
if (endpoint_state.watchers.empty()) {
|
1570
|
+
endpoint_map_.erase(eds_service_name);
|
1571
|
+
chand_->OnResourceNamesChanged(kEdsTypeUrl);
|
1572
|
+
}
|
1335
1573
|
}
|
1574
|
+
chand_->OnWatcherRemoved();
|
1336
1575
|
}
|
1337
1576
|
|
1338
1577
|
void XdsClient::AddClientStats(StringView /*lrs_server*/,
|
1339
|
-
StringView
|
1578
|
+
StringView cluster_name,
|
1340
1579
|
XdsClientStats* client_stats) {
|
1580
|
+
EndpointState& endpoint_state = endpoint_map_[cluster_name];
|
1341
1581
|
// TODO(roth): When we add support for direct federation, use the
|
1342
1582
|
// server name specified in lrs_server.
|
1343
|
-
|
1583
|
+
endpoint_state.client_stats.insert(client_stats);
|
1344
1584
|
chand_->MaybeStartLrsCall();
|
1345
1585
|
}
|
1346
1586
|
|
1347
1587
|
void XdsClient::RemoveClientStats(StringView /*lrs_server*/,
|
1348
|
-
StringView
|
1588
|
+
StringView cluster_name,
|
1349
1589
|
XdsClientStats* client_stats) {
|
1590
|
+
EndpointState& endpoint_state = endpoint_map_[cluster_name];
|
1350
1591
|
// TODO(roth): When we add support for direct federation, use the
|
1351
1592
|
// server name specified in lrs_server.
|
1352
1593
|
// TODO(roth): In principle, we should try to send a final load report
|
1353
1594
|
// containing whatever final stats have been accumulated since the
|
1354
1595
|
// last load report.
|
1355
|
-
auto it =
|
1356
|
-
if (it !=
|
1357
|
-
|
1596
|
+
auto it = endpoint_state.client_stats.find(client_stats);
|
1597
|
+
if (it != endpoint_state.client_stats.end()) {
|
1598
|
+
endpoint_state.client_stats.erase(it);
|
1358
1599
|
}
|
1359
|
-
if (chand_ != nullptr &&
|
1600
|
+
if (chand_ != nullptr && endpoint_state.client_stats.empty()) {
|
1360
1601
|
chand_->StopLrsCall();
|
1361
1602
|
}
|
1362
1603
|
}
|
@@ -1367,15 +1608,55 @@ void XdsClient::ResetBackoff() {
|
|
1367
1608
|
}
|
1368
1609
|
}
|
1369
1610
|
|
1611
|
+
std::set<StringView> XdsClient::WatchedClusterNames() const {
|
1612
|
+
std::set<StringView> cluster_names;
|
1613
|
+
for (const auto& p : cluster_map_) {
|
1614
|
+
const StringView& cluster_name = p.first;
|
1615
|
+
const ClusterState& cluster_state = p.second;
|
1616
|
+
// Don't request for the clusters that are cached before watched.
|
1617
|
+
if (cluster_state.watchers.empty()) continue;
|
1618
|
+
cluster_names.emplace(cluster_name);
|
1619
|
+
}
|
1620
|
+
return cluster_names;
|
1621
|
+
}
|
1622
|
+
|
1623
|
+
std::set<StringView> XdsClient::EdsServiceNames() const {
|
1624
|
+
std::set<StringView> eds_service_names;
|
1625
|
+
for (const auto& p : endpoint_map_) {
|
1626
|
+
const StringView& eds_service_name = p.first;
|
1627
|
+
eds_service_names.emplace(eds_service_name);
|
1628
|
+
}
|
1629
|
+
return eds_service_names;
|
1630
|
+
}
|
1631
|
+
|
1632
|
+
std::map<StringView, std::set<XdsClientStats*>> XdsClient::ClientStatsMap()
|
1633
|
+
const {
|
1634
|
+
std::map<StringView, std::set<XdsClientStats*>> client_stats_map;
|
1635
|
+
for (const auto& p : endpoint_map_) {
|
1636
|
+
const StringView& cluster_name = p.first;
|
1637
|
+
const auto& client_stats = p.second.client_stats;
|
1638
|
+
if (chand_->lrs_calld()->ShouldSendLoadReports(cluster_name)) {
|
1639
|
+
client_stats_map.emplace(cluster_name, client_stats);
|
1640
|
+
}
|
1641
|
+
}
|
1642
|
+
return client_stats_map;
|
1643
|
+
}
|
1644
|
+
|
1370
1645
|
void XdsClient::NotifyOnError(grpc_error* error) {
|
1371
1646
|
if (service_config_watcher_ != nullptr) {
|
1372
1647
|
service_config_watcher_->OnError(GRPC_ERROR_REF(error));
|
1373
1648
|
}
|
1374
|
-
for (const auto& p :
|
1375
|
-
p.
|
1649
|
+
for (const auto& p : cluster_map_) {
|
1650
|
+
const ClusterState& cluster_state = p.second;
|
1651
|
+
for (const auto& p : cluster_state.watchers) {
|
1652
|
+
p.first->OnError(GRPC_ERROR_REF(error));
|
1653
|
+
}
|
1376
1654
|
}
|
1377
|
-
for (const auto& p :
|
1378
|
-
p.
|
1655
|
+
for (const auto& p : endpoint_map_) {
|
1656
|
+
const EndpointState& endpoint_state = p.second;
|
1657
|
+
for (const auto& p : endpoint_state.watchers) {
|
1658
|
+
p.first->OnError(GRPC_ERROR_REF(error));
|
1659
|
+
}
|
1379
1660
|
}
|
1380
1661
|
GRPC_ERROR_UNREF(error);
|
1381
1662
|
}
|
@@ -1393,7 +1674,7 @@ void XdsClient::NotifyOnServiceConfig(void* arg, grpc_error* error) {
|
|
1393
1674
|
" } }\n"
|
1394
1675
|
" ]\n"
|
1395
1676
|
"}",
|
1396
|
-
self->server_name_.
|
1677
|
+
self->server_name_.c_str());
|
1397
1678
|
RefCountedPtr<ServiceConfig> service_config =
|
1398
1679
|
ServiceConfig::Create(json, &error);
|
1399
1680
|
gpr_free(json);
|