1 // 2 // Copyright 2019 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef GRPC_SRC_CORE_RESOLVER_XDS_XDS_DEPENDENCY_MANAGER_H 18 #define GRPC_SRC_CORE_RESOLVER_XDS_XDS_DEPENDENCY_MANAGER_H 19 20 #include "absl/container/flat_hash_map.h" 21 #include "absl/container/flat_hash_set.h" 22 #include "absl/strings/string_view.h" 23 #include "src/core/resolver/resolver.h" 24 #include "src/core/resolver/xds/xds_config.h" 25 #include "src/core/util/ref_counted.h" 26 #include "src/core/xds/grpc/xds_client_grpc.h" 27 #include "src/core/xds/grpc/xds_cluster.h" 28 #include "src/core/xds/grpc/xds_endpoint.h" 29 #include "src/core/xds/grpc/xds_listener.h" 30 #include "src/core/xds/grpc/xds_route_config.h" 31 32 namespace grpc_core { 33 34 // Watches all xDS resources and handles dependencies between them. 35 // Reports updates only when all necessary resources have been obtained. 36 class XdsDependencyManager final : public RefCounted<XdsDependencyManager>, 37 public Orphanable { 38 public: 39 class Watcher { 40 public: 41 virtual ~Watcher() = default; 42 43 virtual void OnUpdate( 44 absl::StatusOr<RefCountedPtr<const XdsConfig>> config) = 0; 45 }; 46 47 class ClusterSubscription final : public DualRefCounted<ClusterSubscription> { 48 public: ClusterSubscription(absl::string_view cluster_name,RefCountedPtr<XdsDependencyManager> dependency_mgr)49 ClusterSubscription(absl::string_view cluster_name, 50 RefCountedPtr<XdsDependencyManager> dependency_mgr) 51 : cluster_name_(cluster_name), 52 dependency_mgr_(std::move(dependency_mgr)) {} 53 cluster_name()54 absl::string_view cluster_name() const { return cluster_name_; } 55 56 private: 57 void Orphaned() override; 58 59 std::string cluster_name_; 60 RefCountedPtr<XdsDependencyManager> dependency_mgr_; 61 }; 62 63 XdsDependencyManager(RefCountedPtr<GrpcXdsClient> xds_client, 64 std::shared_ptr<WorkSerializer> work_serializer, 65 std::unique_ptr<Watcher> watcher, 66 std::string data_plane_authority, 67 std::string listener_resource_name, ChannelArgs args, 68 grpc_pollset_set* interested_parties); 69 70 void Orphan() override; 71 72 // Gets an external cluster subscription. This allows us to include 73 // clusters in the config that are referenced by something other than 74 // the route config (e.g., RLS). The cluster will be included in the 75 // config as long as the returned object is still referenced. 76 RefCountedPtr<ClusterSubscription> GetClusterSubscription( 77 absl::string_view cluster_name); 78 79 void RequestReresolution(); 80 81 void ResetBackoff(); 82 ChannelArgName()83 static absl::string_view ChannelArgName() { 84 return GRPC_ARG_NO_SUBCHANNEL_PREFIX "xds_dependency_manager"; 85 } ChannelArgsCompare(const XdsDependencyManager * a,const XdsDependencyManager * b)86 static int ChannelArgsCompare(const XdsDependencyManager* a, 87 const XdsDependencyManager* b) { 88 return QsortCompare(a, b); 89 } 90 91 private: 92 class ListenerWatcher; 93 class RouteConfigWatcher; 94 class ClusterWatcher; 95 class EndpointWatcher; 96 97 class DnsResultHandler; 98 99 struct ClusterWatcherState { 100 // Pointer to watcher, to be used when cancelling. 101 // Not owned, so do not dereference. 102 ClusterWatcher* watcher = nullptr; 103 // Most recent update obtained from this watcher. 104 absl::StatusOr<std::shared_ptr<const XdsClusterResource>> update = nullptr; 105 // Ambient error. 106 std::string resolution_note; 107 }; 108 109 struct EndpointConfig { 110 // If there was an error, update will be null and resolution_note 111 // will be non-empty. 112 std::shared_ptr<const XdsEndpointResource> endpoints; 113 std::string resolution_note; 114 }; 115 116 struct EndpointWatcherState { 117 // Pointer to watcher, to be used when cancelling. 118 // Not owned, so do not dereference. 119 EndpointWatcher* watcher = nullptr; 120 // Most recent update obtained from this watcher. 121 EndpointConfig update; 122 }; 123 124 struct DnsState { 125 OrphanablePtr<Resolver> resolver; 126 // Most recent result from the resolver. 127 EndpointConfig update; 128 }; 129 130 // Event handlers. 131 void OnListenerUpdate( 132 absl::StatusOr<std::shared_ptr<const XdsListenerResource>> listener); 133 void OnListenerAmbientError(absl::Status status); 134 135 void OnRouteConfigUpdate( 136 const std::string& name, 137 absl::StatusOr<std::shared_ptr<const XdsRouteConfigResource>> 138 route_config); 139 void OnRouteConfigAmbientError(std::string name, absl::Status status); 140 141 void OnClusterUpdate( 142 const std::string& name, 143 absl::StatusOr<std::shared_ptr<const XdsClusterResource>> cluster); 144 void OnClusterAmbientError(const std::string& name, absl::Status status); 145 146 void OnEndpointUpdate( 147 const std::string& name, 148 absl::StatusOr<std::shared_ptr<const XdsEndpointResource>> endpoint); 149 void OnEndpointAmbientError(const std::string& name, absl::Status status); 150 151 void OnDnsResult(const std::string& dns_name, Resolver::Result result); 152 void PopulateDnsUpdate(const std::string& dns_name, Resolver::Result result, 153 DnsState* dns_state); 154 155 // Starts CDS and EDS/DNS watches for the specified cluster if needed. 156 // Adds an entry to cluster_config_map, which will contain the cluster 157 // data if the data is available. 158 // For each EDS cluster, adds the EDS resource to eds_resources_seen. 159 // For each Logical DNS cluster, adds the DNS hostname to dns_names_seen. 160 // For aggregate clusters, calls itself recursively. If leaf_clusters is 161 // non-null, populates it with a list of leaf clusters, or an error if 162 // max depth is exceeded. 163 // Returns true if all resources have been obtained. 164 bool PopulateClusterConfigMap( 165 absl::string_view name, int depth, 166 absl::flat_hash_map<std::string, 167 absl::StatusOr<XdsConfig::ClusterConfig>>* 168 cluster_config_map, 169 std::set<absl::string_view>* eds_resources_seen, 170 std::set<absl::string_view>* dns_names_seen, 171 absl::StatusOr<std::vector<absl::string_view>>* leaf_clusters = nullptr); 172 173 // Called when an external cluster subscription is unreffed. 174 void OnClusterSubscriptionUnref(absl::string_view cluster_name, 175 ClusterSubscription* subscription); 176 177 // Checks whether all necessary resources have been obtained, and if 178 // so reports an update to the watcher. 179 void MaybeReportUpdate(); 180 181 void ReportError(absl::string_view resource_type, 182 absl::string_view resource_name, absl::string_view error); 183 184 // Parameters passed into ctor. 185 RefCountedPtr<GrpcXdsClient> xds_client_; 186 std::shared_ptr<WorkSerializer> work_serializer_; 187 std::unique_ptr<Watcher> watcher_; 188 const std::string data_plane_authority_; 189 const std::string listener_resource_name_; 190 ChannelArgs args_; 191 grpc_pollset_set* interested_parties_; 192 193 // Listener state. 194 ListenerWatcher* listener_watcher_ = nullptr; 195 std::shared_ptr<const XdsListenerResource> current_listener_; 196 std::string route_config_name_; 197 std::string lds_resolution_note_; 198 199 // RouteConfig state. 200 RouteConfigWatcher* route_config_watcher_ = nullptr; 201 std::shared_ptr<const XdsRouteConfigResource> current_route_config_; 202 const XdsRouteConfigResource::VirtualHost* current_virtual_host_ = nullptr; 203 absl::flat_hash_set<absl::string_view> clusters_from_route_config_; 204 std::string rds_resolution_note_; 205 206 // Cluster state. 207 absl::flat_hash_map<std::string, ClusterWatcherState> cluster_watchers_; 208 absl::flat_hash_map<absl::string_view, WeakRefCountedPtr<ClusterSubscription>> 209 cluster_subscriptions_; 210 211 // Endpoint state. 212 absl::flat_hash_map<std::string, EndpointWatcherState> endpoint_watchers_; 213 absl::flat_hash_map<std::string, DnsState> dns_resolvers_; 214 }; 215 216 } // namespace grpc_core 217 218 #endif // GRPC_SRC_CORE_RESOLVER_XDS_XDS_DEPENDENCY_MANAGER_H 219