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"
39 #include "src/core/lib/security/authorization/matchers.h"
43 // TODO(yashykt): Check to see if xDS security is enabled. This will be
44 // removed once this feature is fully integration-tested and enabled by
46 bool XdsSecurityEnabled();
52 static const char* kLdsTypeUrl;
53 static const char* kRdsTypeUrl;
54 static const char* kCdsTypeUrl;
55 static const char* kEdsTypeUrl;
60 bool operator==(const Duration& other) const {
61 return (seconds == other.seconds && nanos == other.nanos);
63 std::string ToString() const {
64 return absl::StrFormat("Duration seconds: %ld, nanos %d", seconds, nanos);
68 // TODO(donnadionne): When we can use absl::variant<>, consider using that
69 // for: PathMatcher, HeaderMatcher, cluster_name and weighted_clusters
71 // Matchers for this route.
73 StringMatcher path_matcher;
74 std::vector<HeaderMatcher> header_matchers;
75 absl::optional<uint32_t> fraction_per_million;
77 bool operator==(const Matchers& other) const {
78 return (path_matcher == other.path_matcher &&
79 header_matchers == other.header_matchers &&
80 fraction_per_million == other.fraction_per_million);
82 std::string ToString() const;
87 // Action for this route.
88 // TODO(roth): When we can use absl::variant<>, consider using that
89 // here, to enforce the fact that only one of the two fields can be set.
90 std::string cluster_name;
91 struct ClusterWeight {
94 bool operator==(const ClusterWeight& other) const {
95 return (name == other.name && weight == other.weight);
97 std::string ToString() const;
99 std::vector<ClusterWeight> weighted_clusters;
100 // Storing the timeout duration from route action:
101 // RouteAction.max_stream_duration.grpc_timeout_header_max or
102 // RouteAction.max_stream_duration.max_stream_duration if the former is
104 absl::optional<Duration> max_stream_duration;
106 bool operator==(const Route& other) const {
107 return (matchers == other.matchers &&
108 cluster_name == other.cluster_name &&
109 weighted_clusters == other.weighted_clusters &&
110 max_stream_duration == other.max_stream_duration);
112 std::string ToString() const;
117 std::vector<std::string> domains;
118 std::vector<Route> routes;
120 bool operator==(const VirtualHost& other) const {
121 return domains == other.domains && routes == other.routes;
125 std::vector<VirtualHost> virtual_hosts;
127 bool operator==(const RdsUpdate& other) const {
128 return virtual_hosts == other.virtual_hosts;
130 std::string ToString() const;
131 VirtualHost* FindVirtualHostForDomain(const std::string& domain);
134 struct CommonTlsContext {
135 struct CertificateValidationContext {
136 std::vector<StringMatcher> match_subject_alt_names;
138 bool operator==(const CertificateValidationContext& other) const {
139 return match_subject_alt_names == other.match_subject_alt_names;
142 std::string ToString() const;
146 struct CertificateProviderInstance {
147 std::string instance_name;
148 std::string certificate_name;
150 bool operator==(const CertificateProviderInstance& other) const {
151 return instance_name == other.instance_name &&
152 certificate_name == other.certificate_name;
155 std::string ToString() const;
159 struct CombinedCertificateValidationContext {
160 CertificateValidationContext default_validation_context;
161 CertificateProviderInstance
162 validation_context_certificate_provider_instance;
164 bool operator==(const CombinedCertificateValidationContext& other) const {
165 return default_validation_context == other.default_validation_context &&
166 validation_context_certificate_provider_instance ==
167 other.validation_context_certificate_provider_instance;
170 std::string ToString() const;
174 CertificateProviderInstance tls_certificate_certificate_provider_instance;
175 CombinedCertificateValidationContext combined_validation_context;
177 bool operator==(const CommonTlsContext& other) const {
178 return tls_certificate_certificate_provider_instance ==
179 other.tls_certificate_certificate_provider_instance &&
180 combined_validation_context == other.combined_validation_context;
183 std::string ToString() const;
187 struct DownstreamTlsContext {
188 CommonTlsContext common_tls_context;
189 bool require_client_certificate = false;
191 bool operator==(const DownstreamTlsContext& other) const {
192 return common_tls_context == other.common_tls_context &&
193 require_client_certificate == other.require_client_certificate;
196 std::string ToString() const;
200 // TODO(roth): When we can use absl::variant<>, consider using that
201 // here, to enforce the fact that only one of the two fields can be set.
203 enum class ListenerType {
207 DownstreamTlsContext downstream_tls_context;
208 // The name to use in the RDS request.
209 std::string route_config_name;
210 // Storing the Http Connection Manager Common Http Protocol Option
211 // max_stream_duration
212 Duration http_max_stream_duration;
213 // The RouteConfiguration to use for this listener.
214 // Present only if it is inlined in the LDS response.
215 absl::optional<RdsUpdate> rds_update;
217 bool operator==(const LdsUpdate& other) const {
218 return downstream_tls_context == other.downstream_tls_context &&
219 route_config_name == other.route_config_name &&
220 rds_update == other.rds_update &&
221 http_max_stream_duration == other.http_max_stream_duration;
224 std::string ToString() const;
227 using LdsUpdateMap = std::map<std::string /*server_name*/, LdsUpdate>;
229 using RdsUpdateMap = std::map<std::string /*route_config_name*/, RdsUpdate>;
232 enum ClusterType { EDS, LOGICAL_DNS, AGGREGATE };
233 ClusterType cluster_type;
234 // For cluster type EDS.
235 // The name to use in the EDS request.
236 // If empty, the cluster name will be used.
237 std::string eds_service_name;
238 // Tls Context used by clients
239 CommonTlsContext common_tls_context;
240 // The LRS server to use for load reporting.
241 // If not set, load reporting will be disabled.
242 // If set to the empty string, will use the same server we obtained the CDS
244 absl::optional<std::string> lrs_load_reporting_server_name;
245 // The LB policy to use (e.g., "ROUND_ROBIN" or "RING_HASH").
246 std::string lb_policy;
247 // Used for RING_HASH LB policy only.
248 uint64_t min_ring_size = 1024;
249 uint64_t max_ring_size = 8388608;
250 enum HashFunction { XX_HASH, MURMUR_HASH_2 };
251 HashFunction hash_function;
252 // Maximum number of outstanding requests can be made to the upstream
254 uint32_t max_concurrent_requests = 1024;
255 // For cluster type AGGREGATE.
256 // The prioritized list of cluster names.
257 std::vector<std::string> prioritized_cluster_names;
259 bool operator==(const CdsUpdate& other) const {
260 return cluster_type == other.cluster_type &&
261 eds_service_name == other.eds_service_name &&
262 common_tls_context == other.common_tls_context &&
263 lrs_load_reporting_server_name ==
264 other.lrs_load_reporting_server_name &&
265 prioritized_cluster_names == other.prioritized_cluster_names &&
266 max_concurrent_requests == other.max_concurrent_requests;
269 std::string ToString() const;
272 using CdsUpdateMap = std::map<std::string /*cluster_name*/, CdsUpdate>;
277 RefCountedPtr<XdsLocalityName> name;
279 ServerAddressList endpoints;
281 bool operator==(const Locality& other) const {
282 return *name == *other.name && lb_weight == other.lb_weight &&
283 endpoints == other.endpoints;
285 bool operator!=(const Locality& other) const {
286 return !(*this == other);
288 std::string ToString() const;
291 std::map<XdsLocalityName*, Locality, XdsLocalityName::Less> localities;
293 bool operator==(const Priority& other) const;
294 std::string ToString() const;
296 using PriorityList = absl::InlinedVector<Priority, 2>;
298 // There are two phases of accessing this class's content:
299 // 1. to initialize in the control plane combiner;
300 // 2. to use in the data plane combiner.
301 // So no additional synchronization is needed.
302 class DropConfig : public RefCounted<DropConfig> {
304 struct DropCategory {
305 bool operator==(const DropCategory& other) const {
306 return name == other.name &&
307 parts_per_million == other.parts_per_million;
311 const uint32_t parts_per_million;
314 using DropCategoryList = absl::InlinedVector<DropCategory, 2>;
316 void AddCategory(std::string name, uint32_t parts_per_million) {
317 drop_category_list_.emplace_back(
318 DropCategory{std::move(name), parts_per_million});
319 if (parts_per_million == 1000000) drop_all_ = true;
322 // The only method invoked from outside the WorkSerializer (used in
324 bool ShouldDrop(const std::string** category_name) const;
326 const DropCategoryList& drop_category_list() const {
327 return drop_category_list_;
330 bool drop_all() const { return drop_all_; }
332 bool operator==(const DropConfig& other) const {
333 return drop_category_list_ == other.drop_category_list_;
335 bool operator!=(const DropConfig& other) const {
336 return !(*this == other);
339 std::string ToString() const;
342 DropCategoryList drop_category_list_;
343 bool drop_all_ = false;
346 PriorityList priorities;
347 RefCountedPtr<DropConfig> drop_config;
349 bool operator==(const EdsUpdate& other) const {
350 return priorities == other.priorities &&
351 *drop_config == *other.drop_config;
353 std::string ToString() const;
356 using EdsUpdateMap = std::map<std::string /*eds_service_name*/, EdsUpdate>;
358 struct ClusterLoadReport {
359 XdsClusterDropStats::Snapshot dropped_requests;
360 std::map<RefCountedPtr<XdsLocalityName>, XdsClusterLocalityStats::Snapshot,
361 XdsLocalityName::Less>
363 grpc_millis load_report_interval;
365 using ClusterLoadReportMap = std::map<
366 std::pair<std::string /*cluster_name*/, std::string /*eds_service_name*/>,
369 XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node);
371 // Creates an ADS request.
372 // Takes ownership of \a error.
373 grpc_slice CreateAdsRequest(const XdsBootstrap::XdsServer& server,
374 const std::string& type_url,
375 const std::set<absl::string_view>& resource_names,
376 const std::string& version,
377 const std::string& nonce, grpc_error* error,
380 // Parses an ADS response.
381 // If the response can't be parsed at the top level, the resulting
382 // type_url will be empty.
383 // If there is any other type of validation error, the parse_error
384 // field will be set to something other than GRPC_ERROR_NONE and the
385 // resource_names_failed field will be populated.
386 // Otherwise, one of the *_update_map fields will be populated, based
387 // on the type_url field.
388 struct AdsParseResult {
389 grpc_error* parse_error = GRPC_ERROR_NONE;
392 std::string type_url;
393 LdsUpdateMap lds_update_map;
394 RdsUpdateMap rds_update_map;
395 CdsUpdateMap cds_update_map;
396 EdsUpdateMap eds_update_map;
397 std::set<std::string> resource_names_failed;
399 AdsParseResult ParseAdsResponse(
400 const grpc_slice& encoded_response,
401 const std::set<absl::string_view>& expected_listener_names,
402 const std::set<absl::string_view>& expected_route_configuration_names,
403 const std::set<absl::string_view>& expected_cluster_names,
404 const std::set<absl::string_view>& expected_eds_service_names);
406 // Creates an initial LRS request.
407 grpc_slice CreateLrsInitialRequest(const XdsBootstrap::XdsServer& server);
409 // Creates an LRS request sending a client-side load report.
410 grpc_slice CreateLrsRequest(ClusterLoadReportMap cluster_load_report_map);
412 // Parses the LRS response and returns \a
413 // load_reporting_interval for client-side load reporting. If there is any
414 // error, the output config is invalid.
415 grpc_error* ParseLrsResponse(const grpc_slice& encoded_response,
416 bool* send_all_clusters,
417 std::set<std::string>* cluster_names,
418 grpc_millis* load_reporting_interval);
423 const XdsBootstrap::Node* node_; // Do not own.
424 upb::SymbolTable symtab_;
425 const std::string build_version_;
426 const std::string user_agent_name_;
429 } // namespace grpc_core
431 #endif /* GRPC_CORE_EXT_XDS_XDS_API_H */