xds_resolver.cc
Go to the documentation of this file.
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 
18 
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include <algorithm>
23 #include <cstdint>
24 #include <map>
25 #include <memory>
26 #include <string>
27 #include <type_traits>
28 #include <utility>
29 #include <vector>
30 
31 #include "absl/memory/memory.h"
32 #include "absl/meta/type_traits.h"
33 #include "absl/random/random.h"
34 #include "absl/status/status.h"
35 #include "absl/status/statusor.h"
36 #include "absl/strings/match.h"
37 #include "absl/strings/str_cat.h"
38 #include "absl/strings/str_format.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/strings/strip.h"
43 #include "absl/types/optional.h"
44 #include "absl/types/variant.h"
45 #include "re2/re2.h"
46 
48 
49 #define XXH_INLINE_ALL
50 #include "xxhash.h"
51 
53 #include <grpc/slice.h>
54 #include <grpc/status.h>
55 #include <grpc/support/log.h>
56 
93 
94 namespace grpc_core {
95 
96 TraceFlag grpc_xds_resolver_trace(false, "xds_resolver");
97 
99  static UniqueTypeName::Factory kFactory("xds_cluster_name");
100  return kFactory.Create();
101 }
102 
103 namespace {
104 
105 std::string GetDefaultAuthorityInternal(const URI& uri) {
106  // Obtain the authority to use for the data plane connections, which is
107  // also used to select the right VirtualHost from the RouteConfiguration.
108  // We need to take the part of the URI path following the last
109  // "/" character or the entire path if the path contains no "/" character.
110  size_t pos = uri.path().find_last_of('/');
111  if (pos == uri.path().npos) return uri.path();
112  return uri.path().substr(pos + 1);
113 }
114 
115 std::string GetDataPlaneAuthority(const grpc_channel_args& args,
116  const URI& uri) {
117  const char* authority =
119  if (authority != nullptr) return authority;
120  return GetDefaultAuthorityInternal(uri);
121 }
122 
123 //
124 // XdsResolver
125 //
126 
127 class XdsResolver : public Resolver {
128  public:
129  explicit XdsResolver(ResolverArgs args)
130  : work_serializer_(std::move(args.work_serializer)),
131  result_handler_(std::move(args.result_handler)),
133  interested_parties_(args.pollset_set),
134  uri_(std::move(args.uri)),
135  data_plane_authority_(GetDataPlaneAuthority(*args.args, uri_)),
138  gpr_log(
139  GPR_INFO,
140  "[xds_resolver %p] created for URI %s; data plane authority is %s",
141  this, uri_.ToString().c_str(), data_plane_authority_.c_str());
142  }
143  }
144 
145  ~XdsResolver() override {
148  gpr_log(GPR_INFO, "[xds_resolver %p] destroyed", this);
149  }
150  }
151 
152  void StartLocked() override;
153 
154  void ShutdownLocked() override;
155 
156  void ResetBackoffLocked() override {
157  if (xds_client_ != nullptr) xds_client_->ResetBackoff();
158  }
159 
160  private:
161  class ListenerWatcher : public XdsListenerResourceType::WatcherInterface {
162  public:
163  explicit ListenerWatcher(RefCountedPtr<XdsResolver> resolver)
164  : resolver_(std::move(resolver)) {}
165  void OnResourceChanged(XdsListenerResource listener) override {
166  Ref().release(); // ref held by lambda
167  resolver_->work_serializer_->Run(
168  // TODO(yashykt): When we move to C++14, capture listener with
169  // std::move
170  [this, listener]() mutable {
171  resolver_->OnListenerUpdate(std::move(listener));
172  Unref();
173  },
175  }
176  void OnError(absl::Status status) override {
177  Ref().release(); // ref held by lambda
178  resolver_->work_serializer_->Run(
179  [this, status]() {
180  resolver_->OnError(resolver_->lds_resource_name_, status);
181  Unref();
182  },
184  }
185  void OnResourceDoesNotExist() override {
186  Ref().release(); // ref held by lambda
187  resolver_->work_serializer_->Run(
188  [this]() {
189  resolver_->OnResourceDoesNotExist(
190  absl::StrCat(resolver_->lds_resource_name_,
191  ": xDS listener resource does not exist"));
192  Unref();
193  },
195  }
196 
197  private:
198  RefCountedPtr<XdsResolver> resolver_;
199  };
200 
201  class RouteConfigWatcher
202  : public XdsRouteConfigResourceType::WatcherInterface {
203  public:
204  explicit RouteConfigWatcher(RefCountedPtr<XdsResolver> resolver)
205  : resolver_(std::move(resolver)) {}
206  void OnResourceChanged(XdsRouteConfigResource route_config) override {
207  Ref().release(); // ref held by lambda
208  resolver_->work_serializer_->Run(
209  // TODO(yashykt): When we move to C++14, capture route_config with
210  // std::move
211  [this, route_config]() mutable {
212  resolver_->OnRouteConfigUpdate(std::move(route_config));
213  Unref();
214  },
216  }
217  void OnError(absl::Status status) override {
218  Ref().release(); // ref held by lambda
219  resolver_->work_serializer_->Run(
220  [this, status]() {
221  resolver_->OnError(resolver_->route_config_name_, status);
222  Unref();
223  },
225  }
226  void OnResourceDoesNotExist() override {
227  Ref().release(); // ref held by lambda
228  resolver_->work_serializer_->Run(
229  [this]() {
230  resolver_->OnResourceDoesNotExist(absl::StrCat(
231  resolver_->route_config_name_,
232  ": xDS route configuration resource does not exist"));
233  Unref();
234  },
236  }
237 
238  private:
239  RefCountedPtr<XdsResolver> resolver_;
240  };
241 
242  // An entry in the map of clusters that need to be present in the LB
243  // policy config. The map holds a weak ref. One strong ref is held by
244  // the ConfigSelector, and another is held by each call assigned to
245  // the cluster by the ConfigSelector. The ref for each call is held
246  // until the call is committed. When the strong refs go away, we hop
247  // back into the WorkSerializer to remove the entry from the map.
248  class ClusterState : public DualRefCounted<ClusterState> {
249  public:
250  using ClusterStateMap =
251  std::map<std::string, WeakRefCountedPtr<ClusterState>>;
252 
253  ClusterState(RefCountedPtr<XdsResolver> resolver,
254  const std::string& cluster_name)
255  : resolver_(std::move(resolver)),
256  it_(resolver_->cluster_state_map_.emplace(cluster_name, WeakRef())
257  .first) {}
258 
259  void Orphan() override {
260  auto* resolver = resolver_.release();
261  resolver->work_serializer_->Run(
262  [resolver]() {
263  resolver->MaybeRemoveUnusedClusters();
264  resolver->Unref();
265  },
267  }
268 
269  const std::string& cluster() const { return it_->first; }
270 
271  private:
272  RefCountedPtr<XdsResolver> resolver_;
274  };
275 
276  // Call dispatch controller, created for each call handled by the
277  // ConfigSelector. Holds a ref to the ClusterState object until the
278  // call is committed.
279  class XdsCallDispatchController
280  : public ConfigSelector::CallDispatchController {
281  public:
282  explicit XdsCallDispatchController(
283  RefCountedPtr<ClusterState> cluster_state)
284  : cluster_state_(std::move(cluster_state)) {}
285 
286  bool ShouldRetry() override {
287  // TODO(donnadionne): Implement the retry circuit breaker here.
288  return true;
289  }
290 
291  void Commit() override {
292  // TODO(donnadionne): If ShouldRetry() was called previously,
293  // decrement the retry circuit breaker counter.
294  cluster_state_.reset();
295  }
296 
297  private:
298  // Note: The XdsCallDispatchController object is never actually destroyed,
299  // so do not add any data members that require destruction unless you have
300  // some other way to clean them up.
301  RefCountedPtr<ClusterState> cluster_state_;
302  };
303 
304  class XdsConfigSelector : public ConfigSelector {
305  public:
306  XdsConfigSelector(RefCountedPtr<XdsResolver> resolver,
308  ~XdsConfigSelector() override;
309 
310  const char* name() const override { return "XdsConfigSelector"; }
311 
312  bool Equals(const ConfigSelector* other) const override {
313  const auto* other_xds = static_cast<const XdsConfigSelector*>(other);
314  // Don't need to compare resolver_, since that will always be the same.
315  return route_table_ == other_xds->route_table_ &&
316  clusters_ == other_xds->clusters_;
317  }
318 
319  CallConfig GetCallConfig(GetCallConfigArgs args) override;
320 
321  std::vector<const grpc_channel_filter*> GetFilters() override {
322  return filters_;
323  }
324 
325  grpc_channel_args* ModifyChannelArgs(grpc_channel_args* args) override;
326 
327  private:
328  struct Route {
329  struct ClusterWeightState {
332  RefCountedPtr<ServiceConfig> method_config;
333 
334  bool operator==(const ClusterWeightState& other) const;
335  };
336 
337  XdsRouteConfigResource::Route route;
338  RefCountedPtr<ServiceConfig> method_config;
339  std::vector<ClusterWeightState> weighted_cluster_state;
340 
341  bool operator==(const Route& other) const;
342  };
343  using RouteTable = std::vector<Route>;
344 
345  class RouteListIterator;
346 
347  void MaybeAddCluster(const std::string& name);
348  grpc_error_handle CreateMethodConfig(
349  const XdsRouteConfigResource::Route& route,
350  const XdsRouteConfigResource::Route::RouteAction::ClusterWeight*
351  cluster_weight,
352  RefCountedPtr<ServiceConfig>* method_config);
353 
354  RefCountedPtr<XdsResolver> resolver_;
355  RouteTable route_table_;
356  std::map<absl::string_view, RefCountedPtr<ClusterState>> clusters_;
357  std::vector<const grpc_channel_filter*> filters_;
358  };
359 
360  void OnListenerUpdate(XdsListenerResource listener);
361  void OnRouteConfigUpdate(XdsRouteConfigResource rds_update);
363  void OnResourceDoesNotExist(std::string context);
364 
365  absl::StatusOr<RefCountedPtr<ServiceConfig>> CreateServiceConfig();
366  void GenerateResult();
367  void MaybeRemoveUnusedClusters();
368  uint64_t channel_id() const { return channel_id_; }
369 
370  std::shared_ptr<WorkSerializer> work_serializer_;
371  std::unique_ptr<ResultHandler> result_handler_;
374  URI uri_;
375  RefCountedPtr<XdsClient> xds_client_;
379 
380  ListenerWatcher* listener_watcher_ = nullptr;
381  // This will not contain the RouteConfiguration, even if it comes with the
382  // LDS response; instead, the relevant VirtualHost from the
383  // RouteConfiguration will be saved in current_virtual_host_.
384  XdsListenerResource current_listener_;
385 
387  RouteConfigWatcher* route_config_watcher_ = nullptr;
388  XdsRouteConfigResource::VirtualHost current_virtual_host_;
389  std::map<std::string /*cluster_specifier_plugin_name*/,
390  std::string /*LB policy config*/>
392 
393  ClusterState::ClusterStateMap cluster_state_map_;
394 };
395 
396 //
397 // XdsResolver::XdsConfigSelector::Route
398 //
399 
400 bool MethodConfigsEqual(const ServiceConfig* sc1, const ServiceConfig* sc2) {
401  if (sc1 == nullptr) return sc2 == nullptr;
402  if (sc2 == nullptr) return false;
403  return sc1->json_string() == sc2->json_string();
404 }
405 
407  const ClusterWeightState& other) const {
408  return range_end == other.range_end && cluster == other.cluster &&
409  MethodConfigsEqual(method_config.get(), other.method_config.get());
410 }
411 
413  const Route& other) const {
414  return route == other.route &&
415  weighted_cluster_state == other.weighted_cluster_state &&
416  MethodConfigsEqual(method_config.get(), other.method_config.get());
417 }
418 
419 // Implementation of XdsRouting::RouteListIterator for getting the matching
420 // route for a request.
421 class XdsResolver::XdsConfigSelector::RouteListIterator
422  : public XdsRouting::RouteListIterator {
423  public:
424  explicit RouteListIterator(const RouteTable* route_table)
425  : route_table_(route_table) {}
426 
427  size_t Size() const override { return route_table_->size(); }
428 
429  const XdsRouteConfigResource::Route::Matchers& GetMatchersForRoute(
430  size_t index) const override {
431  return (*route_table_)[index].route.matchers;
432  }
433 
434  private:
435  const RouteTable* route_table_;
436 };
437 
438 //
439 // XdsResolver::XdsConfigSelector
440 //
441 
442 XdsResolver::XdsConfigSelector::XdsConfigSelector(
443  RefCountedPtr<XdsResolver> resolver, grpc_error_handle* error)
444  : resolver_(std::move(resolver)) {
446  gpr_log(GPR_INFO, "[xds_resolver %p] creating XdsConfigSelector %p",
447  resolver_.get(), this);
448  }
449  // 1. Construct the route table
450  // 2 Update resolver's cluster state map
451  // 3. Construct cluster list to hold on to entries in the cluster state
452  // map.
453  // Reserve the necessary entries up-front to avoid reallocation as we add
454  // elements. This is necessary because the string_view in the entry's
455  // weighted_cluster_state field points to the memory in the route field, so
456  // moving the entry in a reallocation will cause the string_view to point to
457  // invalid data.
458  route_table_.reserve(resolver_->current_virtual_host_.routes.size());
459  for (auto& route : resolver_->current_virtual_host_.routes) {
461  gpr_log(GPR_INFO, "[xds_resolver %p] XdsConfigSelector %p: route: %s",
462  resolver_.get(), this, route.ToString().c_str());
463  }
464  route_table_.emplace_back();
465  auto& route_entry = route_table_.back();
466  route_entry.route = route;
467  auto* route_action =
468  absl::get_if<XdsRouteConfigResource::Route::RouteAction>(
469  &route_entry.route.action);
470  if (route_action != nullptr) {
471  // If the route doesn't specify a timeout, set its timeout to the global
472  // one.
473  if (!route_action->max_stream_duration.has_value()) {
474  route_action->max_stream_duration =
475  resolver_->current_listener_.http_connection_manager
476  .http_max_stream_duration;
477  }
478  if (route_action->action.index() ==
479  XdsRouteConfigResource::Route::RouteAction::kClusterIndex) {
480  *error = CreateMethodConfig(route_entry.route, nullptr,
481  &route_entry.method_config);
482  MaybeAddCluster(absl::StrCat(
483  "cluster:",
484  absl::get<
485  XdsRouteConfigResource::Route::RouteAction::kClusterIndex>(
486  route_action->action)));
487  } else if (route_action->action.index() ==
488  XdsRouteConfigResource::Route::RouteAction::
489  kWeightedClustersIndex) {
490  auto& action_weighted_clusters = absl::get<
491  XdsRouteConfigResource::Route::RouteAction::kWeightedClustersIndex>(
492  route_action->action);
493  uint32_t end = 0;
494  for (const auto& weighted_cluster : action_weighted_clusters) {
495  Route::ClusterWeightState cluster_weight_state;
496  *error = CreateMethodConfig(route_entry.route, &weighted_cluster,
497  &cluster_weight_state.method_config);
498  if (!GRPC_ERROR_IS_NONE(*error)) return;
499  end += weighted_cluster.weight;
500  cluster_weight_state.range_end = end;
501  cluster_weight_state.cluster = weighted_cluster.name;
502  route_entry.weighted_cluster_state.push_back(
503  std::move(cluster_weight_state));
504  MaybeAddCluster(absl::StrCat("cluster:", weighted_cluster.name));
505  }
506  } else if (route_action->action.index() ==
507  XdsRouteConfigResource::Route::RouteAction::
508  kClusterSpecifierPluginIndex) {
509  // cluster_specifier_plugin case:
510  *error = CreateMethodConfig(route_entry.route, nullptr,
511  &route_entry.method_config);
512  MaybeAddCluster(absl::StrCat(
513  "cluster_specifier_plugin:",
514  absl::get<XdsRouteConfigResource::Route::RouteAction::
515  kClusterSpecifierPluginIndex>(route_action->action)));
516  }
517  }
518  }
519  // Populate filter list.
520  for (const auto& http_filter :
521  resolver_->current_listener_.http_connection_manager.http_filters) {
522  // Find filter. This is guaranteed to succeed, because it's checked
523  // at config validation time in the XdsApi code.
524  const XdsHttpFilterImpl* filter_impl =
525  XdsHttpFilterRegistry::GetFilterForType(
526  http_filter.config.config_proto_type_name);
527  GPR_ASSERT(filter_impl != nullptr);
528  // Add C-core filter to list.
529  if (filter_impl->channel_filter() != nullptr) {
530  filters_.push_back(filter_impl->channel_filter());
531  }
532  }
533 }
534 
535 XdsResolver::XdsConfigSelector::~XdsConfigSelector() {
537  gpr_log(GPR_INFO, "[xds_resolver %p] destroying XdsConfigSelector %p",
538  resolver_.get(), this);
539  }
540  clusters_.clear();
541  resolver_->MaybeRemoveUnusedClusters();
542 }
543 
544 grpc_error_handle XdsResolver::XdsConfigSelector::CreateMethodConfig(
545  const XdsRouteConfigResource::Route& route,
546  const XdsRouteConfigResource::Route::RouteAction::ClusterWeight*
547  cluster_weight,
548  RefCountedPtr<ServiceConfig>* method_config) {
549  std::vector<std::string> fields;
550  const auto& route_action =
551  absl::get<XdsRouteConfigResource::Route::RouteAction>(route.action);
552  // Set retry policy if any.
553  if (route_action.retry_policy.has_value() &&
554  !route_action.retry_policy->retry_on.Empty()) {
555  std::vector<std::string> retry_parts;
556  retry_parts.push_back(absl::StrFormat(
557  "\"retryPolicy\": {\n"
558  " \"maxAttempts\": %d,\n"
559  " \"initialBackoff\": \"%s\",\n"
560  " \"maxBackoff\": \"%s\",\n"
561  " \"backoffMultiplier\": 2,\n",
562  route_action.retry_policy->num_retries + 1,
563  route_action.retry_policy->retry_back_off.base_interval.ToJsonString(),
564  route_action.retry_policy->retry_back_off.max_interval.ToJsonString()));
565  std::vector<std::string> code_parts;
566  if (route_action.retry_policy->retry_on.Contains(GRPC_STATUS_CANCELLED)) {
567  code_parts.push_back(" \"CANCELLED\"");
568  }
569  if (route_action.retry_policy->retry_on.Contains(
571  code_parts.push_back(" \"DEADLINE_EXCEEDED\"");
572  }
573  if (route_action.retry_policy->retry_on.Contains(GRPC_STATUS_INTERNAL)) {
574  code_parts.push_back(" \"INTERNAL\"");
575  }
576  if (route_action.retry_policy->retry_on.Contains(
578  code_parts.push_back(" \"RESOURCE_EXHAUSTED\"");
579  }
580  if (route_action.retry_policy->retry_on.Contains(GRPC_STATUS_UNAVAILABLE)) {
581  code_parts.push_back(" \"UNAVAILABLE\"");
582  }
583  retry_parts.push_back(
584  absl::StrFormat(" \"retryableStatusCodes\": [\n %s ]\n",
585  absl::StrJoin(code_parts, ",\n")));
586  retry_parts.push_back(absl::StrFormat(" }"));
587  fields.emplace_back(absl::StrJoin(retry_parts, ""));
588  }
589  // Set timeout.
590  if (route_action.max_stream_duration.has_value() &&
591  (route_action.max_stream_duration != Duration::Zero())) {
592  fields.emplace_back(
593  absl::StrFormat(" \"timeout\": \"%s\"",
594  route_action.max_stream_duration->ToJsonString()));
595  }
596  // Handle xDS HTTP filters.
597  XdsRouting::GeneratePerHttpFilterConfigsResult result =
598  XdsRouting::GeneratePerHTTPFilterConfigs(
599  resolver_->current_listener_.http_connection_manager.http_filters,
600  resolver_->current_virtual_host_, route, cluster_weight,
602  if (!GRPC_ERROR_IS_NONE(result.error)) {
603  return result.error;
604  }
605  for (const auto& p : result.per_filter_configs) {
606  fields.emplace_back(absl::StrCat(" \"", p.first, "\": [\n",
607  absl::StrJoin(p.second, ",\n"),
608  "\n ]"));
609  }
610  // Construct service config.
612  if (!fields.empty()) {
613  std::string json = absl::StrCat(
614  "{\n"
615  " \"methodConfig\": [ {\n"
616  " \"name\": [\n"
617  " {}\n"
618  " ],\n"
619  " ",
620  absl::StrJoin(fields, ",\n"),
621  "\n } ]\n"
622  "}");
623  *method_config =
624  ServiceConfigImpl::Create(result.args, json.c_str(), &error);
625  }
627  return error;
628 }
629 
630 grpc_channel_args* XdsResolver::XdsConfigSelector::ModifyChannelArgs(
632  return args;
633 }
634 
635 void XdsResolver::XdsConfigSelector::MaybeAddCluster(const std::string& name) {
636  if (clusters_.find(name) == clusters_.end()) {
637  auto it = resolver_->cluster_state_map_.find(name);
638  if (it == resolver_->cluster_state_map_.end()) {
639  auto new_cluster_state = MakeRefCounted<ClusterState>(resolver_, name);
640  clusters_[new_cluster_state->cluster()] = std::move(new_cluster_state);
641  } else {
642  clusters_[it->second->cluster()] = it->second->Ref();
643  }
644  }
645 }
646 
647 absl::optional<uint64_t> HeaderHashHelper(
648  const XdsRouteConfigResource::Route::RouteAction::HashPolicy& policy,
649  grpc_metadata_batch* initial_metadata) {
650  GPR_ASSERT(policy.type ==
652  std::string value_buffer;
653  absl::optional<absl::string_view> header_value = XdsRouting::GetHeaderValue(
654  initial_metadata, policy.header_name, &value_buffer);
655  if (!header_value.has_value()) {
656  return absl::nullopt;
657  }
658  if (policy.regex != nullptr) {
659  // If GetHeaderValue() did not already store the value in
660  // value_buffer, copy it there now, so we can modify it.
661  if (header_value->data() != value_buffer.data()) {
662  value_buffer = std::string(*header_value);
663  }
664  RE2::GlobalReplace(&value_buffer, *policy.regex, policy.regex_substitution);
665  header_value = value_buffer;
666  }
667  return XXH64(header_value->data(), header_value->size(), 0);
668 }
669 
670 ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
671  GetCallConfigArgs args) {
672  auto route_index = XdsRouting::GetRouteForRequest(
673  RouteListIterator(&route_table_), StringViewFromSlice(*args.path),
674  args.initial_metadata);
675  if (!route_index.has_value()) {
676  return CallConfig();
677  }
678  auto& entry = route_table_[*route_index];
679  // Found a route match
680  const auto* route_action =
681  absl::get_if<XdsRouteConfigResource::Route::RouteAction>(
682  &entry.route.action);
683  if (route_action == nullptr) {
684  CallConfig call_config;
685  call_config.error =
687  "Matching route has inappropriate action"),
689  return call_config;
690  }
692  RefCountedPtr<ServiceConfig> method_config;
693  if (route_action->action.index() ==
694  XdsRouteConfigResource::Route::RouteAction::kClusterIndex) {
696  "cluster:",
697  absl::get<XdsRouteConfigResource::Route::RouteAction::kClusterIndex>(
698  route_action->action));
699  method_config = entry.method_config;
700  } else if (route_action->action.index() ==
701  XdsRouteConfigResource::Route::RouteAction::
702  kWeightedClustersIndex) {
703  const uint32_t key =
704  rand() %
705  entry.weighted_cluster_state[entry.weighted_cluster_state.size() - 1]
706  .range_end;
707  // Find the index in weighted clusters corresponding to key.
708  size_t mid = 0;
709  size_t start_index = 0;
710  size_t end_index = entry.weighted_cluster_state.size() - 1;
711  size_t index = 0;
712  while (end_index > start_index) {
713  mid = (start_index + end_index) / 2;
714  if (entry.weighted_cluster_state[mid].range_end > key) {
715  end_index = mid;
716  } else if (entry.weighted_cluster_state[mid].range_end < key) {
717  start_index = mid + 1;
718  } else {
719  index = mid + 1;
720  break;
721  }
722  }
723  if (index == 0) index = start_index;
724  GPR_ASSERT(entry.weighted_cluster_state[index].range_end > key);
725  cluster_name =
726  absl::StrCat("cluster:", entry.weighted_cluster_state[index].cluster);
727  method_config = entry.weighted_cluster_state[index].method_config;
728  } else if (route_action->action.index() ==
729  XdsRouteConfigResource::Route::RouteAction::
730  kClusterSpecifierPluginIndex) {
732  "cluster_specifier_plugin:",
733  absl::get<XdsRouteConfigResource::Route::RouteAction::
734  kClusterSpecifierPluginIndex>(route_action->action));
735  method_config = entry.method_config;
736  }
737  auto it = clusters_.find(cluster_name);
738  GPR_ASSERT(it != clusters_.end());
739  // Generate a hash.
741  for (const auto& hash_policy : route_action->hash_policies) {
742  absl::optional<uint64_t> new_hash;
743  switch (hash_policy.type) {
745  new_hash = HeaderHashHelper(hash_policy, args.initial_metadata);
746  break;
747  case XdsRouteConfigResource::Route::RouteAction::HashPolicy::CHANNEL_ID:
748  new_hash = resolver_->channel_id();
749  break;
750  default:
751  GPR_ASSERT(0);
752  }
753  if (new_hash.has_value()) {
754  // Rotating the old value prevents duplicate hash rules from cancelling
755  // each other out and preserves all of the entropy
756  const uint64_t old_value =
757  hash.has_value() ? ((hash.value() << 1) | (hash.value() >> 63)) : 0;
758  hash = old_value ^ new_hash.value();
759  }
760  // If the policy is a terminal policy and a hash has been generated,
761  // ignore the rest of the hash policies.
762  if (hash_policy.terminal && hash.has_value()) {
763  break;
764  }
765  }
766  if (!hash.has_value()) {
767  hash = absl::Uniform<uint64_t>(absl::BitGen());
768  }
769  CallConfig call_config;
770  if (method_config != nullptr) {
771  call_config.method_configs =
772  method_config->GetMethodParsedConfigVector(grpc_empty_slice());
773  call_config.service_config = std::move(method_config);
774  }
775  call_config.call_attributes[XdsClusterAttributeTypeName()] = it->first;
776  std::string hash_string = absl::StrCat(hash.value());
777  char* hash_value =
778  static_cast<char*>(args.arena->Alloc(hash_string.size() + 1));
779  memcpy(hash_value, hash_string.c_str(), hash_string.size());
780  hash_value[hash_string.size()] = '\0';
781  call_config.call_attributes[RequestHashAttributeName()] = hash_value;
782  call_config.call_dispatch_controller =
783  args.arena->New<XdsCallDispatchController>(it->second->Ref());
784  return call_config;
785 }
786 
787 //
788 // XdsResolver
789 //
790 
791 void XdsResolver::StartLocked() {
793  xds_client_ = XdsClient::GetOrCreate(args_, &error);
794  if (!GRPC_ERROR_IS_NONE(error)) {
796  "Failed to create xds client -- channel will remain in "
797  "TRANSIENT_FAILURE: %s",
799  std::string error_message;
802  absl::StrCat("Failed to create XdsClient: ", error_message));
803  Result result;
804  result.addresses = status;
805  result.service_config = std::move(status);
807  result_handler_->ReportResult(std::move(result));
809  return;
810  }
811  std::string resource_name_fragment(absl::StripPrefix(uri_.path(), "/"));
812  if (!uri_.authority().empty()) {
813  // target_uri.authority is set case
814  const auto* authority_config =
815  xds_client_->bootstrap().LookupAuthority(uri_.authority());
816  if (authority_config == nullptr) {
818  absl::StrCat("Invalid target URI -- authority not found for ",
819  uri_.authority().c_str()));
820  Result result;
821  result.addresses = status;
822  result.service_config = std::move(status);
824  result_handler_->ReportResult(std::move(result));
825  return;
826  }
827  std::string name_template =
828  authority_config->client_listener_resource_name_template;
829  if (name_template.empty()) {
830  name_template = absl::StrCat(
831  "xdstp://", URI::PercentEncodeAuthority(uri_.authority()),
832  "/envoy.config.listener.v3.Listener/%s");
833  }
835  name_template,
836  {{"%s", URI::PercentEncodePath(resource_name_fragment)}});
837  } else {
838  // target_uri.authority not set
839  absl::string_view name_template =
840  xds_client_->bootstrap()
841  .client_default_listener_resource_name_template();
842  if (name_template.empty()) {
843  name_template = "%s";
844  }
845  if (absl::StartsWith(name_template, "xdstp:")) {
846  resource_name_fragment = URI::PercentEncodePath(resource_name_fragment);
847  }
849  absl::StrReplaceAll(name_template, {{"%s", resource_name_fragment}});
850  }
852  gpr_log(GPR_INFO, "[xds_resolver %p] Started with lds_resource_name %s.",
853  this, lds_resource_name_.c_str());
854  }
855  grpc_pollset_set_add_pollset_set(xds_client_->interested_parties(),
857  auto watcher = MakeRefCounted<ListenerWatcher>(Ref());
858  listener_watcher_ = watcher.get();
859  XdsListenerResourceType::StartWatch(xds_client_.get(), lds_resource_name_,
860  std::move(watcher));
861 }
862 
863 void XdsResolver::ShutdownLocked() {
865  gpr_log(GPR_INFO, "[xds_resolver %p] shutting down", this);
866  }
867  if (xds_client_ != nullptr) {
868  if (listener_watcher_ != nullptr) {
869  XdsListenerResourceType::CancelWatch(
871  /*delay_unsubscription=*/false);
872  }
873  if (route_config_watcher_ != nullptr) {
874  XdsRouteConfigResourceType::CancelWatch(
876  /*delay_unsubscription=*/false);
877  }
878  grpc_pollset_set_del_pollset_set(xds_client_->interested_parties(),
880  xds_client_.reset();
881  }
882 }
883 
884 void XdsResolver::OnListenerUpdate(XdsListenerResource listener) {
886  gpr_log(GPR_INFO, "[xds_resolver %p] received updated listener data", this);
887  }
888  if (xds_client_ == nullptr) {
889  return;
890  }
891  if (listener.http_connection_manager.route_config_name !=
893  if (route_config_watcher_ != nullptr) {
894  XdsRouteConfigResourceType::CancelWatch(
896  /*delay_unsubscription=*/
897  !listener.http_connection_manager.route_config_name.empty());
898  route_config_watcher_ = nullptr;
899  }
901  std::move(listener.http_connection_manager.route_config_name);
902  if (!route_config_name_.empty()) {
903  current_virtual_host_.routes.clear();
904  auto watcher = MakeRefCounted<RouteConfigWatcher>(Ref());
906  XdsRouteConfigResourceType::StartWatch(
908  }
909  }
910  current_listener_ = std::move(listener);
911  if (route_config_name_.empty()) {
912  GPR_ASSERT(
913  current_listener_.http_connection_manager.rds_update.has_value());
914  OnRouteConfigUpdate(
915  std::move(*current_listener_.http_connection_manager.rds_update));
916  } else {
917  // HCM may contain newer filter config. We need to propagate the update as
918  // config selector to the channel
919  GenerateResult();
920  }
921 }
922 
923 namespace {
924 class VirtualHostListIterator : public XdsRouting::VirtualHostListIterator {
925  public:
926  explicit VirtualHostListIterator(
927  const std::vector<XdsRouteConfigResource::VirtualHost>* virtual_hosts)
928  : virtual_hosts_(virtual_hosts) {}
929 
930  size_t Size() const override { return virtual_hosts_->size(); }
931 
932  const std::vector<std::string>& GetDomainsForVirtualHost(
933  size_t index) const override {
934  return (*virtual_hosts_)[index].domains;
935  }
936 
937  private:
938  const std::vector<XdsRouteConfigResource::VirtualHost>* virtual_hosts_;
939 };
940 } // namespace
941 
942 void XdsResolver::OnRouteConfigUpdate(XdsRouteConfigResource rds_update) {
944  gpr_log(GPR_INFO, "[xds_resolver %p] received updated route config", this);
945  }
946  if (xds_client_ == nullptr) {
947  return;
948  }
949  // Find the relevant VirtualHost from the RouteConfiguration.
950  auto vhost_index = XdsRouting::FindVirtualHostForDomain(
951  VirtualHostListIterator(&rds_update.virtual_hosts),
953  if (!vhost_index.has_value()) {
954  OnError(
956  absl::UnavailableError(absl::StrCat("could not find VirtualHost for ",
958  " in RouteConfiguration")));
959  return;
960  }
961  // Save the virtual host in the resolver.
962  current_virtual_host_ = std::move(rds_update.virtual_hosts[*vhost_index]);
964  std::move(rds_update.cluster_specifier_plugin_map);
965  // Send a new result to the channel.
966  GenerateResult();
967 }
968 
970  gpr_log(GPR_ERROR, "[xds_resolver %p] received error from XdsClient: %s: %s",
971  this, std::string(context).c_str(), status.ToString().c_str());
972  if (xds_client_ == nullptr) return;
973  status =
975  Result result;
976  result.addresses = status;
977  result.service_config = std::move(status);
978  grpc_arg new_arg = xds_client_->MakeChannelArg();
979  result.args = grpc_channel_args_copy_and_add(args_, &new_arg, 1);
980  result_handler_->ReportResult(std::move(result));
981 }
982 
983 void XdsResolver::OnResourceDoesNotExist(std::string context) {
985  "[xds_resolver %p] LDS/RDS resource does not exist -- clearing "
986  "update and returning empty service config",
987  this);
988  if (xds_client_ == nullptr) {
989  return;
990  }
991  current_virtual_host_.routes.clear();
992  Result result;
993  result.addresses.emplace();
995  result.service_config = ServiceConfigImpl::Create(args_, "{}", &error);
996  GPR_ASSERT(*result.service_config != nullptr);
997  result.resolution_note = std::move(context);
999  result_handler_->ReportResult(std::move(result));
1000 }
1001 
1003 XdsResolver::CreateServiceConfig() {
1004  std::vector<std::string> clusters;
1005  for (const auto& cluster : cluster_state_map_) {
1006  absl::string_view child_name = cluster.first;
1007  if (absl::ConsumePrefix(&child_name, "cluster_specifier_plugin:")) {
1008  clusters.push_back(absl::StrFormat(
1009  " \"%s\":{\n"
1010  " \"childPolicy\": %s\n"
1011  " }",
1012  cluster.first,
1014  } else {
1015  absl::ConsumePrefix(&child_name, "cluster:");
1016  clusters.push_back(
1017  absl::StrFormat(" \"%s\":{\n"
1018  " \"childPolicy\":[ {\n"
1019  " \"cds_experimental\":{\n"
1020  " \"cluster\": \"%s\"\n"
1021  " }\n"
1022  " } ]\n"
1023  " }",
1024  cluster.first, child_name));
1025  }
1026  }
1027  std::vector<std::string> config_parts;
1028  config_parts.push_back(
1029  "{\n"
1030  " \"loadBalancingConfig\":[\n"
1031  " { \"xds_cluster_manager_experimental\":{\n"
1032  " \"children\":{\n");
1033  config_parts.push_back(absl::StrJoin(clusters, ",\n"));
1034  config_parts.push_back(
1035  " }\n"
1036  " } }\n"
1037  " ]\n"
1038  "}");
1039  std::string json = absl::StrJoin(config_parts, "");
1042  ServiceConfigImpl::Create(args_, json.c_str(), &error);
1043  if (!GRPC_ERROR_IS_NONE(error)) {
1046  }
1047  return result;
1048 }
1049 
1050 void XdsResolver::GenerateResult() {
1051  if (current_virtual_host_.routes.empty()) return;
1052  // First create XdsConfigSelector, which may add new entries to the cluster
1053  // state map, and then CreateServiceConfig for LB policies.
1055  auto config_selector = MakeRefCounted<XdsConfigSelector>(Ref(), &error);
1056  if (!GRPC_ERROR_IS_NONE(error)) {
1057  OnError("could not create ConfigSelector",
1060  return;
1061  }
1062  Result result;
1063  result.addresses.emplace();
1064  result.service_config = CreateServiceConfig();
1066  gpr_log(GPR_INFO, "[xds_resolver %p] generated service config: %s", this,
1067  result.service_config.ok()
1068  ? std::string((*result.service_config)->json_string()).c_str()
1069  : result.service_config.status().ToString().c_str());
1070  }
1071  grpc_arg new_args[] = {
1072  xds_client_->MakeChannelArg(),
1073  config_selector->MakeChannelArg(),
1074  };
1075  result.args =
1076  grpc_channel_args_copy_and_add(args_, new_args, GPR_ARRAY_SIZE(new_args));
1077  result_handler_->ReportResult(std::move(result));
1078 }
1079 
1080 void XdsResolver::MaybeRemoveUnusedClusters() {
1081  bool update_needed = false;
1082  for (auto it = cluster_state_map_.begin(); it != cluster_state_map_.end();) {
1083  RefCountedPtr<ClusterState> cluster_state = it->second->RefIfNonZero();
1084  if (cluster_state != nullptr) {
1085  ++it;
1086  } else {
1087  update_needed = true;
1088  it = cluster_state_map_.erase(it);
1089  }
1090  }
1091  if (update_needed && xds_client_ != nullptr) {
1092  // Send a new result to the channel.
1093  GenerateResult();
1094  }
1095 }
1096 
1097 //
1098 // Factory
1099 //
1100 
1101 class XdsResolverFactory : public ResolverFactory {
1102  public:
1103  absl::string_view scheme() const override { return "xds"; }
1104 
1105  bool IsValidUri(const URI& uri) const override {
1106  if (uri.path().empty() || uri.path().back() == '/') {
1108  "URI path does not contain valid data plane authority");
1109  return false;
1110  }
1111  return true;
1112  }
1113 
1114  std::string GetDefaultAuthority(const URI& uri) const override {
1115  return GetDefaultAuthorityInternal(uri);
1116  }
1117 
1118  OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
1119  if (!IsValidUri(args.uri)) return nullptr;
1120  return MakeOrphanable<XdsResolver>(std::move(args));
1121  }
1122 };
1123 
1124 } // namespace
1125 
1127  builder->resolver_registry()->RegisterResolverFactory(
1128  absl::make_unique<XdsResolverFactory>());
1129 }
1130 
1131 } // namespace grpc_core
grpc_arg
Definition: grpc_types.h:103
trace.h
grpc_channel_args_find_string
char * grpc_channel_args_find_string(const grpc_channel_args *args, const char *name)
Definition: channel_args.cc:441
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
xds_routing.h
grpc_core::UniqueTypeName::Factory::Create
UniqueTypeName Create()
Definition: unique_type_name.h:67
cluster_state_
RefCountedPtr< ClusterState > cluster_state_
Definition: xds_resolver.cc:301
regen-readme.it
it
Definition: regen-readme.py:15
orphanable.h
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
log.h
route_config_watcher_
RouteConfigWatcher * route_config_watcher_
Definition: xds_resolver.cc:387
core_configuration.h
metadata_batch.h
grpc_event_engine::experimental::slice_detail::operator==
bool operator==(const BaseSlice &a, const BaseSlice &b)
Definition: include/grpc/event_engine/slice.h:117
pos
int pos
Definition: libuv/docs/code/tty-gravity/main.c:11
GRPC_STATUS_UNAVAILABLE
@ GRPC_STATUS_UNAVAILABLE
Definition: include/grpc/impl/codegen/status.h:143
testing::internal::Equals
constexpr bool Equals(const char(&a)[N], const char(&b)[M])
Definition: googletest/googlemock/include/gmock/gmock-function-mocker.h:83
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
channel_fwd.h
rds_update
absl::optional< absl::StatusOr< XdsRouteConfigResource > > rds_update
Definition: xds_server_config_fetcher.cc:231
absl::StrFormat
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec< Args... > &format, const Args &... args)
Definition: abseil-cpp/absl/strings/str_format.h:338
cluster_state_map_
ClusterState::ClusterStateMap cluster_state_map_
Definition: xds_resolver.cc:393
grpc_core::XdsClusterAttributeTypeName
UniqueTypeName XdsClusterAttributeTypeName()
Definition: xds_resolver.cc:98
route
XdsRouteConfigResource::Route route
Definition: xds_resolver.cc:337
grpc_core::RequestHashAttributeName
UniqueTypeName RequestHashAttributeName()
Definition: ring_hash.cc:77
slice.h
grpc_core
Definition: call_metric_recorder.h:31
cluster_name
std::string cluster_name
Definition: xds_cluster_resolver.cc:91
grpc_core::CoreConfiguration::Builder
Definition: core_configuration.h:41
status_util.h
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
cluster_specifier_plugin_map_
std::map< std::string, std::string > cluster_specifier_plugin_map_
Definition: xds_resolver.cc:391
grpc_core::StringViewFromSlice
absl::string_view StringViewFromSlice(const grpc_slice &slice)
Definition: slice_internal.h:93
useful.h
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
xds_http_filters.h
xds_route_config.h
arena.h
range_end
uint32_t range_end
Definition: xds_resolver.cc:330
config_selector.h
status
absl::Status status
Definition: rls.cc:251
channel_id_
uint64_t channel_id_
Definition: xds_resolver.cc:378
GRPC_STATUS_CANCELLED
@ GRPC_STATUS_CANCELLED
Definition: include/grpc/impl/codegen/status.h:33
xds_resource_type_impl.h
route_config_name_
std::string route_config_name_
Definition: xds_resolver.cc:386
setup.name
name
Definition: setup.py:542
GRPC_STATUS_DEADLINE_EXCEEDED
@ GRPC_STATUS_DEADLINE_EXCEEDED
Definition: include/grpc/impl/codegen/status.h:53
absl::StripPrefix
ABSL_MUST_USE_RESULT absl::string_view StripPrefix(absl::string_view str, absl::string_view prefix)
Definition: abseil-cpp/absl/strings/strip.h:73
xds_manager.p
p
Definition: xds_manager.py:60
GRPC_STATUS_RESOURCE_EXHAUSTED
@ GRPC_STATUS_RESOURCE_EXHAUSTED
Definition: include/grpc/impl/codegen/status.h:76
xds_client_
RefCountedPtr< XdsClient > xds_client_
Definition: xds_resolver.cc:375
iterator
const typedef MCPhysReg * iterator
Definition: MCRegisterInfo.h:27
grpc_pollset_set_del_pollset_set
void grpc_pollset_set_del_pollset_set(grpc_pollset_set *bag, grpc_pollset_set *item)
Definition: pollset_set.cc:52
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
GRPC_ERROR_STR_DESCRIPTION
@ GRPC_ERROR_STR_DESCRIPTION
top-level textual description of this error
Definition: error.h:106
grpc_channel_args
Definition: grpc_types.h:132
GRPC_TRACE_FLAG_ENABLED
#define GRPC_TRACE_FLAG_ENABLED(f)
Definition: debug/trace.h:114
status.h
grpc_types.h
hash
uint64_t hash
Definition: ring_hash.cc:284
it_
ClusterStateMap::iterator it_
Definition: xds_resolver.cc:273
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
resolver_factory.h
DEBUG_LOCATION
#define DEBUG_LOCATION
Definition: debug_location.h:41
work_serializer_
std::shared_ptr< WorkSerializer > work_serializer_
Definition: xds_resolver.cc:370
GRPC_ARG_DEFAULT_AUTHORITY
#define GRPC_ARG_DEFAULT_AUTHORITY
Definition: grpc_types.h:251
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
profile_analyzer.builder
builder
Definition: profile_analyzer.py:159
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
current_listener_
XdsListenerResource current_listener_
Definition: xds_resolver.cc:384
absl::BitGen
random_internal::NonsecureURBGBase< random_internal::randen_engine< uint64_t > > BitGen
Definition: abseil-cpp/absl/random/random.h:121
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
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
filters_
std::vector< const grpc_channel_filter * > filters_
Definition: xds_resolver.cc:357
absl::StrJoin
std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, Formatter &&fmt)
Definition: abseil-cpp/absl/strings/str_join.h:239
cluster
absl::string_view cluster
Definition: xds_resolver.cc:331
absl::string_view::size
constexpr size_type size() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:277
absl::optional::has_value
constexpr bool has_value() const noexcept
Definition: abseil-cpp/absl/types/optional.h:461
re2::Result
TestInstance::Result Result
Definition: bloaty/third_party/re2/re2/testing/tester.cc:96
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
xds_client.h
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
work_serializer.h
xds_bootstrap.h
data_plane_authority_
std::string data_plane_authority_
Definition: xds_resolver.cc:377
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::optional< uint64_t >
pollset_set.h
clusters_
std::map< absl::string_view, RefCountedPtr< ClusterState > > clusters_
Definition: xds_resolver.cc:356
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
absl::get
constexpr T & get(variant< Types... > &v)
Definition: abseil-cpp/absl/types/variant.h:300
service_config_call_data.h
server_address.h
time.h
grpc_empty_slice
GPRAPI grpc_slice grpc_empty_slice(void)
Definition: slice/slice.cc:42
grpc_channel_args_copy
grpc_channel_args * grpc_channel_args_copy(const grpc_channel_args *src)
Definition: channel_args.cc:285
xds_listener.h
gen_gtest_pred_impl.HEADER
HEADER
Definition: bloaty/third_party/googletest/googletest/scripts/gen_gtest_pred_impl.py:59
interested_parties_
grpc_pollset_set * interested_parties_
Definition: xds_resolver.cc:373
error.h
ring_hash.h
XXH64
XXH_PUBLIC_API XXH64_hash_t XXH64(const void *input, size_t length, XXH64_hash_t seed)
Calculates the 64-bit hash of input using xxHash64.
slice_internal.h
resolver_
RefCountedPtr< XdsResolver > resolver_
Definition: xds_resolver.cc:198
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc_core::grpc_xds_resolver_trace
TraceFlag grpc_xds_resolver_trace(false, "xds_resolver")
grpc_core::RegisterXdsResolver
void RegisterXdsResolver(CoreConfiguration::Builder *builder)
Definition: xds_resolver.cc:1126
resolver_registry.h
GRPC_ERROR_CREATE_FROM_STATIC_STRING
#define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc)
Definition: error.h:291
resolver.h
route_table_
RouteTable route_table_
Definition: xds_resolver.cc:355
xxhash.h
weighted_cluster_state
std::vector< ClusterWeightState > weighted_cluster_state
Definition: xds_resolver.cc:339
absl::optional::value
constexpr const T & value() const &
Definition: abseil-cpp/absl/types/optional.h:475
GPR_ARRAY_SIZE
#define GPR_ARRAY_SIZE(array)
Definition: useful.h:129
debug_location.h
key
const char * key
Definition: hpack_parser_table.cc:164
grpc_core::UniqueTypeName
Definition: unique_type_name.h:56
lds_resource_name_
std::string lds_resource_name_
Definition: xds_resolver.cc:376
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_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
listener_watcher_
ListenerWatcher * listener_watcher_
Definition: xds_resolver.cc:380
uri_
URI uri_
Definition: xds_resolver.cc:374
profile_analyzer.fields
list fields
Definition: profile_analyzer.py:266
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
absl::random_internal::NonsecureURBGBase< random_internal::randen_engine< uint64_t > >
grpc_pollset_set_add_pollset_set
void grpc_pollset_set_add_pollset_set(grpc_pollset_set *bag, grpc_pollset_set *item)
Definition: pollset_set.cc:47
first
StrT first
Definition: cxa_demangle.cpp:4884
service_config_impl.h
current_virtual_host_
XdsRouteConfigResource::VirtualHost current_virtual_host_
Definition: xds_resolver.cc:388
absl::StrReplaceAll
std::string StrReplaceAll(absl::string_view s, strings_internal::FixedMapping replacements)
Definition: abseil-cpp/absl/strings/str_replace.cc:71
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
watcher
ClusterWatcher * watcher
Definition: cds.cc:148
dual_ref_counted.h
channel_args.h
virtual_hosts_
const std::vector< XdsRouteConfigResource::VirtualHost > * virtual_hosts_
Definition: xds_resolver.cc:938
service_config.h
GRPC_STATUS_INTERNAL
@ GRPC_STATUS_INTERNAL
Definition: include/grpc/impl/codegen/status.h:129
method_config
RefCountedPtr< ServiceConfig > method_config
Definition: xds_resolver.cc:332
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
context
grpc::ClientContext context
Definition: istio_echo_server_lib.cc:61
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::StatusOr
Definition: abseil-cpp/absl/status/statusor.h:187
grpc_error_get_str
bool grpc_error_get_str(grpc_error_handle err, grpc_error_strs which, std::string *s)
Returns false if the specified string is not set.
Definition: error.cc:659
uri_parser.h
iomgr_fwd.h
result_handler_
std::unique_ptr< ResultHandler > result_handler_
Definition: xds_resolver.cc:371
grpc_error
Definition: error_internal.h:42
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
grpc_metadata_batch
Definition: metadata_batch.h:1259
absl::string_view::data
constexpr const_pointer data() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:336
grpc_core::UniqueTypeName::Factory
Definition: unique_type_name.h:60
args_
const grpc_channel_args * args_
Definition: xds_resolver.cc:372
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
old_value
int old_value
Definition: abseil-cpp/absl/strings/internal/str_format/output.cc:30
error_utils.h
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
port_platform.h
absl::Uniform
absl::enable_if_t<!std::is_same< R, void >::value, R > Uniform(TagType tag, URBG &&urbg, R lo, R hi)
Definition: abseil-cpp/absl/random/distributions.h:123
absl::ConsumePrefix
ABSL_NAMESPACE_BEGIN bool ConsumePrefix(absl::string_view *str, absl::string_view expected)
Definition: abseil-cpp/absl/strings/strip.h:46


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