3 * Copyright 2018 gRPC authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #ifndef GRPC_CORE_EXT_XDS_XDS_API_H
20 #define GRPC_CORE_EXT_XDS_XDS_API_H
22 #include <grpc/support/port_platform.h>
28 #include "absl/container/inlined_vector.h"
29 #include "absl/types/optional.h"
32 #include "upb/def.hpp"
34 #include <grpc/slice_buffer.h>
36 #include "src/core/ext/filters/client_channel/server_address.h"
37 #include "src/core/ext/xds/xds_bootstrap.h"
38 #include "src/core/ext/xds/xds_client_stats.h"
42 // TODO(yashykt): Check to see if xDS security is enabled. This will be
43 // removed once this feature is fully integration-tested and enabled by
45 bool XdsSecurityEnabled();
51 static const char* kLdsTypeUrl;
52 static const char* kRdsTypeUrl;
53 static const char* kCdsTypeUrl;
54 static const char* kEdsTypeUrl;
59 bool operator==(const Duration& other) const {
60 return (seconds == other.seconds && nanos == other.nanos);
62 std::string ToString() const {
63 return absl::StrFormat("Duration seconds: %ld, nanos %d", seconds, nanos);
67 // TODO(donnadionne): When we can use absl::variant<>, consider using that
68 // for: PathMatcher, HeaderMatcher, cluster_name and weighted_clusters
70 // Matchers for this route.
73 enum class PathMatcherType {
74 PATH, // path stored in string_matcher field
75 PREFIX, // prefix stored in string_matcher field
76 REGEX, // regex stored in regex_matcher field
79 std::string string_matcher;
80 std::unique_ptr<RE2> regex_matcher;
81 bool case_sensitive = true;
83 PathMatcher() = default;
84 PathMatcher(const PathMatcher& other);
85 PathMatcher& operator=(const PathMatcher& other);
86 bool operator==(const PathMatcher& other) const;
87 std::string ToString() const;
90 struct HeaderMatcher {
91 enum class HeaderMatcherType {
92 EXACT, // value stored in string_matcher field
93 REGEX, // uses regex_match field
94 RANGE, // uses range_start and range_end fields
95 PRESENT, // uses present_match field
96 PREFIX, // prefix stored in string_matcher field
97 SUFFIX, // suffix stored in string_matcher field
100 HeaderMatcherType type;
103 std::string string_matcher;
104 std::unique_ptr<RE2> regex_match;
106 // invert_match field may or may not exisit, so initialize it to
108 bool invert_match = false;
110 HeaderMatcher() = default;
111 HeaderMatcher(const HeaderMatcher& other);
112 HeaderMatcher& operator=(const HeaderMatcher& other);
113 bool operator==(const HeaderMatcher& other) const;
114 std::string ToString() const;
117 PathMatcher path_matcher;
118 std::vector<HeaderMatcher> header_matchers;
119 absl::optional<uint32_t> fraction_per_million;
121 bool operator==(const Matchers& other) const {
122 return (path_matcher == other.path_matcher &&
123 header_matchers == other.header_matchers &&
124 fraction_per_million == other.fraction_per_million);
126 std::string ToString() const;
131 // Action for this route.
132 // TODO(roth): When we can use absl::variant<>, consider using that
133 // here, to enforce the fact that only one of the two fields can be set.
134 std::string cluster_name;
135 struct ClusterWeight {
138 bool operator==(const ClusterWeight& other) const {
139 return (name == other.name && weight == other.weight);
141 std::string ToString() const;
143 std::vector<ClusterWeight> weighted_clusters;
144 // Storing the timeout duration from route action:
145 // RouteAction.max_stream_duration.grpc_timeout_header_max or
146 // RouteAction.max_stream_duration.max_stream_duration if the former is
148 absl::optional<Duration> max_stream_duration;
150 bool operator==(const Route& other) const {
151 return (matchers == other.matchers &&
152 cluster_name == other.cluster_name &&
153 weighted_clusters == other.weighted_clusters &&
154 max_stream_duration == other.max_stream_duration);
156 std::string ToString() const;
161 std::vector<std::string> domains;
162 std::vector<Route> routes;
164 bool operator==(const VirtualHost& other) const {
165 return domains == other.domains && routes == other.routes;
169 std::vector<VirtualHost> virtual_hosts;
171 bool operator==(const RdsUpdate& other) const {
172 return virtual_hosts == other.virtual_hosts;
174 std::string ToString() const;
175 VirtualHost* FindVirtualHostForDomain(const std::string& domain);
178 struct StringMatcher {
179 enum class StringMatcherType {
180 EXACT, // value stored in string_matcher_field
181 PREFIX, // value stored in string_matcher_field
182 SUFFIX, // value stored in string_matcher_field
183 SAFE_REGEX, // use regex_match field
184 CONTAINS, // value stored in string_matcher_field
186 StringMatcherType type;
187 std::string string_matcher;
188 std::unique_ptr<RE2> regex_match;
191 StringMatcher() = default;
192 StringMatcher(const StringMatcher& other);
193 StringMatcher& operator=(const StringMatcher& other);
194 bool operator==(const StringMatcher& other) const;
197 struct CommonTlsContext {
198 struct CertificateValidationContext {
199 std::vector<StringMatcher> match_subject_alt_names;
201 bool operator==(const CertificateValidationContext& other) const {
202 return match_subject_alt_names == other.match_subject_alt_names;
206 struct CertificateProviderInstance {
207 std::string instance_name;
208 std::string certificate_name;
210 bool operator==(const CertificateProviderInstance& other) const {
211 return instance_name == other.instance_name &&
212 certificate_name == other.certificate_name;
216 struct CombinedCertificateValidationContext {
217 CertificateValidationContext default_validation_context;
218 CertificateProviderInstance
219 validation_context_certificate_provider_instance;
221 bool operator==(const CombinedCertificateValidationContext& other) const {
222 return default_validation_context == other.default_validation_context &&
223 validation_context_certificate_provider_instance ==
224 other.validation_context_certificate_provider_instance;
228 CertificateProviderInstance tls_certificate_certificate_provider_instance;
229 CombinedCertificateValidationContext combined_validation_context;
231 bool operator==(const CommonTlsContext& other) const {
232 return tls_certificate_certificate_provider_instance ==
233 other.tls_certificate_certificate_provider_instance &&
234 combined_validation_context == other.combined_validation_context;
238 // TODO(roth): When we can use absl::variant<>, consider using that
239 // here, to enforce the fact that only one of the two fields can be set.
241 // The name to use in the RDS request.
242 std::string route_config_name;
243 // Storing the Http Connection Manager Common Http Protocol Option
244 // max_stream_duration
245 Duration http_max_stream_duration;
246 // The RouteConfiguration to use for this listener.
247 // Present only if it is inlined in the LDS response.
248 absl::optional<RdsUpdate> rds_update;
250 bool operator==(const LdsUpdate& other) const {
251 return route_config_name == other.route_config_name &&
252 rds_update == other.rds_update &&
253 http_max_stream_duration == other.http_max_stream_duration;
257 using LdsUpdateMap = std::map<std::string /*server_name*/, LdsUpdate>;
259 using RdsUpdateMap = std::map<std::string /*route_config_name*/, RdsUpdate>;
262 // The name to use in the EDS request.
263 // If empty, the cluster name will be used.
264 std::string eds_service_name;
265 // Tls Context used by clients
266 CommonTlsContext common_tls_context;
267 // The LRS server to use for load reporting.
268 // If not set, load reporting will be disabled.
269 // If set to the empty string, will use the same server we obtained the CDS
271 absl::optional<std::string> lrs_load_reporting_server_name;
272 // Maximum number of outstanding requests can be made to the upstream
274 uint32_t max_concurrent_requests = 1024;
276 bool operator==(const CdsUpdate& other) const {
277 return eds_service_name == other.eds_service_name &&
278 common_tls_context == other.common_tls_context &&
279 lrs_load_reporting_server_name ==
280 other.lrs_load_reporting_server_name &&
281 max_concurrent_requests == other.max_concurrent_requests;
285 using CdsUpdateMap = std::map<std::string /*cluster_name*/, CdsUpdate>;
290 RefCountedPtr<XdsLocalityName> name;
292 ServerAddressList endpoints;
294 bool operator==(const Locality& other) const {
295 return *name == *other.name && lb_weight == other.lb_weight &&
296 endpoints == other.endpoints;
298 bool operator!=(const Locality& other) const {
299 return !(*this == other);
301 std::string ToString() const;
304 std::map<XdsLocalityName*, Locality, XdsLocalityName::Less> localities;
306 bool operator==(const Priority& other) const;
307 std::string ToString() const;
309 using PriorityList = absl::InlinedVector<Priority, 2>;
311 // There are two phases of accessing this class's content:
312 // 1. to initialize in the control plane combiner;
313 // 2. to use in the data plane combiner.
314 // So no additional synchronization is needed.
315 class DropConfig : public RefCounted<DropConfig> {
317 struct DropCategory {
318 bool operator==(const DropCategory& other) const {
319 return name == other.name &&
320 parts_per_million == other.parts_per_million;
324 const uint32_t parts_per_million;
327 using DropCategoryList = absl::InlinedVector<DropCategory, 2>;
329 void AddCategory(std::string name, uint32_t parts_per_million) {
330 drop_category_list_.emplace_back(
331 DropCategory{std::move(name), parts_per_million});
332 if (parts_per_million == 1000000) drop_all_ = true;
335 // The only method invoked from outside the WorkSerializer (used in
337 bool ShouldDrop(const std::string** category_name) const;
339 const DropCategoryList& drop_category_list() const {
340 return drop_category_list_;
343 bool drop_all() const { return drop_all_; }
345 bool operator==(const DropConfig& other) const {
346 return drop_category_list_ == other.drop_category_list_;
348 bool operator!=(const DropConfig& other) const {
349 return !(*this == other);
352 std::string ToString() const;
355 DropCategoryList drop_category_list_;
356 bool drop_all_ = false;
359 PriorityList priorities;
360 RefCountedPtr<DropConfig> drop_config;
362 bool operator==(const EdsUpdate& other) const {
363 return priorities == other.priorities &&
364 *drop_config == *other.drop_config;
366 std::string ToString() const;
369 using EdsUpdateMap = std::map<std::string /*eds_service_name*/, EdsUpdate>;
371 struct ClusterLoadReport {
372 XdsClusterDropStats::Snapshot dropped_requests;
373 std::map<RefCountedPtr<XdsLocalityName>, XdsClusterLocalityStats::Snapshot,
374 XdsLocalityName::Less>
376 grpc_millis load_report_interval;
378 using ClusterLoadReportMap = std::map<
379 std::pair<std::string /*cluster_name*/, std::string /*eds_service_name*/>,
382 XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node);
384 // Creates an ADS request.
385 // Takes ownership of \a error.
386 grpc_slice CreateAdsRequest(const XdsBootstrap::XdsServer& server,
387 const std::string& type_url,
388 const std::set<absl::string_view>& resource_names,
389 const std::string& version,
390 const std::string& nonce, grpc_error* error,
393 // Parses an ADS response.
394 // If the response can't be parsed at the top level, the resulting
395 // type_url will be empty.
396 struct AdsParseResult {
397 grpc_error* parse_error = GRPC_ERROR_NONE;
400 std::string type_url;
401 LdsUpdateMap lds_update_map;
402 RdsUpdateMap rds_update_map;
403 CdsUpdateMap cds_update_map;
404 EdsUpdateMap eds_update_map;
406 AdsParseResult ParseAdsResponse(
407 const grpc_slice& encoded_response,
408 const std::set<absl::string_view>& expected_listener_names,
409 const std::set<absl::string_view>& expected_route_configuration_names,
410 const std::set<absl::string_view>& expected_cluster_names,
411 const std::set<absl::string_view>& expected_eds_service_names);
413 // Creates an initial LRS request.
414 grpc_slice CreateLrsInitialRequest(const XdsBootstrap::XdsServer& server);
416 // Creates an LRS request sending a client-side load report.
417 grpc_slice CreateLrsRequest(ClusterLoadReportMap cluster_load_report_map);
419 // Parses the LRS response and returns \a
420 // load_reporting_interval for client-side load reporting. If there is any
421 // error, the output config is invalid.
422 grpc_error* ParseLrsResponse(const grpc_slice& encoded_response,
423 bool* send_all_clusters,
424 std::set<std::string>* cluster_names,
425 grpc_millis* load_reporting_interval);
430 const XdsBootstrap::Node* node_; // Do not own.
431 upb::SymbolTable symtab_;
432 const std::string build_version_;
433 const std::string user_agent_name_;
436 } // namespace grpc_core
438 #endif /* GRPC_CORE_EXT_XDS_XDS_API_H */