summaryrefslogtreecommitdiff
path: root/grpc/src/core/ext/xds/xds_api.h
diff options
context:
space:
mode:
Diffstat (limited to 'grpc/src/core/ext/xds/xds_api.h')
-rw-r--r--grpc/src/core/ext/xds/xds_api.h450
1 files changed, 326 insertions, 124 deletions
diff --git a/grpc/src/core/ext/xds/xds_api.h b/grpc/src/core/ext/xds/xds_api.h
index f2a67072..e7bf1cd1 100644
--- a/grpc/src/core/ext/xds/xds_api.h
+++ b/grpc/src/core/ext/xds/xds_api.h
@@ -33,9 +33,12 @@
#include <grpc/slice_buffer.h>
+#include "envoy/admin/v3/config_dump.upb.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/xds/xds_bootstrap.h"
#include "src/core/ext/xds/xds_client_stats.h"
+#include "src/core/ext/xds/xds_http_filters.h"
+#include "src/core/lib/matchers/matchers.h"
namespace grpc_core {
@@ -57,76 +60,58 @@ class XdsApi {
int64_t seconds = 0;
int32_t nanos = 0;
bool operator==(const Duration& other) const {
- return (seconds == other.seconds && nanos == other.nanos);
+ return seconds == other.seconds && nanos == other.nanos;
}
std::string ToString() const {
return absl::StrFormat("Duration seconds: %ld, nanos %d", seconds, nanos);
}
};
+ using TypedPerFilterConfig =
+ std::map<std::string, XdsHttpFilterImpl::FilterConfig>;
+
// TODO(donnadionne): When we can use absl::variant<>, consider using that
// for: PathMatcher, HeaderMatcher, cluster_name and weighted_clusters
struct Route {
// Matchers for this route.
struct Matchers {
- struct PathMatcher {
- enum class PathMatcherType {
- PATH, // path stored in string_matcher field
- PREFIX, // prefix stored in string_matcher field
- REGEX, // regex stored in regex_matcher field
- };
- PathMatcherType type;
- std::string string_matcher;
- std::unique_ptr<RE2> regex_matcher;
- bool case_sensitive = true;
-
- PathMatcher() = default;
- PathMatcher(const PathMatcher& other);
- PathMatcher& operator=(const PathMatcher& other);
- bool operator==(const PathMatcher& other) const;
- std::string ToString() const;
- };
-
- struct HeaderMatcher {
- enum class HeaderMatcherType {
- EXACT, // value stored in string_matcher field
- REGEX, // uses regex_match field
- RANGE, // uses range_start and range_end fields
- PRESENT, // uses present_match field
- PREFIX, // prefix stored in string_matcher field
- SUFFIX, // suffix stored in string_matcher field
- };
- std::string name;
- HeaderMatcherType type;
- int64_t range_start;
- int64_t range_end;
- std::string string_matcher;
- std::unique_ptr<RE2> regex_match;
- bool present_match;
- // invert_match field may or may not exisit, so initialize it to
- // false.
- bool invert_match = false;
-
- HeaderMatcher() = default;
- HeaderMatcher(const HeaderMatcher& other);
- HeaderMatcher& operator=(const HeaderMatcher& other);
- bool operator==(const HeaderMatcher& other) const;
- std::string ToString() const;
- };
-
- PathMatcher path_matcher;
+ StringMatcher path_matcher;
std::vector<HeaderMatcher> header_matchers;
absl::optional<uint32_t> fraction_per_million;
bool operator==(const Matchers& other) const {
- return (path_matcher == other.path_matcher &&
- header_matchers == other.header_matchers &&
- fraction_per_million == other.fraction_per_million);
+ return path_matcher == other.path_matcher &&
+ header_matchers == other.header_matchers &&
+ fraction_per_million == other.fraction_per_million;
}
std::string ToString() const;
};
+ struct HashPolicy {
+ enum Type { HEADER, CHANNEL_ID };
+ Type type;
+ bool terminal = false;
+ // Fields used for type HEADER.
+ std::string header_name;
+ std::unique_ptr<RE2> regex = nullptr;
+ std::string regex_substitution;
+
+ HashPolicy() {}
+
+ // Copyable.
+ HashPolicy(const HashPolicy& other);
+ HashPolicy& operator=(const HashPolicy& other);
+
+ // Moveable.
+ HashPolicy(HashPolicy&& other) noexcept;
+ HashPolicy& operator=(HashPolicy&& other) noexcept;
+
+ bool operator==(const HashPolicy& other) const;
+ std::string ToString() const;
+ };
+
Matchers matchers;
+ std::vector<HashPolicy> hash_policies;
// Action for this route.
// TODO(roth): When we can use absl::variant<>, consider using that
@@ -135,8 +120,11 @@ class XdsApi {
struct ClusterWeight {
std::string name;
uint32_t weight;
+ TypedPerFilterConfig typed_per_filter_config;
+
bool operator==(const ClusterWeight& other) const {
- return (name == other.name && weight == other.weight);
+ return name == other.name && weight == other.weight &&
+ typed_per_filter_config == other.typed_per_filter_config;
}
std::string ToString() const;
};
@@ -147,11 +135,13 @@ class XdsApi {
// not set.
absl::optional<Duration> max_stream_duration;
+ TypedPerFilterConfig typed_per_filter_config;
+
bool operator==(const Route& other) const {
- return (matchers == other.matchers &&
- cluster_name == other.cluster_name &&
- weighted_clusters == other.weighted_clusters &&
- max_stream_duration == other.max_stream_duration);
+ return matchers == other.matchers && cluster_name == other.cluster_name &&
+ weighted_clusters == other.weighted_clusters &&
+ max_stream_duration == other.max_stream_duration &&
+ typed_per_filter_config == other.typed_per_filter_config;
}
std::string ToString() const;
};
@@ -160,9 +150,11 @@ class XdsApi {
struct VirtualHost {
std::vector<std::string> domains;
std::vector<Route> routes;
+ TypedPerFilterConfig typed_per_filter_config;
bool operator==(const VirtualHost& other) const {
- return domains == other.domains && routes == other.routes;
+ return domains == other.domains && routes == other.routes &&
+ typed_per_filter_config == other.typed_per_filter_config;
}
};
@@ -175,42 +167,6 @@ class XdsApi {
VirtualHost* FindVirtualHostForDomain(const std::string& domain);
};
- class StringMatcher {
- public:
- enum class StringMatcherType {
- EXACT, // value stored in string_matcher_ field
- PREFIX, // value stored in string_matcher_ field
- SUFFIX, // value stored in string_matcher_ field
- SAFE_REGEX, // pattern stored in regex_matcher_ field
- CONTAINS, // value stored in string_matcher_ field
- };
-
- StringMatcher() = default;
- StringMatcher(const StringMatcher& other);
- StringMatcher(StringMatcherType type, const std::string& matcher,
- bool ignore_case = false);
- StringMatcher& operator=(const StringMatcher& other);
- bool operator==(const StringMatcher& other) const;
-
- bool Match(absl::string_view value) const;
-
- std::string ToString() const;
-
- StringMatcherType type() const { return type_; }
-
- // Valid for EXACT, PREFIX, SUFFIX and CONTAINS
- const std::string& string_matcher() const { return string_matcher_; }
-
- // Valid for SAFE_REGEX
- RE2* regex_matcher() const { return regex_matcher_.get(); }
-
- private:
- StringMatcherType type_ = StringMatcherType::EXACT;
- std::string string_matcher_;
- std::unique_ptr<RE2> regex_matcher_;
- bool ignore_case_ = false;
- };
-
struct CommonTlsContext {
struct CertificateValidationContext {
std::vector<StringMatcher> match_subject_alt_names;
@@ -264,30 +220,182 @@ class XdsApi {
bool Empty() const;
};
+ struct DownstreamTlsContext {
+ CommonTlsContext common_tls_context;
+ bool require_client_certificate = false;
+
+ bool operator==(const DownstreamTlsContext& other) const {
+ return common_tls_context == other.common_tls_context &&
+ require_client_certificate == other.require_client_certificate;
+ }
+
+ std::string ToString() const;
+ bool Empty() const;
+ };
+
// TODO(roth): When we can use absl::variant<>, consider using that
// here, to enforce the fact that only one of the two fields can be set.
struct LdsUpdate {
- // The name to use in the RDS request.
- std::string route_config_name;
- // Storing the Http Connection Manager Common Http Protocol Option
- // max_stream_duration
- Duration http_max_stream_duration;
- // The RouteConfiguration to use for this listener.
- // Present only if it is inlined in the LDS response.
- absl::optional<RdsUpdate> rds_update;
+ enum class ListenerType {
+ kTcpListener = 0,
+ kHttpApiListener,
+ } type;
+
+ struct HttpConnectionManager {
+ // The name to use in the RDS request.
+ std::string route_config_name;
+ // Storing the Http Connection Manager Common Http Protocol Option
+ // max_stream_duration
+ Duration http_max_stream_duration;
+ // The RouteConfiguration to use for this listener.
+ // Present only if it is inlined in the LDS response.
+ absl::optional<RdsUpdate> rds_update;
+
+ struct HttpFilter {
+ std::string name;
+ XdsHttpFilterImpl::FilterConfig config;
+
+ bool operator==(const HttpFilter& other) const {
+ return name == other.name && config == other.config;
+ }
+
+ std::string ToString() const;
+ };
+ std::vector<HttpFilter> http_filters;
+
+ bool operator==(const HttpConnectionManager& other) const {
+ return route_config_name == other.route_config_name &&
+ http_max_stream_duration == other.http_max_stream_duration &&
+ rds_update == other.rds_update &&
+ http_filters == other.http_filters;
+ }
+
+ std::string ToString() const;
+ };
+
+ // Populated for type=kHttpApiListener.
+ HttpConnectionManager http_connection_manager;
+
+ // Populated for type=kTcpListener.
+ // host:port listening_address set when type is kTcpListener
+ std::string address;
+
+ struct FilterChainData {
+ DownstreamTlsContext downstream_tls_context;
+ // This is in principle the filter list.
+ // We currently require exactly one filter, which is the HCM.
+ HttpConnectionManager http_connection_manager;
+
+ bool operator==(const FilterChainData& other) const {
+ return downstream_tls_context == other.downstream_tls_context &&
+ http_connection_manager == other.http_connection_manager;
+ }
+
+ std::string ToString() const;
+ } filter_chain_data;
+
+ // A multi-level map used to determine which filter chain to use for a given
+ // incoming connection. Determining the right filter chain for a given
+ // connection checks the following properties, in order:
+ // - destination port (never matched, so not present in map)
+ // - destination IP address
+ // - server name (never matched, so not present in map)
+ // - transport protocol (allows only "raw_buffer" or unset, prefers the
+ // former, so only one of those two types is present in map)
+ // - application protocol (never matched, so not present in map)
+ // - connection source type (any, local or external)
+ // - source IP address
+ // - source port
+ // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener_components.proto#config-listener-v3-filterchainmatch
+ // for more details
+ struct FilterChainMap {
+ struct FilterChainDataSharedPtr {
+ std::shared_ptr<FilterChainData> data;
+ bool operator==(const FilterChainDataSharedPtr& other) const {
+ return *data == *other.data;
+ }
+ };
+ struct CidrRange {
+ grpc_resolved_address address;
+ uint32_t prefix_len;
+
+ bool operator==(const CidrRange& other) const {
+ return memcmp(&address, &other.address, sizeof(address)) == 0 &&
+ prefix_len == other.prefix_len;
+ }
+
+ std::string ToString() const;
+ };
+ using SourcePortsMap = std::map<uint16_t, FilterChainDataSharedPtr>;
+ struct SourceIp {
+ absl::optional<CidrRange> prefix_range;
+ SourcePortsMap ports_map;
+
+ bool operator==(const SourceIp& other) const {
+ return prefix_range == other.prefix_range &&
+ ports_map == other.ports_map;
+ }
+ };
+ using SourceIpVector = std::vector<SourceIp>;
+ enum class ConnectionSourceType {
+ kAny = 0,
+ kSameIpOrLoopback,
+ kExternal
+ };
+ using ConnectionSourceTypesArray = std::array<SourceIpVector, 3>;
+ struct DestinationIp {
+ absl::optional<CidrRange> prefix_range;
+ // We always fail match on server name, so those filter chains are not
+ // included here.
+ ConnectionSourceTypesArray source_types_array;
+
+ bool operator==(const DestinationIp& other) const {
+ return prefix_range == other.prefix_range &&
+ source_types_array == other.source_types_array;
+ }
+ };
+ // We always fail match on destination ports map
+ using DestinationIpVector = std::vector<DestinationIp>;
+ DestinationIpVector destination_ip_vector;
+
+ bool operator==(const FilterChainMap& other) const {
+ return destination_ip_vector == other.destination_ip_vector;
+ }
+
+ std::string ToString() const;
+ } filter_chain_map;
+
+ absl::optional<FilterChainData> default_filter_chain;
bool operator==(const LdsUpdate& other) const {
- return route_config_name == other.route_config_name &&
- rds_update == other.rds_update &&
- http_max_stream_duration == other.http_max_stream_duration;
+ return http_connection_manager == other.http_connection_manager &&
+ address == other.address &&
+ filter_chain_map == other.filter_chain_map &&
+ default_filter_chain == other.default_filter_chain;
}
+
+ std::string ToString() const;
};
- using LdsUpdateMap = std::map<std::string /*server_name*/, LdsUpdate>;
+ struct LdsResourceData {
+ LdsUpdate resource;
+ std::string serialized_proto;
+ };
- using RdsUpdateMap = std::map<std::string /*route_config_name*/, RdsUpdate>;
+ using LdsUpdateMap = std::map<std::string /*server_name*/, LdsResourceData>;
+
+ struct RdsResourceData {
+ RdsUpdate resource;
+ std::string serialized_proto;
+ };
+
+ using RdsUpdateMap =
+ std::map<std::string /*route_config_name*/, RdsResourceData>;
struct CdsUpdate {
+ enum ClusterType { EDS, LOGICAL_DNS, AGGREGATE };
+ ClusterType cluster_type;
+ // For cluster type EDS.
// The name to use in the EDS request.
// If empty, the cluster name will be used.
std::string eds_service_name;
@@ -298,22 +406,39 @@ class XdsApi {
// If set to the empty string, will use the same server we obtained the CDS
// data from.
absl::optional<std::string> lrs_load_reporting_server_name;
+ // The LB policy to use (e.g., "ROUND_ROBIN" or "RING_HASH").
+ std::string lb_policy;
+ // Used for RING_HASH LB policy only.
+ uint64_t min_ring_size = 1024;
+ uint64_t max_ring_size = 8388608;
+ enum HashFunction { XX_HASH, MURMUR_HASH_2 };
+ HashFunction hash_function;
// Maximum number of outstanding requests can be made to the upstream
// cluster.
uint32_t max_concurrent_requests = 1024;
+ // For cluster type AGGREGATE.
+ // The prioritized list of cluster names.
+ std::vector<std::string> prioritized_cluster_names;
bool operator==(const CdsUpdate& other) const {
- return eds_service_name == other.eds_service_name &&
+ return cluster_type == other.cluster_type &&
+ eds_service_name == other.eds_service_name &&
common_tls_context == other.common_tls_context &&
lrs_load_reporting_server_name ==
other.lrs_load_reporting_server_name &&
+ prioritized_cluster_names == other.prioritized_cluster_names &&
max_concurrent_requests == other.max_concurrent_requests;
}
std::string ToString() const;
};
- using CdsUpdateMap = std::map<std::string /*cluster_name*/, CdsUpdate>;
+ struct CdsResourceData {
+ CdsUpdate resource;
+ std::string serialized_proto;
+ };
+
+ using CdsUpdateMap = std::map<std::string /*cluster_name*/, CdsResourceData>;
struct EdsUpdate {
struct Priority {
@@ -397,7 +522,13 @@ class XdsApi {
std::string ToString() const;
};
- using EdsUpdateMap = std::map<std::string /*eds_service_name*/, EdsUpdate>;
+ struct EdsResourceData {
+ EdsUpdate resource;
+ std::string serialized_proto;
+ };
+
+ using EdsUpdateMap =
+ std::map<std::string /*eds_service_name*/, EdsResourceData>;
struct ClusterLoadReport {
XdsClusterDropStats::Snapshot dropped_requests;
@@ -410,22 +541,75 @@ class XdsApi {
std::pair<std::string /*cluster_name*/, std::string /*eds_service_name*/>,
ClusterLoadReport>;
- XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node);
+ // The metadata of the xDS resource; used by the xDS config dump.
+ struct ResourceMetadata {
+ // Resource status from the view of a xDS client, which tells the
+ // synchronization status between the xDS client and the xDS server.
+ enum ClientResourceStatus {
+ // Client requested this resource but hasn't received any update from
+ // management server. The client will not fail requests, but will queue
+ // them
+ // until update arrives or the client times out waiting for the resource.
+ REQUESTED = 1,
+ // This resource has been requested by the client but has either not been
+ // delivered by the server or was previously delivered by the server and
+ // then subsequently removed from resources provided by the server.
+ DOES_NOT_EXIST,
+ // Client received this resource and replied with ACK.
+ ACKED,
+ // Client received this resource and replied with NACK.
+ NACKED
+ };
- // Creates an ADS request.
- // Takes ownership of \a error.
- grpc_slice CreateAdsRequest(const XdsBootstrap::XdsServer& server,
- const std::string& type_url,
- const std::set<absl::string_view>& resource_names,
- const std::string& version,
- const std::string& nonce, grpc_error* error,
- bool populate_node);
+ // The client status of this resource.
+ ClientResourceStatus client_status = REQUESTED;
+ // The serialized bytes of the last successfully updated raw xDS resource.
+ std::string serialized_proto;
+ // The timestamp when the resource was last successfully updated.
+ grpc_millis update_time = 0;
+ // The last successfully updated version of the resource.
+ std::string version;
+ // The rejected version string of the last failed update attempt.
+ std::string failed_version;
+ // Details about the last failed update attempt.
+ std::string failed_details;
+ // Timestamp of the last failed update attempt.
+ grpc_millis failed_update_time = 0;
+ };
+ using ResourceMetadataMap =
+ std::map<absl::string_view /*resource_name*/, const ResourceMetadata*>;
+ struct ResourceTypeMetadata {
+ absl::string_view version;
+ ResourceMetadataMap resource_metadata_map;
+ };
+ using ResourceTypeMetadataMap =
+ std::map<absl::string_view /*type_url*/, ResourceTypeMetadata>;
+ static_assert(static_cast<ResourceMetadata::ClientResourceStatus>(
+ envoy_admin_v3_REQUESTED) ==
+ ResourceMetadata::ClientResourceStatus::REQUESTED,
+ "");
+ static_assert(static_cast<ResourceMetadata::ClientResourceStatus>(
+ envoy_admin_v3_DOES_NOT_EXIST) ==
+ ResourceMetadata::ClientResourceStatus::DOES_NOT_EXIST,
+ "");
+ static_assert(static_cast<ResourceMetadata::ClientResourceStatus>(
+ envoy_admin_v3_ACKED) ==
+ ResourceMetadata::ClientResourceStatus::ACKED,
+ "");
+ static_assert(static_cast<ResourceMetadata::ClientResourceStatus>(
+ envoy_admin_v3_NACKED) ==
+ ResourceMetadata::ClientResourceStatus::NACKED,
+ "");
- // Parses an ADS response.
// If the response can't be parsed at the top level, the resulting
// type_url will be empty.
+ // If there is any other type of validation error, the parse_error
+ // field will be set to something other than GRPC_ERROR_NONE and the
+ // resource_names_failed field will be populated.
+ // Otherwise, one of the *_update_map fields will be populated, based
+ // on the type_url field.
struct AdsParseResult {
- grpc_error* parse_error = GRPC_ERROR_NONE;
+ grpc_error_handle parse_error = GRPC_ERROR_NONE;
std::string version;
std::string nonce;
std::string type_url;
@@ -433,9 +617,23 @@ class XdsApi {
RdsUpdateMap rds_update_map;
CdsUpdateMap cds_update_map;
EdsUpdateMap eds_update_map;
+ std::set<std::string> resource_names_failed;
};
+
+ XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node);
+
+ // Creates an ADS request.
+ // Takes ownership of \a error.
+ grpc_slice CreateAdsRequest(const XdsBootstrap::XdsServer& server,
+ const std::string& type_url,
+ const std::set<absl::string_view>& resource_names,
+ const std::string& version,
+ const std::string& nonce, grpc_error_handle error,
+ bool populate_node);
+
+ // Parses an ADS response.
AdsParseResult ParseAdsResponse(
- const grpc_slice& encoded_response,
+ const XdsBootstrap::XdsServer& server, const grpc_slice& encoded_response,
const std::set<absl::string_view>& expected_listener_names,
const std::set<absl::string_view>& expected_route_configuration_names,
const std::set<absl::string_view>& expected_cluster_names,
@@ -450,10 +648,14 @@ class XdsApi {
// Parses the LRS response and returns \a
// load_reporting_interval for client-side load reporting. If there is any
// error, the output config is invalid.
- grpc_error* ParseLrsResponse(const grpc_slice& encoded_response,
- bool* send_all_clusters,
- std::set<std::string>* cluster_names,
- grpc_millis* load_reporting_interval);
+ grpc_error_handle ParseLrsResponse(const grpc_slice& encoded_response,
+ bool* send_all_clusters,
+ std::set<std::string>* cluster_names,
+ grpc_millis* load_reporting_interval);
+
+ // Assemble the client config proto message and return the serialized result.
+ std::string AssembleClientConfig(
+ const ResourceTypeMetadataMap& resource_type_metadata_map);
private:
XdsClient* client_;