xds_server_config_fetcher.cc
Go to the documentation of this file.
1 //
2 //
3 // Copyright 2020 gRPC authors.
4 //
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
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17 //
18 
20 
21 #include <string.h>
22 
23 #include <algorithm>
24 #include <array>
25 #include <map>
26 #include <memory>
27 #include <set>
28 #include <string>
29 #include <utility>
30 #include <vector>
31 
32 #include "absl/base/thread_annotations.h"
33 #include "absl/container/inlined_vector.h"
34 #include "absl/status/status.h"
35 #include "absl/status/statusor.h"
36 #include "absl/strings/match.h"
37 #include "absl/strings/numbers.h"
38 #include "absl/strings/str_cat.h"
39 #include "absl/strings/str_join.h"
40 #include "absl/strings/str_replace.h"
41 #include "absl/strings/string_view.h"
42 #include "absl/types/optional.h"
43 #include "absl/types/variant.h"
44 
45 #include <grpc/grpc.h>
46 #include <grpc/grpc_security.h>
48 #include <grpc/slice.h>
49 #include <grpc/status.h>
50 #include <grpc/support/log.h>
51 
94 
95 namespace grpc_core {
96 namespace {
97 
98 TraceFlag grpc_xds_server_config_fetcher_trace(false,
99  "xds_server_config_fetcher");
100 
101 // A server config fetcher that fetches the information for configuring server
102 // listeners from the xDS control plane.
103 class XdsServerConfigFetcher : public grpc_server_config_fetcher {
104  public:
105  XdsServerConfigFetcher(RefCountedPtr<XdsClient> xds_client,
107 
108  void StartWatch(std::string listening_address,
109  std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
110  watcher) override;
111 
112  void CancelWatch(
114 
115  // Return the interested parties from the xds client so that it can be polled.
116  grpc_pollset_set* interested_parties() override {
117  return xds_client_->interested_parties();
118  }
119 
120  private:
121  class ListenerWatcher;
122 
123  const RefCountedPtr<XdsClient> xds_client_;
126  std::map<grpc_server_config_fetcher::WatcherInterface*, ListenerWatcher*>
127  listener_watchers_ ABSL_GUARDED_BY(mu_);
128 };
129 
130 // A watcher implementation for listening on LDS updates from the xDS control
131 // plane. When a good LDS update is received, it creates a
132 // FilterChainMatchManager object that would replace the existing (if any)
133 // FilterChainMatchManager object after all referenced RDS resources are
134 // fetched. Note that a good update also causes the server listener to start
135 // listening if it isn't already. If an error LDS update is received (NACKed
136 // resource, timeouts), the previous good FilterChainMatchManager, if any,
137 // continues to be used. If there isn't any previous good update or if the
138 // update received was a fatal error (resource does not exist), the server
139 // listener is made to stop listening.
140 class XdsServerConfigFetcher::ListenerWatcher
141  : public XdsListenerResourceType::WatcherInterface {
142  public:
143  ListenerWatcher(RefCountedPtr<XdsClient> xds_client,
144  std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
145  server_config_watcher,
146  grpc_server_xds_status_notifier serving_status_notifier,
147  std::string listening_address);
148 
149  void OnResourceChanged(XdsListenerResource listener) override;
150 
151  void OnError(absl::Status status) override;
152 
153  void OnResourceDoesNotExist() override;
154 
155  const std::string& listening_address() const { return listening_address_; }
156 
157  private:
158  class FilterChainMatchManager;
159 
161 
162  // Invoked by FilterChainMatchManager that is done fetching all referenced RDS
163  // resources. If the calling FilterChainMatchManager is the
164  // pending_filter_chain_match_manager_, it is promoted to be the
165  // filter_chain_match_manager_ in use.
166  void PendingFilterChainMatchManagerReady(
167  FilterChainMatchManager* filter_chain_match_manager) {
168  MutexLock lock(&mu_);
169  PendingFilterChainMatchManagerReadyLocked(filter_chain_match_manager);
170  }
171  void PendingFilterChainMatchManagerReadyLocked(
172  FilterChainMatchManager* filter_chain_match_manager)
174 
175  const RefCountedPtr<XdsClient> xds_client_;
176  const std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
180  Mutex mu_;
181  RefCountedPtr<FilterChainMatchManager> filter_chain_match_manager_
183  RefCountedPtr<FilterChainMatchManager> pending_filter_chain_match_manager_
185 };
186 
187 // A connection manager used by the server listener code to inject channel args
188 // to be used for each incoming connection. This implementation chooses the
189 // appropriate filter chain from the xDS Listener resource and injects channel
190 // args that configure the right mTLS certs and cause the right set of HTTP
191 // filters to be injected.
192 class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager
194  public:
195  FilterChainMatchManager(RefCountedPtr<XdsClient> xds_client,
196  XdsListenerResource::FilterChainMap filter_chain_map,
198  default_filter_chain);
199 
200  absl::StatusOr<grpc_channel_args*> UpdateChannelArgsForConnection(
202 
203  void Orphan() override;
204 
205  // Invoked by ListenerWatcher to start fetching referenced RDS resources.
206  void StartRdsWatch(RefCountedPtr<ListenerWatcher> listener_watcher)
208 
209  const XdsListenerResource::FilterChainMap& filter_chain_map() const {
210  return filter_chain_map_;
211  }
212 
214  default_filter_chain() const {
215  return default_filter_chain_;
216  }
217 
218  private:
219  struct CertificateProviders {
220  // We need to save our own refs to the root and instance certificate
221  // providers since the xds certificate provider just stores a ref to their
222  // distributors.
223  RefCountedPtr<grpc_tls_certificate_provider> root;
224  RefCountedPtr<grpc_tls_certificate_provider> instance;
225  RefCountedPtr<XdsCertificateProvider> xds;
226  };
227 
228  class RouteConfigWatcher;
229  struct RdsUpdateState {
230  RouteConfigWatcher* watcher;
232  };
233 
234  class XdsServerConfigSelector;
235  class StaticXdsServerConfigSelectorProvider;
236  class DynamicXdsServerConfigSelectorProvider;
237 
239  CreateOrGetXdsCertificateProviderFromFilterChainData(
240  const XdsListenerResource::FilterChainData* filter_chain);
241 
242  // Helper functions invoked by RouteConfigWatcher when there are updates to
243  // RDS resources.
244  void OnRouteConfigChanged(const std::string& resource_name,
245  XdsRouteConfigResource route_config);
246  void OnError(const std::string& resource_name, absl::Status status);
247  void OnResourceDoesNotExist(const std::string& resource_name);
248 
249  RefCountedPtr<XdsClient> xds_client_;
250  // This ref is only kept around till the FilterChainMatchManager becomes
251  // ready.
252  RefCountedPtr<ListenerWatcher> listener_watcher_;
253  XdsListenerResource::FilterChainMap filter_chain_map_;
255  Mutex mu_;
256  size_t rds_resources_yet_to_fetch_ ABSL_GUARDED_BY(mu_) = 0;
257  std::map<std::string /* resource_name */, RdsUpdateState> rds_map_
259  std::map<const XdsListenerResource::FilterChainData*, CertificateProviders>
260  certificate_providers_map_ ABSL_GUARDED_BY(mu_);
261 };
262 
263 // A watcher implementation for listening on RDS updates referenced to by a
264 // FilterChainMatchManager object. After all referenced RDS resources are
265 // fetched (errors are allowed), the FilterChainMatchManager tries to replace
266 // the current object. The watcher continues to update the referenced RDS
267 // resources so that new XdsServerConfigSelectorProvider objects are created
268 // with the latest updates and new connections do not need to wait for the RDS
269 // resources to be fetched.
270 class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
271  RouteConfigWatcher : public XdsRouteConfigResourceType::WatcherInterface {
272  public:
273  RouteConfigWatcher(
274  std::string resource_name,
275  WeakRefCountedPtr<FilterChainMatchManager> filter_chain_match_manager)
276  : resource_name_(std::move(resource_name)),
277  filter_chain_match_manager_(std::move(filter_chain_match_manager)) {}
278 
279  void OnResourceChanged(XdsRouteConfigResource route_config) override {
280  filter_chain_match_manager_->OnRouteConfigChanged(resource_name_,
281  std::move(route_config));
282  }
283 
284  void OnError(absl::Status status) override {
286  }
287 
288  void OnResourceDoesNotExist() override {
289  filter_chain_match_manager_->OnResourceDoesNotExist(resource_name_);
290  }
291 
292  private:
294  WeakRefCountedPtr<FilterChainMatchManager> filter_chain_match_manager_;
295 };
296 
297 // An implementation of ServerConfigSelector used by
298 // StaticXdsServerConfigSelectorProvider and
299 // DynamicXdsServerConfigSelectorProvider to parse the RDS update and get
300 // per-call configuration based on incoming metadata.
301 class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
302  XdsServerConfigSelector : public ServerConfigSelector {
303  public:
305  XdsRouteConfigResource rds_update,
306  const std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>&
307  http_filters);
308  ~XdsServerConfigSelector() override = default;
309 
310  CallConfig GetCallConfig(grpc_metadata_batch* metadata) override;
311 
312  private:
313  struct VirtualHost {
314  struct Route {
315  // true if an action other than kNonForwardingAction is configured.
317  XdsRouteConfigResource::Route::Matchers matchers;
318  RefCountedPtr<ServiceConfig> method_config;
319  };
320 
321  class RouteListIterator : public XdsRouting::RouteListIterator {
322  public:
323  explicit RouteListIterator(const std::vector<Route>* routes)
324  : routes_(routes) {}
325 
326  size_t Size() const override { return routes_->size(); }
327 
328  const XdsRouteConfigResource::Route::Matchers& GetMatchersForRoute(
329  size_t index) const override {
330  return (*routes_)[index].matchers;
331  }
332 
333  private:
334  const std::vector<Route>* routes_;
335  };
336 
337  std::vector<std::string> domains;
338  std::vector<Route> routes;
339  };
340 
341  class VirtualHostListIterator : public XdsRouting::VirtualHostListIterator {
342  public:
343  explicit VirtualHostListIterator(
344  const std::vector<VirtualHost>* virtual_hosts)
345  : virtual_hosts_(virtual_hosts) {}
346 
347  size_t Size() const override { return virtual_hosts_->size(); }
348 
349  const std::vector<std::string>& GetDomainsForVirtualHost(
350  size_t index) const override {
351  return (*virtual_hosts_)[index].domains;
352  }
353 
354  private:
355  const std::vector<VirtualHost>* virtual_hosts_;
356  };
357 
358  std::vector<VirtualHost> virtual_hosts_;
359 };
360 
361 // An XdsServerConfigSelectorProvider implementation for when the
362 // RouteConfiguration is available inline.
363 class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
364  StaticXdsServerConfigSelectorProvider
365  : public ServerConfigSelectorProvider {
366  public:
367  StaticXdsServerConfigSelectorProvider(
369  std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>
370  http_filters)
371  : static_resource_(std::move(static_resource)),
372  http_filters_(std::move(http_filters)) {}
373 
375  std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
376  watcher) override {
377  GPR_ASSERT(watcher_ == nullptr);
379  if (!static_resource_.ok()) {
380  return static_resource_.status();
381  }
382  return XdsServerConfigSelector::Create(static_resource_.value(),
383  http_filters_);
384  }
385 
386  void Orphan() override {}
387 
388  void CancelWatch() override { watcher_.reset(); }
389 
390  private:
392  std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>
394  std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
396 };
397 
398 // An XdsServerConfigSelectorProvider implementation for when the
399 // RouteConfiguration is to be fetched separately via RDS.
400 class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
401  DynamicXdsServerConfigSelectorProvider
402  : public ServerConfigSelectorProvider {
403  public:
404  DynamicXdsServerConfigSelectorProvider(
405  RefCountedPtr<XdsClient> xds_client, std::string resource_name,
407  std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>
408  http_filters);
409 
410  void Orphan() override;
411 
413  std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
414  watcher) override;
415  void CancelWatch() override;
416 
417  private:
418  class RouteConfigWatcher;
419 
420  void OnRouteConfigChanged(XdsRouteConfigResource rds_update);
422  void OnResourceDoesNotExist();
423 
424  RefCountedPtr<XdsClient> xds_client_;
426  std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>
428  RouteConfigWatcher* route_config_watcher_ = nullptr;
429  Mutex mu_;
430  std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
433 };
434 
435 // A watcher implementation for updating the RDS resource used by
436 // DynamicXdsServerConfigSelectorProvider
437 class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
438  DynamicXdsServerConfigSelectorProvider::RouteConfigWatcher
439  : public XdsRouteConfigResourceType::WatcherInterface {
440  public:
441  explicit RouteConfigWatcher(
442  WeakRefCountedPtr<DynamicXdsServerConfigSelectorProvider> parent)
443  : parent_(std::move(parent)) {}
444 
445  void OnResourceChanged(XdsRouteConfigResource route_config) override {
446  parent_->OnRouteConfigChanged(std::move(route_config));
447  }
448 
449  void OnError(absl::Status status) override { parent_->OnError(status); }
450 
451  void OnResourceDoesNotExist() override { parent_->OnResourceDoesNotExist(); }
452 
453  private:
454  WeakRefCountedPtr<DynamicXdsServerConfigSelectorProvider> parent_;
455 };
456 
457 //
458 // XdsServerConfigFetcher
459 //
460 
461 XdsServerConfigFetcher::XdsServerConfigFetcher(
462  RefCountedPtr<XdsClient> xds_client,
464  : xds_client_(std::move(xds_client)), serving_status_notifier_(notifier) {
465  GPR_ASSERT(xds_client_ != nullptr);
466 }
467 
468 std::string ListenerResourceName(absl::string_view resource_name_template,
469  absl::string_view listening_address) {
471  if (absl::StartsWith(resource_name_template, "xdstp:")) {
472  tmp = URI::PercentEncodePath(listening_address);
473  listening_address = tmp;
474  }
475  return absl::StrReplaceAll(resource_name_template,
476  {{"%s", listening_address}});
477 }
478 
479 void XdsServerConfigFetcher::StartWatch(
480  std::string listening_address,
481  std::unique_ptr<grpc_server_config_fetcher::WatcherInterface> watcher) {
483  auto listener_watcher = MakeRefCounted<ListenerWatcher>(
485  listening_address);
486  auto* listener_watcher_ptr = listener_watcher.get();
487  XdsListenerResourceType::StartWatch(
488  xds_client_.get(),
489  ListenerResourceName(
490  xds_client_->bootstrap().server_listener_resource_name_template(),
491  listening_address),
492  std::move(listener_watcher));
493  MutexLock lock(&mu_);
494  listener_watchers_.emplace(watcher_ptr, listener_watcher_ptr);
495 }
496 
497 void XdsServerConfigFetcher::CancelWatch(
499  MutexLock lock(&mu_);
500  auto it = listener_watchers_.find(watcher);
501  if (it != listener_watchers_.end()) {
502  // Cancel the watch on the listener before erasing
503  XdsListenerResourceType::CancelWatch(
504  xds_client_.get(),
505  ListenerResourceName(
506  xds_client_->bootstrap().server_listener_resource_name_template(),
507  it->second->listening_address()),
508  it->second, false /* delay_unsubscription */);
509  listener_watchers_.erase(it);
510  }
511 }
512 
513 //
514 // XdsServerConfigFetcher::ListenerWatcher
515 //
516 
517 XdsServerConfigFetcher::ListenerWatcher::ListenerWatcher(
518  RefCountedPtr<XdsClient> xds_client,
519  std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
520  server_config_watcher,
521  grpc_server_xds_status_notifier serving_status_notifier,
522  std::string listening_address)
523  : xds_client_(std::move(xds_client)),
524  server_config_watcher_(std::move(server_config_watcher)),
525  serving_status_notifier_(serving_status_notifier),
526  listening_address_(std::move(listening_address)) {}
527 
528 void XdsServerConfigFetcher::ListenerWatcher::OnResourceChanged(
529  XdsListenerResource listener) {
530  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_server_config_fetcher_trace)) {
532  "[ListenerWatcher %p] Received LDS update from xds client %p: %s",
533  this, xds_client_.get(), listener.ToString().c_str());
534  }
535  if (listener.address != listening_address_) {
536  MutexLock lock(&mu_);
537  OnFatalError(absl::FailedPreconditionError(
538  "Address in LDS update does not match listening address"));
539  return;
540  }
541  auto new_filter_chain_match_manager = MakeRefCounted<FilterChainMatchManager>(
542  xds_client_, std::move(listener.filter_chain_map),
543  std::move(listener.default_filter_chain));
544  MutexLock lock(&mu_);
545  if (filter_chain_match_manager_ == nullptr ||
546  !(new_filter_chain_match_manager->filter_chain_map() ==
547  filter_chain_match_manager_->filter_chain_map() &&
548  new_filter_chain_match_manager->default_filter_chain() ==
549  filter_chain_match_manager_->default_filter_chain())) {
550  pending_filter_chain_match_manager_ =
551  std::move(new_filter_chain_match_manager);
552  if (XdsRbacEnabled()) {
553  pending_filter_chain_match_manager_->StartRdsWatch(Ref());
554  } else {
555  PendingFilterChainMatchManagerReadyLocked(
556  pending_filter_chain_match_manager_.get());
557  }
558  }
559 }
560 
562  MutexLock lock(&mu_);
563  if (filter_chain_match_manager_ != nullptr ||
564  pending_filter_chain_match_manager_ != nullptr) {
566  "ListenerWatcher:%p XdsClient reports error: %s for %s; "
567  "ignoring in favor of existing resource",
568  this, status.ToString().c_str(), listening_address_.c_str());
569  } else {
573  {GRPC_STATUS_UNAVAILABLE, status.ToString().c_str()});
574  } else {
576  "ListenerWatcher:%p error obtaining xDS Listener resource: %s; "
577  "not serving on %s",
578  this, status.ToString().c_str(), listening_address_.c_str());
579  }
580  }
581 }
582 
583 void XdsServerConfigFetcher::ListenerWatcher::OnFatalError(
585  pending_filter_chain_match_manager_.reset();
586  if (filter_chain_match_manager_ != nullptr) {
587  // The server has started listening already, so we need to gracefully
588  // stop serving.
589  server_config_watcher_->StopServing();
591  }
595  {static_cast<grpc_status_code>(status.raw_code()),
596  std::string(status.message()).c_str()});
597  } else {
599  "ListenerWatcher:%p Encountered fatal error %s; not serving on %s",
600  this, status.ToString().c_str(), listening_address_.c_str());
601  }
602 }
603 
604 void XdsServerConfigFetcher::ListenerWatcher::OnResourceDoesNotExist() {
605  MutexLock lock(&mu_);
606  OnFatalError(absl::NotFoundError("Requested listener does not exist"));
607 }
608 
609 void XdsServerConfigFetcher::ListenerWatcher::
610  PendingFilterChainMatchManagerReadyLocked(
611  XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager*
612  filter_chain_match_manager) {
613  if (pending_filter_chain_match_manager_ != filter_chain_match_manager) {
614  // This FilterChainMatchManager is no longer the current pending resource.
615  // It should get cleaned up eventually. Ignore this update.
616  return;
617  }
618  // Let the logger know about the update if there was no previous good update.
619  if (filter_chain_match_manager_ == nullptr) {
623  {GRPC_STATUS_OK, ""});
624  } else {
626  "xDS Listener resource obtained; will start serving on %s",
627  listening_address_.c_str());
628  }
629  }
630  // Promote the pending FilterChainMatchManager
631  filter_chain_match_manager_ = std::move(pending_filter_chain_match_manager_);
632  // TODO(yashykt): Right now, the server_config_watcher_ does not invoke
633  // XdsServerConfigFetcher while holding a lock, but that might change in the
634  // future in which case we would want to execute this update outside the
635  // critical region through a WorkSerializer similar to XdsClient.
636  server_config_watcher_->UpdateConnectionManager(filter_chain_match_manager_);
637 }
638 
639 //
640 // XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager
641 //
642 
643 XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
644  FilterChainMatchManager(
645  RefCountedPtr<XdsClient> xds_client,
646  XdsListenerResource::FilterChainMap filter_chain_map,
648  default_filter_chain)
649  : xds_client_(std::move(xds_client)),
650  filter_chain_map_(std::move(filter_chain_map)),
651  default_filter_chain_(std::move(default_filter_chain)) {}
652 
653 void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
654  StartRdsWatch(RefCountedPtr<ListenerWatcher> listener_watcher) {
655  // Get the set of RDS resources to watch on. Also get the set of
656  // FilterChainData so that we can reverse the list of HTTP filters since
657  // received data moves *up* the stack in Core.
658  std::set<std::string> resource_names;
659  std::set<XdsListenerResource::FilterChainData*> filter_chain_data_set;
660  for (const auto& destination_ip : filter_chain_map_.destination_ip_vector) {
661  for (const auto& source_type : destination_ip.source_types_array) {
662  for (const auto& source_ip : source_type) {
663  for (const auto& source_port_pair : source_ip.ports_map) {
664  if (!source_port_pair.second.data->http_connection_manager
665  .route_config_name.empty()) {
666  resource_names.insert(
667  source_port_pair.second.data->http_connection_manager
668  .route_config_name);
669  }
670  filter_chain_data_set.insert(source_port_pair.second.data.get());
671  }
672  }
673  }
674  }
675  if (default_filter_chain_.has_value()) {
676  if (!default_filter_chain_->http_connection_manager.route_config_name
677  .empty()) {
678  resource_names.insert(
679  default_filter_chain_->http_connection_manager.route_config_name);
680  }
681  std::reverse(
682  default_filter_chain_->http_connection_manager.http_filters.begin(),
683  default_filter_chain_->http_connection_manager.http_filters.end());
684  }
685  // Reverse the lists of HTTP filters in all the filter chains
686  for (auto* filter_chain_data : filter_chain_data_set) {
687  std::reverse(
688  filter_chain_data->http_connection_manager.http_filters.begin(),
689  filter_chain_data->http_connection_manager.http_filters.end());
690  }
691  // Start watching on referenced RDS resources
692  struct WatcherToStart {
693  std::string resource_name;
694  RefCountedPtr<RouteConfigWatcher> watcher;
695  };
696  std::vector<WatcherToStart> watchers_to_start;
697  watchers_to_start.reserve(resource_names.size());
698  {
699  MutexLock lock(&mu_);
700  for (const auto& resource_name : resource_names) {
701  ++rds_resources_yet_to_fetch_;
702  auto route_config_watcher =
703  MakeRefCounted<RouteConfigWatcher>(resource_name, WeakRef());
704  rds_map_.emplace(resource_name, RdsUpdateState{route_config_watcher.get(),
705  absl::nullopt});
706  watchers_to_start.push_back(
707  WatcherToStart{resource_name, std::move(route_config_watcher)});
708  }
709  if (rds_resources_yet_to_fetch_ != 0) {
710  listener_watcher_ = std::move(listener_watcher);
711  listener_watcher = nullptr;
712  }
713  }
714  for (auto& watcher_to_start : watchers_to_start) {
715  XdsRouteConfigResourceType::StartWatch(xds_client_.get(),
716  watcher_to_start.resource_name,
717  std::move(watcher_to_start.watcher));
718  }
719  // Promote this filter chain match manager if all referenced resources are
720  // fetched.
721  if (listener_watcher != nullptr) {
722  listener_watcher->PendingFilterChainMatchManagerReadyLocked(this);
723  }
724 }
725 
726 void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
727  Orphan() {
728  MutexLock lock(&mu_);
729  // Cancel the RDS watches to clear up the weak refs
730  for (const auto& entry : rds_map_) {
731  XdsRouteConfigResourceType::CancelWatch(xds_client_.get(), entry.first,
732  entry.second.watcher,
733  false /* delay_unsubscription */);
734  }
735  // Also give up the ref on ListenerWatcher since it won't be needed anymore
736  listener_watcher_.reset();
737 }
738 
740 XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
741  CreateOrGetXdsCertificateProviderFromFilterChainData(
742  const XdsListenerResource::FilterChainData* filter_chain) {
743  MutexLock lock(&mu_);
744  auto it = certificate_providers_map_.find(filter_chain);
745  if (it != certificate_providers_map_.end()) {
746  return it->second.xds;
747  }
748  CertificateProviders certificate_providers;
749  // Configure root cert.
750  absl::string_view root_provider_instance_name =
751  filter_chain->downstream_tls_context.common_tls_context
752  .certificate_validation_context.ca_certificate_provider_instance
753  .instance_name;
754  absl::string_view root_provider_cert_name =
755  filter_chain->downstream_tls_context.common_tls_context
756  .certificate_validation_context.ca_certificate_provider_instance
757  .certificate_name;
758  if (!root_provider_instance_name.empty()) {
759  certificate_providers.root =
760  xds_client_->certificate_provider_store()
761  .CreateOrGetCertificateProvider(root_provider_instance_name);
762  if (certificate_providers.root == nullptr) {
763  return absl::NotFoundError(
764  absl::StrCat("Certificate provider instance name: \"",
765  root_provider_instance_name, "\" not recognized."));
766  }
767  }
768  // Configure identity cert.
769  absl::string_view identity_provider_instance_name =
770  filter_chain->downstream_tls_context.common_tls_context
771  .tls_certificate_provider_instance.instance_name;
772  absl::string_view identity_provider_cert_name =
773  filter_chain->downstream_tls_context.common_tls_context
774  .tls_certificate_provider_instance.certificate_name;
775  if (!identity_provider_instance_name.empty()) {
776  certificate_providers.instance =
777  xds_client_->certificate_provider_store()
778  .CreateOrGetCertificateProvider(identity_provider_instance_name);
779  if (certificate_providers.instance == nullptr) {
780  return absl::NotFoundError(
781  absl::StrCat("Certificate provider instance name: \"",
782  identity_provider_instance_name, "\" not recognized."));
783  }
784  }
785  certificate_providers.xds = MakeRefCounted<XdsCertificateProvider>();
786  certificate_providers.xds->UpdateRootCertNameAndDistributor(
787  "", root_provider_cert_name,
788  certificate_providers.root == nullptr
789  ? nullptr
790  : certificate_providers.root->distributor());
791  certificate_providers.xds->UpdateIdentityCertNameAndDistributor(
792  "", identity_provider_cert_name,
793  certificate_providers.instance == nullptr
794  ? nullptr
795  : certificate_providers.instance->distributor());
796  certificate_providers.xds->UpdateRequireClientCertificate(
797  "", filter_chain->downstream_tls_context.require_client_certificate);
798  auto xds_certificate_provider = certificate_providers.xds;
799  certificate_providers_map_.emplace(filter_chain,
800  std::move(certificate_providers));
801  return xds_certificate_provider;
802 }
803 
804 void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
805  OnRouteConfigChanged(const std::string& resource_name,
806  XdsRouteConfigResource route_config) {
807  RefCountedPtr<ListenerWatcher> listener_watcher;
808  {
809  MutexLock lock(&mu_);
810  auto& state = rds_map_[resource_name];
811  if (!state.rds_update.has_value()) {
812  if (--rds_resources_yet_to_fetch_ == 0) {
813  listener_watcher = std::move(listener_watcher_);
814  }
815  }
816  state.rds_update = std::move(route_config);
817  }
818  // Promote the filter chain match manager object if all the referenced
819  // resources are fetched.
820  if (listener_watcher != nullptr) {
821  listener_watcher->PendingFilterChainMatchManagerReady(this);
822  }
823 }
824 
826  const std::string& resource_name, absl::Status status) {
827  RefCountedPtr<ListenerWatcher> listener_watcher;
828  {
829  MutexLock lock(&mu_);
830  auto& state = rds_map_[resource_name];
831  if (!state.rds_update.has_value()) {
832  if (--rds_resources_yet_to_fetch_ == 0) {
833  listener_watcher = std::move(listener_watcher_);
834  }
835  state.rds_update = status;
836  } else {
837  // Prefer existing good version over current errored version
838  if (!state.rds_update->ok()) {
839  state.rds_update = status;
840  }
841  }
842  }
843  // Promote the filter chain match manager object if all the referenced
844  // resources are fetched.
845  if (listener_watcher != nullptr) {
846  listener_watcher->PendingFilterChainMatchManagerReady(this);
847  }
848 }
849 
850 void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
851  OnResourceDoesNotExist(const std::string& resource_name) {
852  RefCountedPtr<ListenerWatcher> listener_watcher;
853  {
854  MutexLock lock(&mu_);
855  auto& state = rds_map_[resource_name];
856  if (!state.rds_update.has_value()) {
857  if (--rds_resources_yet_to_fetch_ == 0) {
858  listener_watcher = std::move(listener_watcher_);
859  }
860  }
861  state.rds_update =
862  absl::NotFoundError("Requested route config does not exist");
863  }
864  // Promote the filter chain match manager object if all the referenced
865  // resources are fetched.
866  if (listener_watcher != nullptr) {
867  listener_watcher->PendingFilterChainMatchManagerReady(this);
868  }
869 }
870 
871 const XdsListenerResource::FilterChainData* FindFilterChainDataForSourcePort(
872  const XdsListenerResource::FilterChainMap::SourcePortsMap& source_ports_map,
873  absl::string_view port_str) {
874  int port = 0;
875  if (!absl::SimpleAtoi(port_str, &port)) return nullptr;
876  auto it = source_ports_map.find(port);
877  if (it != source_ports_map.end()) {
878  return it->second.data.get();
879  }
880  // Search for the catch-all port 0 since we didn't get a direct match
881  it = source_ports_map.find(0);
882  if (it != source_ports_map.end()) {
883  return it->second.data.get();
884  }
885  return nullptr;
886 }
887 
888 const XdsListenerResource::FilterChainData* FindFilterChainDataForSourceIp(
889  const XdsListenerResource::FilterChainMap::SourceIpVector& source_ip_vector,
890  const grpc_resolved_address* source_ip, absl::string_view port) {
891  const XdsListenerResource::FilterChainMap::SourceIp* best_match = nullptr;
892  for (const auto& entry : source_ip_vector) {
893  // Special case for catch-all
894  if (!entry.prefix_range.has_value()) {
895  if (best_match == nullptr) {
896  best_match = &entry;
897  }
898  continue;
899  }
900  if (best_match != nullptr && best_match->prefix_range.has_value() &&
901  best_match->prefix_range->prefix_len >=
902  entry.prefix_range->prefix_len) {
903  continue;
904  }
905  if (grpc_sockaddr_match_subnet(source_ip, &entry.prefix_range->address,
906  entry.prefix_range->prefix_len)) {
907  best_match = &entry;
908  }
909  }
910  if (best_match == nullptr) return nullptr;
911  return FindFilterChainDataForSourcePort(best_match->ports_map, port);
912 }
913 
914 bool IsLoopbackIp(const grpc_resolved_address* address) {
915  const grpc_sockaddr* sock_addr =
916  reinterpret_cast<const grpc_sockaddr*>(&address->addr);
917  if (sock_addr->sa_family == GRPC_AF_INET) {
918  const grpc_sockaddr_in* addr4 =
919  reinterpret_cast<const grpc_sockaddr_in*>(sock_addr);
920  if (addr4->sin_addr.s_addr == grpc_htonl(INADDR_LOOPBACK)) {
921  return true;
922  }
923  } else if (sock_addr->sa_family == GRPC_AF_INET6) {
924  const grpc_sockaddr_in6* addr6 =
925  reinterpret_cast<const grpc_sockaddr_in6*>(sock_addr);
926  if (memcmp(&addr6->sin6_addr, &in6addr_loopback,
927  sizeof(in6addr_loopback)) == 0) {
928  return true;
929  }
930  }
931  return false;
932 }
933 
934 const XdsListenerResource::FilterChainData* FindFilterChainDataForSourceType(
935  const XdsListenerResource::FilterChainMap::ConnectionSourceTypesArray&
937  grpc_endpoint* tcp, absl::string_view destination_ip) {
938  auto source_uri = URI::Parse(grpc_endpoint_get_peer(tcp));
939  if (!source_uri.ok() ||
940  (source_uri->scheme() != "ipv4" && source_uri->scheme() != "ipv6")) {
941  return nullptr;
942  }
943  std::string host;
945  if (!SplitHostPort(source_uri->path(), &host, &port)) {
946  return nullptr;
947  }
948  grpc_resolved_address source_addr;
950  &source_addr, host.c_str(), 0 /* port doesn't matter here */);
951  if (!GRPC_ERROR_IS_NONE(error)) {
952  gpr_log(GPR_DEBUG, "Could not parse string to socket address: %s",
953  host.c_str());
955  return nullptr;
956  }
957  // Use kAny only if kSameIporLoopback and kExternal are empty
958  if (source_types_array[static_cast<int>(
959  XdsListenerResource::FilterChainMap::
960  ConnectionSourceType::kSameIpOrLoopback)]
961  .empty() &&
962  source_types_array[static_cast<int>(XdsListenerResource::FilterChainMap::
963  ConnectionSourceType::kExternal)]
964  .empty()) {
965  return FindFilterChainDataForSourceIp(
966  source_types_array[static_cast<int>(
967  XdsListenerResource::FilterChainMap::ConnectionSourceType::kAny)],
968  &source_addr, port);
969  }
970  if (IsLoopbackIp(&source_addr) || host == destination_ip) {
971  return FindFilterChainDataForSourceIp(
972  source_types_array[static_cast<int>(
973  XdsListenerResource::FilterChainMap::ConnectionSourceType::
974  kSameIpOrLoopback)],
975  &source_addr, port);
976  } else {
977  return FindFilterChainDataForSourceIp(
978  source_types_array[static_cast<int>(
979  XdsListenerResource::FilterChainMap::ConnectionSourceType::
980  kExternal)],
981  &source_addr, port);
982  }
983 }
984 
985 const XdsListenerResource::FilterChainData* FindFilterChainDataForDestinationIp(
986  const XdsListenerResource::FilterChainMap::DestinationIpVector
987  destination_ip_vector,
988  grpc_endpoint* tcp) {
989  auto destination_uri = URI::Parse(grpc_endpoint_get_local_address(tcp));
990  if (!destination_uri.ok() || (destination_uri->scheme() != "ipv4" &&
991  destination_uri->scheme() != "ipv6")) {
992  return nullptr;
993  }
994  std::string host;
996  if (!SplitHostPort(destination_uri->path(), &host, &port)) {
997  return nullptr;
998  }
999  grpc_resolved_address destination_addr;
1001  &destination_addr, host.c_str(), 0 /* port doesn't matter here */);
1002  if (!GRPC_ERROR_IS_NONE(error)) {
1003  gpr_log(GPR_DEBUG, "Could not parse string to socket address: %s",
1004  host.c_str());
1006  return nullptr;
1007  }
1008  const XdsListenerResource::FilterChainMap::DestinationIp* best_match =
1009  nullptr;
1010  for (const auto& entry : destination_ip_vector) {
1011  // Special case for catch-all
1012  if (!entry.prefix_range.has_value()) {
1013  if (best_match == nullptr) {
1014  best_match = &entry;
1015  }
1016  continue;
1017  }
1018  if (best_match != nullptr && best_match->prefix_range.has_value() &&
1019  best_match->prefix_range->prefix_len >=
1020  entry.prefix_range->prefix_len) {
1021  continue;
1022  }
1023  if (grpc_sockaddr_match_subnet(&destination_addr,
1024  &entry.prefix_range->address,
1025  entry.prefix_range->prefix_len)) {
1026  best_match = &entry;
1027  }
1028  }
1029  if (best_match == nullptr) return nullptr;
1030  return FindFilterChainDataForSourceType(best_match->source_types_array, tcp,
1031  host);
1032 }
1033 
1034 absl::StatusOr<grpc_channel_args*> XdsServerConfigFetcher::ListenerWatcher::
1035  FilterChainMatchManager::UpdateChannelArgsForConnection(
1037  const auto* filter_chain = FindFilterChainDataForDestinationIp(
1038  filter_chain_map_.destination_ip_vector, tcp);
1039  if (filter_chain == nullptr && default_filter_chain_.has_value()) {
1040  filter_chain = &default_filter_chain_.value();
1041  }
1042  if (filter_chain == nullptr) {
1044  return absl::UnavailableError("No matching filter chain found");
1045  }
1047  RefCountedPtr<ServerConfigSelectorProvider> server_config_selector_provider;
1048  RefCountedPtr<XdsChannelStackModifier> channel_stack_modifier;
1049  RefCountedPtr<XdsCertificateProvider> xds_certificate_provider;
1050  // Add config selector filter
1051  if (XdsRbacEnabled()) {
1052  std::vector<const grpc_channel_filter*> filters;
1053  // Iterate the list of HTTP filters in reverse since in Core, received data
1054  // flows *up* the stack.
1055  for (const auto& http_filter :
1056  filter_chain->http_connection_manager.http_filters) {
1057  // Find filter. This is guaranteed to succeed, because it's checked
1058  // at config validation time in the XdsApi code.
1059  const XdsHttpFilterImpl* filter_impl =
1060  XdsHttpFilterRegistry::GetFilterForType(
1061  http_filter.config.config_proto_type_name);
1062  GPR_ASSERT(filter_impl != nullptr);
1063  // Some filters like the router filter are no-op filters and do not have
1064  // an implementation.
1065  if (filter_impl->channel_filter() != nullptr) {
1066  filters.push_back(filter_impl->channel_filter());
1067  }
1068  }
1069  filters.push_back(&kServerConfigSelectorFilter);
1070  channel_stack_modifier =
1071  MakeRefCounted<XdsChannelStackModifier>(std::move(filters));
1072  if (filter_chain->http_connection_manager.rds_update.has_value()) {
1073  server_config_selector_provider =
1074  MakeRefCounted<StaticXdsServerConfigSelectorProvider>(
1075  filter_chain->http_connection_manager.rds_update.value(),
1076  filter_chain->http_connection_manager.http_filters);
1077  } else {
1078  absl::StatusOr<XdsRouteConfigResource> initial_resource;
1079  {
1080  MutexLock lock(&mu_);
1081  initial_resource =
1082  rds_map_[filter_chain->http_connection_manager.route_config_name]
1083  .rds_update.value();
1084  }
1085  server_config_selector_provider =
1086  MakeRefCounted<DynamicXdsServerConfigSelectorProvider>(
1087  xds_client_,
1088  filter_chain->http_connection_manager.route_config_name,
1089  std::move(initial_resource),
1090  filter_chain->http_connection_manager.http_filters);
1091  }
1092  args_to_add.emplace_back(server_config_selector_provider->MakeChannelArg());
1093  args_to_add.emplace_back(channel_stack_modifier->MakeChannelArg());
1094  }
1095  // Add XdsCertificateProvider if credentials are xDS.
1096  grpc_server_credentials* server_creds =
1098  if (server_creds != nullptr &&
1099  server_creds->type() == XdsServerCredentials::Type()) {
1101  CreateOrGetXdsCertificateProviderFromFilterChainData(filter_chain);
1102  if (!result.ok()) {
1104  return result.status();
1105  }
1106  xds_certificate_provider = std::move(*result);
1107  GPR_ASSERT(xds_certificate_provider != nullptr);
1108  args_to_add.emplace_back(xds_certificate_provider->MakeChannelArg());
1109  }
1110  if (!args_to_add.empty()) {
1112  args, args_to_add.data(), args_to_add.size());
1114  args = updated_args;
1115  }
1116  return args;
1117 }
1118 
1119 //
1120 // XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::XdsServerConfigSelector
1121 //
1122 
1124  RefCountedPtr<XdsServerConfigFetcher::ListenerWatcher::
1125  FilterChainMatchManager::XdsServerConfigSelector>>
1126 XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1127  XdsServerConfigSelector::Create(
1128  XdsRouteConfigResource rds_update,
1129  const std::vector<
1130  XdsListenerResource::HttpConnectionManager::HttpFilter>&
1131  http_filters) {
1132  auto config_selector = MakeRefCounted<XdsServerConfigSelector>();
1133  for (auto& vhost : rds_update.virtual_hosts) {
1134  config_selector->virtual_hosts_.emplace_back();
1135  auto& virtual_host = config_selector->virtual_hosts_.back();
1136  virtual_host.domains = std::move(vhost.domains);
1137  for (auto& route : vhost.routes) {
1138  virtual_host.routes.emplace_back();
1139  auto& config_selector_route = virtual_host.routes.back();
1140  config_selector_route.matchers = std::move(route.matchers);
1141  config_selector_route.unsupported_action =
1142  absl::get_if<XdsRouteConfigResource::Route::NonForwardingAction>(
1143  &route.action) == nullptr;
1144  XdsRouting::GeneratePerHttpFilterConfigsResult result =
1145  XdsRouting::GeneratePerHTTPFilterConfigs(http_filters, vhost, route,
1146  nullptr, nullptr);
1147  if (!GRPC_ERROR_IS_NONE(result.error)) {
1148  return grpc_error_to_absl_status(result.error);
1149  }
1150  std::vector<std::string> fields;
1151  fields.reserve(result.per_filter_configs.size());
1152  for (const auto& p : result.per_filter_configs) {
1153  fields.emplace_back(absl::StrCat(" \"", p.first, "\": [\n",
1154  absl::StrJoin(p.second, ",\n"),
1155  "\n ]"));
1156  }
1157  if (!fields.empty()) {
1158  std::string json = absl::StrCat(
1159  "{\n"
1160  " \"methodConfig\": [ {\n"
1161  " \"name\": [\n"
1162  " {}\n"
1163  " ],\n"
1164  " ",
1165  absl::StrJoin(fields, ",\n"),
1166  "\n } ]\n"
1167  "}");
1169  config_selector_route.method_config =
1170  ServiceConfigImpl::Create(result.args, json.c_str(), &error);
1172  }
1174  }
1175  }
1176  return config_selector;
1177 }
1178 
1179 ServerConfigSelector::CallConfig XdsServerConfigFetcher::ListenerWatcher::
1180  FilterChainMatchManager::XdsServerConfigSelector::GetCallConfig(
1182  CallConfig call_config;
1183  if (metadata->get_pointer(HttpPathMetadata()) == nullptr) {
1184  call_config.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("No path found");
1185  return call_config;
1186  }
1188  metadata->get_pointer(HttpPathMetadata())->as_string_view();
1189  if (metadata->get_pointer(HttpAuthorityMetadata()) == nullptr) {
1190  call_config.error =
1191  GRPC_ERROR_CREATE_FROM_STATIC_STRING("No authority found");
1192  return call_config;
1193  }
1194  absl::string_view authority =
1195  metadata->get_pointer(HttpAuthorityMetadata())->as_string_view();
1196  auto vhost_index = XdsRouting::FindVirtualHostForDomain(
1197  VirtualHostListIterator(&virtual_hosts_), authority);
1198  if (!vhost_index.has_value()) {
1199  call_config.error =
1201  "could not find VirtualHost for ", authority,
1202  " in RouteConfiguration")),
1204  return call_config;
1205  }
1206  auto& virtual_host = virtual_hosts_[vhost_index.value()];
1207  auto route_index = XdsRouting::GetRouteForRequest(
1208  VirtualHost::RouteListIterator(&virtual_host.routes), path, metadata);
1209  if (route_index.has_value()) {
1210  auto& route = virtual_host.routes[route_index.value()];
1211  // Found the matching route
1212  if (route.unsupported_action) {
1213  call_config.error = grpc_error_set_int(
1215  "Matching route has unsupported action"),
1217  return call_config;
1218  }
1219  if (route.method_config != nullptr) {
1220  call_config.method_configs =
1221  route.method_config->GetMethodParsedConfigVector(grpc_empty_slice());
1222  call_config.service_config = route.method_config;
1223  }
1224  return call_config;
1225  }
1226  call_config.error = grpc_error_set_int(
1227  GRPC_ERROR_CREATE_FROM_STATIC_STRING("No route matched"),
1229  return call_config;
1230 }
1231 
1232 //
1233 // XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::DynamicXdsServerConfigSelectorProvider
1234 //
1235 
1236 XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1237  DynamicXdsServerConfigSelectorProvider::
1238  DynamicXdsServerConfigSelectorProvider(
1239  RefCountedPtr<XdsClient> xds_client, std::string resource_name,
1240  absl::StatusOr<XdsRouteConfigResource> initial_resource,
1241  std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>
1242  http_filters)
1243  : xds_client_(std::move(xds_client)),
1244  resource_name_(std::move(resource_name)),
1245  http_filters_(std::move(http_filters)),
1246  resource_(std::move(initial_resource)) {
1247  GPR_ASSERT(!resource_name_.empty());
1248  // RouteConfigWatcher is being created here instead of in Watch() to avoid
1249  // deadlocks from invoking XdsRouteConfigResourceType::StartWatch whilst in a
1250  // critical region.
1251  auto route_config_watcher = MakeRefCounted<RouteConfigWatcher>(WeakRef());
1252  route_config_watcher_ = route_config_watcher.get();
1253  XdsRouteConfigResourceType::StartWatch(xds_client_.get(), resource_name_,
1254  std::move(route_config_watcher));
1255 }
1256 
1257 void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1258  DynamicXdsServerConfigSelectorProvider::Orphan() {
1259  XdsRouteConfigResourceType::CancelWatch(xds_client_.get(), resource_name_,
1261  false /* delay_unsubscription */);
1262 }
1263 
1265 XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1266  DynamicXdsServerConfigSelectorProvider::Watch(
1267  std::unique_ptr<
1268  ServerConfigSelectorProvider::ServerConfigSelectorWatcher>
1269  watcher) {
1271  {
1272  MutexLock lock(&mu_);
1273  GPR_ASSERT(watcher_ == nullptr);
1275  resource = resource_;
1276  }
1277  if (!resource.ok()) {
1278  return resource.status();
1279  }
1280  return XdsServerConfigSelector::Create(resource.value(), http_filters_);
1281 }
1282 
1283 void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1284  DynamicXdsServerConfigSelectorProvider::CancelWatch() {
1285  MutexLock lock(&mu_);
1286  watcher_.reset();
1287 }
1288 
1289 void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1290  DynamicXdsServerConfigSelectorProvider::OnRouteConfigChanged(
1291  XdsRouteConfigResource rds_update) {
1292  MutexLock lock(&mu_);
1294  if (watcher_ == nullptr) {
1295  return;
1296  }
1297  // Currently server_config_selector_filter does not call into
1298  // DynamicXdsServerConfigSelectorProvider while holding a lock, but if that
1299  // ever changes, we would want to invoke the update outside the critical
1300  // region with the use of a WorkSerializer.
1301  watcher_->OnServerConfigSelectorUpdate(
1302  XdsServerConfigSelector::Create(*resource_, http_filters_));
1303 }
1304 
1307  MutexLock lock(&mu_);
1308  // Prefer existing good update.
1309  if (resource_.ok()) {
1310  return;
1311  }
1312  resource_ = status;
1313  if (watcher_ == nullptr) {
1314  return;
1315  }
1316  watcher_->OnServerConfigSelectorUpdate(resource_.status());
1317 }
1318 
1319 void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::
1320  DynamicXdsServerConfigSelectorProvider::OnResourceDoesNotExist() {
1321  MutexLock lock(&mu_);
1322  resource_ = absl::NotFoundError("Requested route config does not exist");
1323  if (watcher_ == nullptr) {
1324  return;
1325  }
1326  watcher_->OnServerConfigSelectorUpdate(resource_.status());
1327 }
1328 
1329 } // namespace
1330 } // namespace grpc_core
1331 
1334  grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
1339  .ToC();
1341  "grpc_server_config_fetcher_xds_create(notifier={on_serving_status_"
1342  "update=%p, user_data=%p}, args=%p)",
1343  3, (notifier.on_serving_status_update, notifier.user_data, args));
1348  if (!GRPC_ERROR_IS_NONE(error)) {
1349  gpr_log(GPR_ERROR, "Failed to create xds client: %s",
1352  return nullptr;
1353  }
1354  if (xds_client->bootstrap()
1356  .empty()) {
1358  "server_listener_resource_name_template not provided in bootstrap "
1359  "file.");
1360  return nullptr;
1361  }
1362  return new grpc_core::XdsServerConfigFetcher(std::move(xds_client), notifier);
1363 }
virtual_hosts_
const std::vector< VirtualHost > * virtual_hosts_
Definition: xds_server_config_fetcher.cc:355
trace.h
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
Type
struct Type Type
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:673
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
xds_routing.h
grpc_core::XdsRbacEnabled
bool XdsRbacEnabled()
Definition: xds_route_config.cc:82
http_filters_
std::vector< XdsListenerResource::HttpConnectionManager::HttpFilter > http_filters_
Definition: xds_server_config_fetcher.cc:393
regen-readme.it
it
Definition: regen-readme.py:15
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
log.h
core_configuration.h
metadata_batch.h
sockaddr_utils.h
filter_chain_map_
XdsListenerResource::FilterChainMap filter_chain_map_
Definition: xds_server_config_fetcher.cc:253
GRPC_STATUS_UNAVAILABLE
@ GRPC_STATUS_UNAVAILABLE
Definition: include/grpc/impl/codegen/status.h:143
MutexLock
#define MutexLock(x)
Definition: bloaty/third_party/re2/util/mutex.h:125
absl::Status::ToString
std::string ToString(StatusToStringMode mode=StatusToStringMode::kDefault) const
Definition: third_party/abseil-cpp/absl/status/status.h:821
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
metadata
Definition: cq_verifier.cc:48
listening_address_
const std::string listening_address_
Definition: xds_server_config_fetcher.cc:179
grpc_tls_certificate_distributor.h
channel_fwd.h
absl::InlinedVector::emplace_back
reference emplace_back(Args &&... args)
Definition: abseil-cpp/absl/container/inlined_vector.h:675
rds_update
absl::optional< absl::StatusOr< XdsRouteConfigResource > > rds_update
Definition: xds_server_config_fetcher.cc:231
certificate_provider_store.h
grpc_server_config_fetcher
Definition: src/core/lib/surface/server.h:497
route
XdsRouteConfigResource::Route route
Definition: xds_resolver.cc:337
mu_
Mutex mu_
Definition: xds_server_config_fetcher.cc:125
slice.h
grpc_core
Definition: call_metric_recorder.h:31
SplitHostPort
static void SplitHostPort(std::string *out_hostname, std::string *out_port, const std::string &hostname_and_port)
Definition: transport_common.cc:91
grpc_pollset_set
struct grpc_pollset_set grpc_pollset_set
Definition: iomgr_fwd.h:23
string.h
absl::StartsWith
bool StartsWith(absl::string_view text, absl::string_view prefix) noexcept
Definition: third_party/abseil-cpp/absl/strings/match.h:58
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
matchers
XdsRouteConfigResource::Route::Matchers matchers
Definition: xds_server_config_fetcher.cc:317
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
grpc_endpoint_get_peer
absl::string_view grpc_endpoint_get_peer(grpc_endpoint *ep)
Definition: endpoint.cc:55
xds_http_filters.h
xds_route_config.h
grpc_resolved_address
Definition: resolved_address.h:34
tcp
static uv_tcp_t tcp
Definition: test-connection-fail.c:29
ABSL_GUARDED_BY
#define ABSL_GUARDED_BY(x)
Definition: abseil-cpp/absl/base/thread_annotations.h:62
instance
RefCountedPtr< grpc_tls_certificate_provider > instance
Definition: xds_server_config_fetcher.cc:224
status
absl::Status status
Definition: rls.cc:251
xds_resource_type_impl.h
grpc_core::ApplicationCallbackExecCtx
Definition: exec_ctx.h:283
check_documentation.path
path
Definition: check_documentation.py:57
xds_manager.p
p
Definition: xds_manager.py:60
grpc_security.h
method_config
RefCountedPtr< ServiceConfig > method_config
Definition: xds_server_config_fetcher.cc:318
resolved_address.h
sockaddr.h
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
credentials.h
grpc_channel_args
Definition: grpc_types.h:132
GRPC_TRACE_FLAG_ENABLED
#define GRPC_TRACE_FLAG_ENABLED(f)
Definition: debug/trace.h:114
resource_name_
std::string resource_name_
Definition: xds_server_config_fetcher.cc:293
channel_args_preconditioning.h
status.h
route_config_watcher_
RouteConfigWatcher * route_config_watcher_
Definition: xds_server_config_fetcher.cc:428
grpc_types.h
xds
RefCountedPtr< XdsCertificateProvider > xds
Definition: xds_server_config_fetcher.cc:225
server_config_selector.h
make_dist_html.reverse
reverse
Definition: make_dist_html.py:119
grpc_core::XdsBootstrap::server_listener_resource_name_template
const std::string & server_listener_resource_name_template() const
Definition: xds_bootstrap.h:106
socket_utils.h
absl::SimpleAtoi
ABSL_NAMESPACE_BEGIN ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type *out)
Definition: abseil-cpp/absl/strings/numbers.h:271
grpc_server_xds_status_notifier::on_serving_status_update
void(* on_serving_status_update)(void *user_data, const char *uri, grpc_serving_status_update update)
Definition: grpc.h:453
grpc_sockaddr_match_subnet
bool grpc_sockaddr_match_subnet(const grpc_resolved_address *address, const grpc_resolved_address *subnet_address, uint32_t mask_bits)
Definition: sockaddr_utils.cc:415
parse_address.h
grpc_tls_certificate_provider.h
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
watcher_
std::unique_ptr< ServerConfigSelectorProvider::ServerConfigSelectorWatcher > watcher_
Definition: xds_server_config_fetcher.cc:395
grpc_core::RefCountedPtr< grpc_core::XdsClient >
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
absl::StrJoin
std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, Formatter &&fmt)
Definition: abseil-cpp/absl/strings/str_join.h:239
grpc_core::CoreConfiguration::Get
static const CoreConfiguration & Get()
Definition: core_configuration.h:82
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
absl::FailedPreconditionError
Status FailedPreconditionError(absl::string_view message)
Definition: third_party/abseil-cpp/absl/status/status.cc:343
root
RefCountedPtr< grpc_tls_certificate_provider > root
Definition: xds_server_config_fetcher.cc:223
xds_common_types.h
grpc_string_to_sockaddr
grpc_error_handle grpc_string_to_sockaddr(grpc_resolved_address *out, const char *addr, int port)
Definition: parse_address.cc:320
source_types_array
ConnectionSourceTypesArray source_types_array
Definition: xds_listener.cc:752
xds_client.h
parent_
WeakRefCountedPtr< DynamicXdsServerConfigSelectorProvider > parent_
Definition: xds_server_config_fetcher.cc:454
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
ABSL_EXCLUSIVE_LOCKS_REQUIRED
#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: abseil-cpp/absl/base/thread_annotations.h:145
xds_bootstrap.h
grpc.h
absl::optional
Definition: abseil-cpp/absl/types/internal/optional.h:61
grpc_core::ChannelArgs::ToC
const grpc_channel_args * ToC() const
Definition: channel_args.cc:94
addr6
static struct sockaddr_in6 addr6
Definition: test-getnameinfo.c:34
grpc_server_config_fetcher::ConnectionManager
Definition: src/core/lib/surface/server.h:499
grpc_channel_args_destroy
void grpc_channel_args_destroy(grpc_channel_args *a)
Definition: channel_args.cc:360
gen_settings_ids.OnError
OnError
Definition: gen_settings_ids.py:27
grpc_htonl
uint32_t grpc_htonl(uint32_t hostlong)
grpc_empty_slice
GPRAPI grpc_slice grpc_empty_slice(void)
Definition: slice/slice.cc:42
absl::InlinedVector::data
pointer data() noexcept
Definition: abseil-cpp/absl/container/inlined_vector.h:302
xds_listener.h
absl::flags_internal::Parse
bool Parse(FlagOpFn op, absl::string_view text, void *dst, std::string *error)
Definition: abseil-cpp/absl/flags/internal/flag.h:125
error.h
grpc_core::XdsClient::GetOrCreate
static RefCountedPtr< XdsClient > GetOrCreate(const grpc_channel_args *args, grpc_error_handle *error)
Definition: xds_client.cc:2465
host_port.h
absl::InlinedVector::size
size_type size() const noexcept
Definition: abseil-cpp/absl/container/inlined_vector.h:270
xds_channel_stack_modifier.h
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc_server_credentials::type
virtual grpc_core::UniqueTypeName type() const =0
grpc_core::CoreConfiguration::channel_args_preconditioning
const ChannelArgsPreconditioning & channel_args_preconditioning() const
Definition: core_configuration.h:139
xds_credentials.h
grpc_core::ExecCtx
Definition: exec_ctx.h:97
grpc_server_config_fetcher_xds_create
grpc_server_config_fetcher * grpc_server_config_fetcher_xds_create(grpc_server_xds_status_notifier notifier, const grpc_channel_args *args)
Definition: xds_server_config_fetcher.cc:1332
GRPC_ERROR_CREATE_FROM_STATIC_STRING
#define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc)
Definition: error.h:291
google_benchmark.example.empty
def empty(state)
Definition: example.py:31
watcher
RouteConfigWatcher * watcher
Definition: xds_server_config_fetcher.cc:230
tests.unit._exit_scenarios.port
port
Definition: _exit_scenarios.py:179
grpc_server_config_fetcher::WatcherInterface
Definition: src/core/lib/surface/server.h:507
addr4
static struct sockaddr_in addr4
Definition: test-getnameinfo.c:33
xds_client_
const RefCountedPtr< XdsClient > xds_client_
Definition: xds_server_config_fetcher.cc:121
resource_
UniquePtr< char > resource_
Definition: oauth2_credentials.cc:650
grpc_server_credentials
Definition: src/core/lib/security/credentials/credentials.h:259
routes
std::vector< Route > routes
Definition: xds_server_config_fetcher.cc:338
absl::StatusOr::ok
ABSL_MUST_USE_RESULT bool ok() const
Definition: abseil-cpp/absl/status/statusor.h:491
routes_
const std::vector< Route > * routes_
Definition: xds_server_config_fetcher.cc:334
grpc_error_set_int
grpc_error_handle grpc_error_set_int(grpc_error_handle src, grpc_error_ints which, intptr_t value)
Definition: error.cc:613
grpc_find_server_credentials_in_args
grpc_server_credentials * grpc_find_server_credentials_in_args(const grpc_channel_args *args)
Definition: credentials.cc:149
grpc_server_xds_status_notifier
Definition: grpc.h:452
grpc_server_xds_status_notifier::user_data
void * user_data
Definition: grpc.h:455
exec_ctx
grpc_core::ExecCtx exec_ctx
Definition: end2end_binder_transport_test.cc:75
grpc_error_std_string
std::string grpc_error_std_string(grpc_error_handle error)
Definition: error.cc:944
absl::Status
Definition: third_party/abseil-cpp/absl/status/status.h:424
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
GRPC_ERROR_CREATE_FROM_CPP_STRING
#define GRPC_ERROR_CREATE_FROM_CPP_STRING(desc)
Definition: error.h:297
static_resource_
absl::StatusOr< XdsRouteConfigResource > static_resource_
Definition: xds_server_config_fetcher.cc:391
google::protobuf.internal::Mutex
WrappedMutex Mutex
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/mutex.h:113
profile_analyzer.fields
list fields
Definition: profile_analyzer.py:266
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
service_config_impl.h
absl::StrReplaceAll
std::string StrReplaceAll(absl::string_view s, strings_internal::FixedMapping replacements)
Definition: abseil-cpp/absl/strings/str_replace.cc:71
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
exec_ctx.h
absl::NotFoundError
Status NotFoundError(absl::string_view message)
Definition: third_party/abseil-cpp/absl/status/status.cc:355
server.h
absl::UnavailableError
Status UnavailableError(absl::string_view message)
Definition: third_party/abseil-cpp/absl/status/status.cc:375
unique_type_name.h
GRPC_ERROR_UNREF
#define GRPC_ERROR_UNREF(err)
Definition: error.h:262
ref_counted_ptr.h
channel_args.h
xds_certificate_provider.h
api_trace.h
sockaddr_in6::sin6_addr
struct ares_in6_addr sin6_addr
Definition: ares_ipv6.h:30
service_config.h
GPR_DEBUG
#define GPR_DEBUG
Definition: include/grpc/impl/codegen/log.h:55
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
absl::InlinedVector::empty
bool empty() const noexcept
Definition: abseil-cpp/absl/container/inlined_vector.h:265
grpc_core::kServerConfigSelectorFilter
const grpc_channel_filter kServerConfigSelectorFilter
Definition: server_config_selector_filter.cc:159
absl::StatusOr::value
const T & value() const &ABSL_ATTRIBUTE_LIFETIME_BOUND
Definition: abseil-cpp/absl/status/statusor.h:687
absl::StatusOr
Definition: abseil-cpp/absl/status/statusor.h:187
uri_parser.h
iomgr_fwd.h
serving_status_notifier_
const grpc_server_xds_status_notifier serving_status_notifier_
Definition: xds_server_config_fetcher.cc:124
absl::InlinedVector< grpc_arg, 3 >
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
grpc_endpoint_get_local_address
absl::string_view grpc_endpoint_get_local_address(grpc_endpoint *ep)
Definition: endpoint.cc:59
endpoint.h
grpc_error
Definition: error_internal.h:42
server_config_watcher_
const std::unique_ptr< grpc_server_config_fetcher::WatcherInterface > server_config_watcher_
Definition: xds_server_config_fetcher.cc:177
grpc_error_to_absl_status
absl::Status grpc_error_to_absl_status(grpc_error_handle error)
Definition: error_utils.cc:156
testing::Ref
internal::RefMatcher< T & > Ref(T &x)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8628
listener_watcher_
RefCountedPtr< ListenerWatcher > listener_watcher_
Definition: xds_server_config_fetcher.cc:252
domains
std::vector< std::string > domains
Definition: xds_server_config_fetcher.cc:337
grpc_metadata_batch
Definition: metadata_batch.h:1259
unsupported_action
bool unsupported_action
Definition: xds_server_config_fetcher.cc:316
grpc_resolved_address::addr
char addr[GRPC_MAX_SOCKADDR_SIZE]
Definition: resolved_address.h:35
filter_chain_match_manager_
WeakRefCountedPtr< FilterChainMatchManager > filter_chain_match_manager_
Definition: xds_server_config_fetcher.cc:294
grpc_endpoint
Definition: endpoint.h:105
grpc_core::ChannelArgsPreconditioning::PreconditionChannelArgs
ChannelArgs PreconditionChannelArgs(const grpc_channel_args *args) const
Definition: channel_args_preconditioning.cc:34
default_filter_chain_
absl::optional< XdsListenerResource::FilterChainData > default_filter_chain_
Definition: xds_server_config_fetcher.cc:254
sync.h
grpc_core::XdsClient::bootstrap
const XdsBootstrap & bootstrap() const
Definition: xds_client.h:88
grpc_channel_args_copy_and_add
grpc_channel_args * grpc_channel_args_copy_and_add(const grpc_channel_args *src, const grpc_arg *to_add, size_t num_to_add)
Definition: channel_args.cc:224
GRPC_ERROR_INT_GRPC_STATUS
@ GRPC_ERROR_INT_GRPC_STATUS
grpc status code representing this error
Definition: error.h:66
GRPC_API_TRACE
#define GRPC_API_TRACE(fmt, nargs, args)
Definition: api_trace.h:48
absl::StatusOr::status
const Status & status() const &
Definition: abseil-cpp/absl/status/statusor.h:678
error_utils.h
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
port_platform.h
server_config_selector_filter.h


grpc
Author(s):
autogenerated on Fri May 16 2025 03:01:00