• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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