Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support RDS updates on the server #27851

Merged
merged 25 commits into from
Nov 19, 2021
Merged

Support RDS updates on the server #27851

merged 25 commits into from
Nov 19, 2021

Conversation

yashykt
Copy link
Member

@yashykt yashykt commented Oct 28, 2021

Note that graceful shutdown is still remaining.


This change is Reviewable

@yashykt yashykt changed the title Xds rds support Support RDS updates on the server Oct 28, 2021
@yashykt yashykt added the release notes: yes Indicates if PR needs to be in release notes label Oct 28, 2021
@yashykt yashykt marked this pull request as ready for review October 28, 2021 16:41
Copy link
Member

@markdroth markdroth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's my partial review, as we discussed. I haven't reviewed the tests yet.

Please let me know if you have any questions. Thanks!

Reviewed 22 of 25 files at r1, 4 of 5 files at r2, 2 of 2 files at r3, all commit messages.
Reviewable status: 24 of 25 files reviewed, 27 unresolved discussions (waiting on @markdroth and @yashykt)


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 625 at r1 (raw file):

    GetCallConfigArgs args) {
  for (const auto& entry : route_table_) {
    // Path matching.

How about moving this route selection logic into the XdsRouting API as well, since it should be common between client and server? The code for deciding what to do with the selected route will still be different, but the code to select the route itself could be the same.

What I'm thinking is that instead of having XdsRouting expose HeadersMatch() and UnderFraction(), we could instead have it expose a GetRouteForRequest() method. This could work similar to the virtual host iteration interface that I suggested in xds_routing.h (see my comment there for details). For example:

class RouteListIterator {
 public:
  virtual ~RouteListIterator() = default;
  // Number of routes.
  virtual size_t Size() const = 0;
  // Returns the matchers for the route at the specified index.
  virtual const XdsApi::Route::Matchers& GetMatchersForRoute(size_t index) const = 0;
};

// Returns the index in route_list_iterator to use for a request with
// the specified path and metadata, or nullopt if no route matches.
static absl::optional<size_t> GetRouteForRequest(
    RouteListIterator* route_list_iterator,
    absl::string_view path, grpc_metadata_batch* initial_metadata) {
  for (size_t i = 0; i < route_list_iterator->Size(); ++i) {
    const XdsApi::Route::Matchers& matchers =
        route_list_iterator->GetMatchersForRoute(i);
    if (matchers.path_matcher.Match(path) &&
        HeadersMatch(matchers.header_matchers, initial_metadata) &&
        (!matchers.fraction_per_million.has_value() ||
         UnderFraction(*matchers.fraction_per_million))) {
      return i;
    }
  }
  return absl::nullopt;
}

src/core/ext/xds/xds_api.cc, line 2329 at r1 (raw file):

            "router", {kXdsHttpRouterFilterConfigName, Json()}});
  }
  // Guarding parsing of RouteConfig on the server side with the environmental

I think we still want this env var guard until all of the server-side pieces are in place.


src/core/ext/xds/xds_client.cc, line 870 at r1 (raw file):

  auto& state = state_map_[type_url].subscribed_resources[name];
  if (state == nullptr) {
    state = MakeOrphanable<ResourceState>(type_url, name, false);

Let's merge #27860 before this PR, so we can get the right fix in place here.


src/core/ext/xds/xds_routing.h, line 38 at r1 (raw file):

 public:
  template <typename T>
  static T* FindVirtualHostForDomain(std::vector<T>* virtual_hosts,

Instead of making this a template, how about defining an abstract interface for the virtual host object that this acts on:

class VirtualHostListIterator {
 public:
  virtual ~VirtualHostListIterator() = default;
  // Returns the number of virtual hosts in the list.
  virtual size_t Size() const = 0;
  // Returns the domain list for the virtual host at the specified index.
  virtual const std::set<std::string>& GetDomainsForVirtualHost(size_t index) const = 0;
};

// Returns the index of the selected virtual host in the list.
static absl::optional<size_t> FindVirtualHostForDomain(
    VirtualHostListIterator* vhost_iterator,
    absl::string_view domain) {
  absl::optional<size_t> target_index;
  for (size_t i = 0; i < vhost_iterator->Size(); ++i) {
    const std::set<std::string> domains = vhost_iterator->GetDomainsForVirtualHost(i);
    for (const std::string& domain_pattern : domains) {
      // ...update target_index instead of target_vhost...
    }
  }  
  return target_index;
}

Then callers can just wrap their lists of virtual hosts of whatever type in their own implementation of VirtualHostListIterator.


src/core/ext/xds/xds_routing.h, line 38 at r1 (raw file):

 public:
  template <typename T>
  static T* FindVirtualHostForDomain(std::vector<T>* virtual_hosts,

How about passing in virtual_hosts as a reference instead of a pointer, given that it should never be null?

(No longer relevant if you take my previous suggestion.)


src/core/ext/xds/xds_routing.h, line 99 at r1 (raw file):

 private:
  enum MatchType {

All of this private stuff can be in an anonymous namespace in the .cc file, since it's all static anyway.


src/core/ext/xds/xds_server_config_fetcher.cc, line 50 at r3 (raw file):

class XdsServerConfigFetcher : public grpc_server_config_fetcher {
 public:
  class FilterChainMatchManager

There are a lot of classes here that interact with each other in complex ways, and it makes the code hard to understand for someone who is first approaching it. I have a couple of suggestions to try to help future readers understand the code better.

First, where possible, I think it would make this code more readable to use forward declarations to move class definitions out of the enclosing class, like this:

class XdsServerConfigFetcher : public grpc_server_config_fetcher {
 public:
  class FilterChainMatchManager;  // Forward declaration.
  // ...other members...
};

class XdsServerConfigFetcher::FilterChainMatchManager
    : public grpc_server_config_fetcher::ConnectionManager {
 public:
  // ...members...
};

This makes it easier for the reader to see each class by itself, without having to understand each nested class at the same time.

Second, please add a comment before each class explaining what it is and how it interacts with other classes. For example, for FilterChainMatchManager, you can say something like this:

"""
A connection manager used by the server listener code to inject channel args to be used for each incoming connection. This implementation chooses the appropriate filter chain from the xDS Listener resource and injects channel args that configure the right mTLS certs and cause the right set of HTTP filters to be injected.
"""


src/core/ext/xds/xds_server_config_fetcher.cc, line 101 at r3 (raw file):

  };

  class RdsUpdateWatcherInterface {

Now that we're not exposing an L7-level watcher API as a part of the server config fetcher API (i.e., it's now invisible to all code except the code in this file), I don't think we actually need this to be an interface anymore. At this point, it looks like the only users of this interface are ListenerWatcher and XdsServerConfigSelectorProvider, and those classes are effectively part of the implementation of XdsServerConfigFetcher, so I don't think we actually need an abstraction between them anymore.

Instead, I think we should just allow ListenerWatcher and XdsServerConfigSelectorProvider to directly modify the internal state of XdsServerConfigFetcher. Note that ListenerWatcher is already nested within XdsServerConfigFetcher, so it can already do that; we'd just need to move XdsServerConfigSelectorProvider inside of XdsServerConfigFetcher as well, so that it can do the same thing.

I think that the RdsUpdateWatcherState struct can wind up looking something like this:

  struct RdsUpdateWatcherState {
    RouteConfigWatcher* route_config_watcher = nullptr;
    absl::optional<absl::StatusOr<XdsApi::RdsUpdate>> rds_update;
    // The set of providers that need to be notified when this RDS resource gets updated.
    // Providers will be added here when they are created, and they will automatically
    // remove themselves when they are destroyed.
    // When this becomes empty, the xDS watch can be stopped.
    std::set<XdsServerConfigSelectorProvider*> providers;
  };

I think the code will wind up being much simpler that way, with a lot less bookkeeping.

Hmmm... Alternatively, remind me why we don't just have each XdsServerConfigSelectorProvider start its own RDS watch on the XdsClient directly? That would use the existing watching mechanism instead of building a new one here, which might be even simpler.


src/core/ext/xds/xds_server_config_fetcher.cc, line 192 at r3 (raw file):

  class RouteConfigWatcher : public XdsClient::RouteConfigWatcherInterface {
   public:
    explicit RouteConfigWatcher(

No need for explicit.


src/core/ext/xds/xds_server_config_fetcher.cc, line 220 at r3 (raw file):

  // A fire and forget class to start watching on route config data from
  // XdsClient via ExecCtx

Instead of hopping into the ExecCtx before we call back into the XdsClient, I suggest that we do the reverse: change ListenerWatcher and RouteConfigWatcher to hop into the ExecCtx before delivering updates from the XdsClient to us. That way, if we need to call back into the XdsClient (e.g., to start an RDS watch when we get an LDS update), we know that it's safe to do so.

I think this approach has a number of advantages:

  • It's consistent with how we do things on the client side. In the xds resolver, every notification from an LDS or RDS watcher creates a fire-and-forget Notifier object, which takes a ref to the XdsResolver and then hops into the ExecCtx and then the WorkSerializer to deliver the notification. We could do essentially the same thing here, except that the notifier would hold a ref to the XdsServerConfigFetcher instead of the XdsResolver, and it would hop into the ExecCtx but not the WorkSerializer.
  • It's simpler to implement, because you can use one notifier class for all notifications from either resource type. You would not need separate implementations for RouteConfigWatchStarter and RdsWatchCanceller. (And minimizing the number of classes here would help make this code more understandable.)
  • It minimizes the amount of code run while holding the XdsClient's internal lock, which is probably better for lock contention.

src/core/ext/xds/xds_server_config_fetcher.cc, line 271 at r3 (raw file):

}

class XdsServerConfigSelector : public ServerConfigSelector {

Please move this inside of XdsServerConfigSelectorProvider (in the private section), since it's not needed outside of that class.


src/core/ext/xds/xds_server_config_fetcher.cc, line 302 at r3 (raw file):

        http_filters) {
  auto config_selector = MakeRefCounted<XdsServerConfigSelector>();
  for (auto& vhost : rds_update.virtual_hosts) {

This looks remarkably similar to the client-side code in the XdsResolver::XdsConfigSelector ctor. Can we refactor any of this into the XdsRouting API?


src/core/ext/xds/xds_server_config_fetcher.cc, line 303 at r3 (raw file):

  auto config_selector = MakeRefCounted<XdsServerConfigSelector>();
  for (auto& vhost : rds_update.virtual_hosts) {
    config_selector->virtual_hosts_.push_back(VirtualHost());

This can just say:

config_selector->virtual_hosts_.emplace_back();

src/core/ext/xds/xds_server_config_fetcher.cc, line 307 at r3 (raw file):

    virtual_host.domains = std::move(vhost.domains);
    for (auto& route : vhost.routes) {
      virtual_host.routes.push_back(VirtualHost::Route());

Same here:

virtual_host.routes.emplace_back();

src/core/ext/xds/xds_server_config_fetcher.cc, line 401 at r3 (raw file):

    return call_config;
  }
  for (const auto& route : virtual_host->routes) {

As mentioned elsewhere, it would be nice if this route-selection logic was in the XdsRouting API.


src/core/ext/xds/xds_server_config_fetcher.cc, line 435 at r3 (raw file):

// A fire and forget class to cancel watching on Rds from XdsServerConfigFetcher
// via ExecCtx
class RdsWatchCanceller {

This should be nested inside of XdsServerConfigFetcher.


src/core/ext/xds/xds_server_config_fetcher.cc, line 469 at r3 (raw file):

// StaticXdsServerConfigSelectorProvider and
// DynamicXdsServerConfigSelectorProvider.
class XdsServerConfigSelectorProvider : public ServerConfigSelectorProvider {

This and both of its subclasses should be nested inside of XdsServerConfigFetcher.


src/core/ext/xds/xds_server_config_fetcher.cc, line 526 at r3 (raw file):

      : http_filters_(std::move(http_filters)) {}

  void set_resource(absl::StatusOr<XdsApi::RdsUpdate> resource) {

This seems a little ugly. Is there a way that we can restructure this such that this is not needed, such as maybe storing the resource in each subclass instead of in the base class? Or maybe if we eliminate RdsUpdateWatcherInterface as I suggested above, there will no longer be a need to have a common base class for the static and dynamic providers.

If we keep this, it should probably be protected, since it's only needed by a subclass.


src/core/ext/xds/xds_server_config_fetcher.cc, line 890 at r3 (raw file):

XdsServerConfigFetcher::ListenerWatcher::RdsUpdateWatcher::RdsUpdateWatcher(
    std::string resource_name, ListenerWatcher* parent)
    : resource_name_(resource_name), parent_(parent) {}

std::move(resource_name)


src/core/ext/xds/xds_server_config_fetcher.cc, line 896 at r3 (raw file):

  {
    MutexLock lock(&parent_->mu_);
    for (auto it = parent_->pending_rds_updates_.begin();

This would be much simpler if pending_rds_updates_ was std::set<> instead of std::vector<>.


src/core/ext/xds/xds_server_config_fetcher.cc, line 918 at r3 (raw file):

    std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
        server_config_watcher,
    // grpc_channel_args* args,

Please remove.


src/core/ext/xds/xds_server_config_fetcher.cc, line 966 at r3 (raw file):

          listener.default_filter_chain ==
              filter_chain_match_manager_->default_filter_chain())) {
      // TODO(): Maybe change LdsUpdate to provide a vector of

I don't think we want to do that. We want the LdsUpdate struct to be close to the structure of the underlying Listener proto, so that it's easy for people to understand where it came from when they see it in logs.

I think it's fine to do the conversion here.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1094 at r3 (raw file):

void XdsServerConfigFetcher::RouteConfigWatcher::OnRouteConfigChanged(
    XdsApi::RdsUpdate route_config) {
  ReleasableMutexLock lock(&server_config_fetcher_->rds_mu_);

I generally find code more readable when I avoid ReleaseableMutexLock. I suggest moving this check into Update(), which would be renamed to MaybeUpdate():

// Returns false if all refs have already been dropped.
bool XdsServerConfigFetcher::RouteConfigWatcher::MaybeUpdate(
    absl::StatusOr<XdsApi::RdsUpdate> rds_update) {
  MutexLock lock(&server_config_fetcher_->rds_mu_);
  auto it = server_config_fetcher_->rds_watchers_.find(resource_name_);
  if (it == server_config_fetcher_->rds_watchers_.end()) return false;
  // ...do update...
  return true;
}

Then the code here can just do this:

if (!MaybeUpdate(std::move(route_config))) {
  // All listener refs have already been dropped. Cancel the watch.
  server_config_fetcher_->xds_client_->CancelRouteConfigDataWatch(
      resource_name_, this, false);
}

We can use the same pattern in OnError() and OnResourceDoesNotExist(), so this approach winds up avoiding some code duplication as well.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1177 at r3 (raw file):

  {
    MutexLock lock(&self->server_config_fetcher_->rds_mu_);
    auto rds_watcher_state_it =

This can just be called it.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1272 at r3 (raw file):

  {
    MutexLock lock(&rds_mu_);
    auto rds_watcher_state_it = rds_watchers_.find(std::string(resource_name));

This can just be called it.


src/core/lib/surface/server.h, line 468 at r3 (raw file):

struct grpc_server_config_fetcher
    : public grpc_core::RefCounted<grpc_server_config_fetcher> {

Isn't there still one clear external owner of this? If so, it probably wants to be InternallyRefCounted<> instead of RefCounted<>.


src/core/lib/surface/server.cc, line 1608 at r3 (raw file):

  GRPC_API_TRACE("grpc_server_config_fetcher_destroy(config_fetcher=%p)", 1,
                 (server_config_fetcher));
  delete server_config_fetcher;

If the config fetcher is going to be ref-counted now, then I don't think it's okay to just destroy it here; instead, we should unref it (or orphan it, if you take my suggestion elsewhere to make it InternallyRefCounted<>).

Copy link
Member Author

@yashykt yashykt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 3 of 27 files reviewed, 27 unresolved discussions (waiting on @markdroth and @yashykt)


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 625 at r1 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

How about moving this route selection logic into the XdsRouting API as well, since it should be common between client and server? The code for deciding what to do with the selected route will still be different, but the code to select the route itself could be the same.

What I'm thinking is that instead of having XdsRouting expose HeadersMatch() and UnderFraction(), we could instead have it expose a GetRouteForRequest() method. This could work similar to the virtual host iteration interface that I suggested in xds_routing.h (see my comment there for details). For example:

class RouteListIterator {
 public:
  virtual ~RouteListIterator() = default;
  // Number of routes.
  virtual size_t Size() const = 0;
  // Returns the matchers for the route at the specified index.
  virtual const XdsApi::Route::Matchers& GetMatchersForRoute(size_t index) const = 0;
};

// Returns the index in route_list_iterator to use for a request with
// the specified path and metadata, or nullopt if no route matches.
static absl::optional<size_t> GetRouteForRequest(
    RouteListIterator* route_list_iterator,
    absl::string_view path, grpc_metadata_batch* initial_metadata) {
  for (size_t i = 0; i < route_list_iterator->Size(); ++i) {
    const XdsApi::Route::Matchers& matchers =
        route_list_iterator->GetMatchersForRoute(i);
    if (matchers.path_matcher.Match(path) &&
        HeadersMatch(matchers.header_matchers, initial_metadata) &&
        (!matchers.fraction_per_million.has_value() ||
         UnderFraction(*matchers.fraction_per_million))) {
      return i;
    }
  }
  return absl::nullopt;
}

Done.


src/core/ext/xds/xds_api.cc, line 2329 at r1 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

I think we still want this env var guard until all of the server-side pieces are in place.

Done.


src/core/ext/xds/xds_routing.h, line 38 at r1 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Instead of making this a template, how about defining an abstract interface for the virtual host object that this acts on:

class VirtualHostListIterator {
 public:
  virtual ~VirtualHostListIterator() = default;
  // Returns the number of virtual hosts in the list.
  virtual size_t Size() const = 0;
  // Returns the domain list for the virtual host at the specified index.
  virtual const std::set<std::string>& GetDomainsForVirtualHost(size_t index) const = 0;
};

// Returns the index of the selected virtual host in the list.
static absl::optional<size_t> FindVirtualHostForDomain(
    VirtualHostListIterator* vhost_iterator,
    absl::string_view domain) {
  absl::optional<size_t> target_index;
  for (size_t i = 0; i < vhost_iterator->Size(); ++i) {
    const std::set<std::string> domains = vhost_iterator->GetDomainsForVirtualHost(i);
    for (const std::string& domain_pattern : domains) {
      // ...update target_index instead of target_vhost...
    }
  }  
  return target_index;
}

Then callers can just wrap their lists of virtual hosts of whatever type in their own implementation of VirtualHostListIterator.

Templates seem more compact here since the types can already be iterated on. Suggestion taken anyway since the abstraction seems nice to have.


src/core/ext/xds/xds_routing.h, line 38 at r1 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

How about passing in virtual_hosts as a reference instead of a pointer, given that it should never be null?

(No longer relevant if you take my previous suggestion.)

outdated


src/core/ext/xds/xds_routing.h, line 99 at r1 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

All of this private stuff can be in an anonymous namespace in the .cc file, since it's all static anyway.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 50 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

There are a lot of classes here that interact with each other in complex ways, and it makes the code hard to understand for someone who is first approaching it. I have a couple of suggestions to try to help future readers understand the code better.

First, where possible, I think it would make this code more readable to use forward declarations to move class definitions out of the enclosing class, like this:

class XdsServerConfigFetcher : public grpc_server_config_fetcher {
 public:
  class FilterChainMatchManager;  // Forward declaration.
  // ...other members...
};

class XdsServerConfigFetcher::FilterChainMatchManager
    : public grpc_server_config_fetcher::ConnectionManager {
 public:
  // ...members...
};

This makes it easier for the reader to see each class by itself, without having to understand each nested class at the same time.

Second, please add a comment before each class explaining what it is and how it interacts with other classes. For example, for FilterChainMatchManager, you can say something like this:

"""
A connection manager used by the server listener code to inject channel args to be used for each incoming connection. This implementation chooses the appropriate filter chain from the xDS Listener resource and injects channel args that configure the right mTLS certs and cause the right set of HTTP filters to be injected.
"""

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 101 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Now that we're not exposing an L7-level watcher API as a part of the server config fetcher API (i.e., it's now invisible to all code except the code in this file), I don't think we actually need this to be an interface anymore. At this point, it looks like the only users of this interface are ListenerWatcher and XdsServerConfigSelectorProvider, and those classes are effectively part of the implementation of XdsServerConfigFetcher, so I don't think we actually need an abstraction between them anymore.

Instead, I think we should just allow ListenerWatcher and XdsServerConfigSelectorProvider to directly modify the internal state of XdsServerConfigFetcher. Note that ListenerWatcher is already nested within XdsServerConfigFetcher, so it can already do that; we'd just need to move XdsServerConfigSelectorProvider inside of XdsServerConfigFetcher as well, so that it can do the same thing.

I think that the RdsUpdateWatcherState struct can wind up looking something like this:

  struct RdsUpdateWatcherState {
    RouteConfigWatcher* route_config_watcher = nullptr;
    absl::optional<absl::StatusOr<XdsApi::RdsUpdate>> rds_update;
    // The set of providers that need to be notified when this RDS resource gets updated.
    // Providers will be added here when they are created, and they will automatically
    // remove themselves when they are destroyed.
    // When this becomes empty, the xDS watch can be stopped.
    std::set<XdsServerConfigSelectorProvider*> providers;
  };

I think the code will wind up being much simpler that way, with a lot less bookkeeping.

Hmmm... Alternatively, remind me why we don't just have each XdsServerConfigSelectorProvider start its own RDS watch on the XdsClient directly? That would use the existing watching mechanism instead of building a new one here, which might be even simpler.

Outdated. Using newer approach as discussed offline.


src/core/ext/xds/xds_server_config_fetcher.cc, line 192 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

No need for explicit.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 220 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Instead of hopping into the ExecCtx before we call back into the XdsClient, I suggest that we do the reverse: change ListenerWatcher and RouteConfigWatcher to hop into the ExecCtx before delivering updates from the XdsClient to us. That way, if we need to call back into the XdsClient (e.g., to start an RDS watch when we get an LDS update), we know that it's safe to do so.

I think this approach has a number of advantages:

  • It's consistent with how we do things on the client side. In the xds resolver, every notification from an LDS or RDS watcher creates a fire-and-forget Notifier object, which takes a ref to the XdsResolver and then hops into the ExecCtx and then the WorkSerializer to deliver the notification. We could do essentially the same thing here, except that the notifier would hold a ref to the XdsServerConfigFetcher instead of the XdsResolver, and it would hop into the ExecCtx but not the WorkSerializer.
  • It's simpler to implement, because you can use one notifier class for all notifications from either resource type. You would not need separate implementations for RouteConfigWatchStarter and RdsWatchCanceller. (And minimizing the number of classes here would help make this code more understandable.)
  • It minimizes the amount of code run while holding the XdsClient's internal lock, which is probably better for lock contention.

Outdated. Using the newer WorkSerializer as discussed.


src/core/ext/xds/xds_server_config_fetcher.cc, line 271 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Please move this inside of XdsServerConfigSelectorProvider (in the private section), since it's not needed outside of that class.

Outdated. XdsServerConfigSelectorProvider is no longer a thing. XdsServerConfigSelector is now used by the two independent classes StaticXdsServerConfigSelectorProvider and DyanmicXdsServerConfigSelectorProvider....


src/core/ext/xds/xds_server_config_fetcher.cc, line 302 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This looks remarkably similar to the client-side code in the XdsResolver::XdsConfigSelector ctor. Can we refactor any of this into the XdsRouting API?

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 303 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This can just say:

config_selector->virtual_hosts_.emplace_back();

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 307 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Same here:

virtual_host.routes.emplace_back();

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 401 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

As mentioned elsewhere, it would be nice if this route-selection logic was in the XdsRouting API.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 435 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This should be nested inside of XdsServerConfigFetcher.

outdated


src/core/ext/xds/xds_server_config_fetcher.cc, line 469 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This and both of its subclasses should be nested inside of XdsServerConfigFetcher.

Moved these under FilterChainMatchManager since that's where all these are used. The nesting is getting out of hand though. I'm not sure this nesting is buying us much.


src/core/ext/xds/xds_server_config_fetcher.cc, line 526 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This seems a little ugly. Is there a way that we can restructure this such that this is not needed, such as maybe storing the resource in each subclass instead of in the base class? Or maybe if we eliminate RdsUpdateWatcherInterface as I suggested above, there will no longer be a need to have a common base class for the static and dynamic providers.

If we keep this, it should probably be protected, since it's only needed by a subclass.

Removed the parent class


src/core/ext/xds/xds_server_config_fetcher.cc, line 890 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

std::move(resource_name)

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 896 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This would be much simpler if pending_rds_updates_ was std::set<> instead of std::vector<>.

outdated


src/core/ext/xds/xds_server_config_fetcher.cc, line 918 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Please remove.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 966 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

I don't think we want to do that. We want the LdsUpdate struct to be close to the structure of the underlying Listener proto, so that it's easy for people to understand where it came from when they see it in logs.

I think it's fine to do the conversion here.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1094 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

I generally find code more readable when I avoid ReleaseableMutexLock. I suggest moving this check into Update(), which would be renamed to MaybeUpdate():

// Returns false if all refs have already been dropped.
bool XdsServerConfigFetcher::RouteConfigWatcher::MaybeUpdate(
    absl::StatusOr<XdsApi::RdsUpdate> rds_update) {
  MutexLock lock(&server_config_fetcher_->rds_mu_);
  auto it = server_config_fetcher_->rds_watchers_.find(resource_name_);
  if (it == server_config_fetcher_->rds_watchers_.end()) return false;
  // ...do update...
  return true;
}

Then the code here can just do this:

if (!MaybeUpdate(std::move(route_config))) {
  // All listener refs have already been dropped. Cancel the watch.
  server_config_fetcher_->xds_client_->CancelRouteConfigDataWatch(
      resource_name_, this, false);
}

We can use the same pattern in OnError() and OnResourceDoesNotExist(), so this approach winds up avoiding some code duplication as well.

outdated


src/core/ext/xds/xds_server_config_fetcher.cc, line 1177 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This can just be called it.

outdated


src/core/ext/xds/xds_server_config_fetcher.cc, line 1272 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This can just be called it.

outdated


src/core/lib/surface/server.h, line 468 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Isn't there still one clear external owner of this? If so, it probably wants to be InternallyRefCounted<> instead of RefCounted<>.

outdated


src/core/lib/surface/server.cc, line 1608 at r3 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

If the config fetcher is going to be ref-counted now, then I don't think it's okay to just destroy it here; instead, we should unref it (or orphan it, if you take my suggestion elsewhere to make it InternallyRefCounted<>).

outdated

Copy link
Member Author

@yashykt yashykt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 27 files reviewed, 27 unresolved discussions (waiting on @markdroth)


src/core/ext/xds/xds_client.cc, line 870 at r1 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Let's merge #27860 before this PR, so we can get the right fix in place here.

Done.

Copy link
Member

@markdroth markdroth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking really good! Remaining comments are mostly minor things, no significant structural concerns.

Please let me know if you have any questions. Thanks!

Reviewed 1 of 21 files at r5, 2 of 7 files at r6, 22 of 24 files at r7, 3 of 3 files at r8, all commit messages.
Reviewable status: all files reviewed, 44 unresolved discussions (waiting on @yashykt)


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 334 at r7 (raw file):

    : public XdsRouting::RouteListIterator {
 public:
  RouteListIterator(const RouteTable& route_table)

explicit


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 334 at r7 (raw file):

    : public XdsRouting::RouteListIterator {
 public:
  RouteListIterator(const RouteTable& route_table)

Suggest making this parameter and the corresponding data member be pointers instead of references, so emphasize that there is external ownership.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 565 at r7 (raw file):

      RouteListIterator(route_table_), StringViewFromSlice(*args.path),
      args.initial_metadata);
  if (route_index.has_value()) {

Suggest handling the error case first, to keep the error condition and the error result next to each other, and to avoid unnecessary indentation for the rest of the function:

if (!route_index.has_value()) return CallConfig();

src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 566 at r7 (raw file):

      args.initial_metadata);
  if (route_index.has_value()) {
    auto& entry = route_table_[route_index.value()];

Can say *route_index here.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 748 at r7 (raw file):

namespace {
// TODO(): Should this be moved to xds_api.h?

No, I think this is the right place for it. If we ever need to use it somewhere else, we can consider moving it at that point.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 751 at r7 (raw file):

class VirtualHostListIterator : public XdsRouting::VirtualHostListIterator {
 public:
  VirtualHostListIterator(

explicit


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 752 at r7 (raw file):

 public:
  VirtualHostListIterator(
      const std::vector<XdsApi::RdsUpdate::VirtualHost>& virtual_hosts)

Suggest making this parameter and the corresponding data member be a pointer instead of a reference, to emphasize that it's externally owned.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 785 at r7 (raw file):

  // Save the virtual host in the resolver.
  current_virtual_host_ =
      std::move(rds_update.virtual_hosts[vhost_index.value()]);

Can use *vhost_index here.


src/core/ext/xds/xds_routing.h, line 38 at r1 (raw file):

Previously, yashykt (Yash Tibrewal) wrote…

Templates seem more compact here since the types can already be iterated on. Suggestion taken anyway since the abstraction seems nice to have.

Thanks, this looks good.

The main reason I suggested this is that we've been getting a lot of user input lately about our binary size going up fairly quickly. The more templated code we have, the more we multiply our binary size (because we generate the same code once for each unique template expansion). Using this iterator interface avoids that problem.


src/core/ext/xds/xds_routing.h, line 81 at r7 (raw file):

  struct GeneratePerHttpFilterConfigsResult {
    std::map<std::string, std::vector<std::string>>
        per_filter_configs;  // Map of field name to list of elements for that

Suggest moving these per-field comments to the line above the field they describe, since that should be more readable.


src/core/ext/xds/xds_routing.cc, line 98 at r7 (raw file):

}  // namespace

absl::optional<size_t> XdsRouting::GetRouteForRequest(

Please define these methods in the same order in which they are defined in the .h file, and put the helper functions used by each one right before the method it's used by.


src/core/ext/xds/xds_server_config_fetcher.cc, line 73 at r7 (raw file):

  struct WatcherState {
    std::string listening_address;

This field also exists in the object pointed to by listener_watcher. Do we need it in both places?


src/core/ext/xds/xds_server_config_fetcher.cc, line 85 at r7 (raw file):

// A watcher implementation for listening on LDS updates from the xDS control
// plane. When a good LDS update is received, it creates FilterChainMatchManager

s/FilterChainMatchManager objects/a FilterChainMatchManager object/


src/core/ext/xds/xds_server_config_fetcher.cc, line 87 at r7 (raw file):

// plane. When a good LDS update is received, it creates FilterChainMatchManager
// objects that would replace the existing (if any) FilterChainMatchManager
// object after all referred RDS resources are fetched. Note that a good update

s/referred/referenced/

Same thing throughout all of the comments in this file.


src/core/ext/xds/xds_server_config_fetcher.cc, line 129 at r7 (raw file):

  RefCountedPtr<FilterChainMatchManager> pending_filter_chain_match_manager_
      ABSL_GUARDED_BY(mu_);
  std::vector<std::string> pending_rds_updates_ ABSL_GUARDED_BY(mu_);

Doesn't look like this field is actually used anywhere, so I think it can be removed.


src/core/ext/xds/xds_server_config_fetcher.cc, line 186 at r7 (raw file):

  void UpdateRouteConfig(std::string resource_name,
                         absl::StatusOr<XdsApi::RdsUpdate> rds_update,
                         bool prefer_existing_update);

This parameter isn't very intuitive. Instead, I suggest splitting this method into three parts, one corresponding to each of the methods of the RouteConfigWatcher.


src/core/ext/xds/xds_server_config_fetcher.cc, line 190 at r7 (raw file):

  RefCountedPtr<XdsClient> xds_client_;
  RefCountedPtr<ListenerWatcher>
      listener_watcher_;  // This ref is only kept around till the

Suggest moving this comment to the line before the field, for better formatting.


src/core/ext/xds/xds_server_config_fetcher.cc, line 196 at r7 (raw file):

      default_filter_chain_;
  Mutex mu_;
  size_t rds_resources_yet_to_fetch_ = 0;

Are these two fields also guarded by the mutex?


src/core/ext/xds/xds_server_config_fetcher.cc, line 223 at r7 (raw file):

  void OnError(grpc_error_handle error) override {
    Update(grpc_error_to_absl_status(error), true /* prefer_existing_update */);

Need to unref error before returning.


src/core/ext/xds/xds_server_config_fetcher.cc, line 232 at r7 (raw file):

 private:
  void Update(absl::StatusOr<XdsApi::RdsUpdate> rds_update,

This method doesn't seem that useful, since it's basically just delegating to another method. Why not just call the other method directly from the caller of this method?


src/core/ext/xds/xds_server_config_fetcher.cc, line 234 at r7 (raw file):

  void Update(absl::StatusOr<XdsApi::RdsUpdate> rds_update,
              bool prefer_existing_update) {
    filter_chain_match_manager_->UpdateRouteConfig(resource_name_, rds_update,

std::move(rds_update)


src/core/ext/xds/xds_server_config_fetcher.cc, line 277 at r7 (raw file):

    VirtualHostListIterator : public XdsRouting::VirtualHostListIterator {
 public:
  VirtualHostListIterator(const std::vector<VirtualHost>& virtual_hosts)

explicit


src/core/ext/xds/xds_server_config_fetcher.cc, line 277 at r7 (raw file):

    VirtualHostListIterator : public XdsRouting::VirtualHostListIterator {
 public:
  VirtualHostListIterator(const std::vector<VirtualHost>& virtual_hosts)

Consider making this parameter and the corresponding data member be pointers instead of references, to emphasize the external ownership.


src/core/ext/xds/xds_server_config_fetcher.cc, line 294 at r7 (raw file):

    VirtualHost::RouteListIterator : public XdsRouting::RouteListIterator {
 public:
  RouteListIterator(const std::vector<Route>& routes) : routes_(routes) {}

explicit


src/core/ext/xds/xds_server_config_fetcher.cc, line 294 at r7 (raw file):

    VirtualHost::RouteListIterator : public XdsRouting::RouteListIterator {
 public:
  RouteListIterator(const std::vector<Route>& routes) : routes_(routes) {}

Consider making this parameter and the corresponding data member be pointers instead of references, to emphasize the external ownership.


src/core/ext/xds/xds_server_config_fetcher.cc, line 379 at r7 (raw file):

    : public XdsClient::RouteConfigWatcherInterface {
 public:
  explicit RouteConfigWatcher(DynamicXdsServerConfigSelectorProvider* parent)

Doesn't this need to hold a ref on its parent?


src/core/ext/xds/xds_server_config_fetcher.cc, line 386 at r7 (raw file):

  }
  void OnError(grpc_error_handle error) override {
    Update(grpc_error_to_absl_status(error), true /* prefer_existing_update */);

Need to unref error before returning.


src/core/ext/xds/xds_server_config_fetcher.cc, line 394 at r7 (raw file):

 private:
  void Update(absl::StatusOr<XdsApi::RdsUpdate> rds_update,

Combining the logic of all three methods like this makes it fairly hard to understand the control flow. I think it would make more sense to just inline them:

void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) override {
  if (parent_->watcher_ == nullptr) return;
  parent_->watcher_->OnServerConfigSelectorUpdate(
      XdsServerConfigSelector::Create(std::move(route_config),
                                      parent_->http_filters_));
}

void OnError(grpc_error_handle error) override {
  if (parent_->watcher_ == nullptr) return;
  if (parent_->resource_.ok()) return;  // Prefer existing update, if any.
  parent_->watcher_->OnServerConfigSelectorUpdate(
      grpc_error_to_absl_status(error));
  GRPC_ERROR_UNREF(error);
}

void OnResourceDoesNotExist() override {
  if (parent_->watcher_ == nullptr) return;
  parent_->watcher_->OnServerConfigSelectorUpdate(
      absl::NotFoundError("Requested route config does not exist"));
}

src/core/ext/xds/xds_server_config_fetcher.cc, line 619 at r7 (raw file):

  std::set<std::string> resource_names;
  for (const auto& destination_ip : filter_chain_map.destination_ip_vector) {
    for (int source_type = 0; source_type < 3; ++source_type) {

Instead of hard-coding 3, please use destination_ip.source_types_array.size().

Or better yet, I think you can just say:

for (const auto& source_type : destination_ip.source_types_array) {

src/core/ext/xds/xds_server_config_fetcher.cc, line 277 at r8 (raw file):

};

class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::

The VirtualHostListIterator class is simple enough that it can be inlined in XdsServerConfigSelector.


src/core/ext/xds/xds_server_config_fetcher.cc, line 295 at r8 (raw file):

};

class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager::

The RouteListIterator class is simple enough that it can be inlined in XdsServerConfigSelector::VirtualHost.


src/core/ext/xds/xds_server_config_fetcher.cc, line 481 at r8 (raw file):

void XdsServerConfigFetcher::ListenerWatcher::OnListenerChanged(
    XdsApi::LdsUpdate listener) {
  {

This scope encompasses the whole body of the function, so I don't think it's needed.


src/core/ext/xds/xds_server_config_fetcher.cc, line 544 at r8 (raw file):

  pending_filter_chain_match_manager_.reset();
  gpr_log(GPR_ERROR,
          "ListenerWatcher:%p Encountered fatal error %s; not serving on %s",

Should we log this only if there's no serving status notifier?


src/core/ext/xds/xds_server_config_fetcher.cc, line 565 at r8 (raw file):

}

bool IsLoopbackIp(const grpc_resolved_address* address) {

Suggest moving this down to right above FindFilterChainDataForSourceType(), since that's where this is actually used.


src/core/ext/xds/xds_server_config_fetcher.cc, line 653 at r8 (raw file):

        default_filter_chain_->http_connection_manager.route_config_name);
  }
  bool lds_resource_ready = false;

I don't think this variable is actually needed. Instead, after releasing the lock, just check whether listener_watcher is null, since we always std::move() it away if lds_resource_ready is not set.


src/core/ext/xds/xds_server_config_fetcher.cc, line 760 at r8 (raw file):

                      bool prefer_existing_update) {
  RefCountedPtr<ListenerWatcher> listener_watcher;
  bool lds_resource_ready =

I don't think this variable is needed; instead, after releasing the lock, we can just check whether listener_watcher is non-null.


src/core/ext/xds/xds_server_config_fetcher.cc, line 982 at r8 (raw file):

    grpc_arg args_to_add[] = {server_config_selector_provider->MakeChannelArg(),
                              channel_stack_modifier->MakeChannelArg()};
    args = grpc_channel_args_copy_and_add(old_args, args_to_add, 2);

We've constructing new args both here and then again below to add the certificate provider. Instead, how about combining these, like this:

absl::InlinedVector<grpc_arg, 3> args_to_add;
if (XdsRbacEnabled()) {
  // ...construct server_config_selector_provider...
  args_to_add.emplace_back(server_config_selector_provider->MakeChannelArg());
  // ...construct channel_stack_modifier...
  args_to_add.emplace_back(channel_stack_modifier->MakeChannelArg());
}
// ...construct certificate provider...
args_to_add.emplace_back(xds_certificate_provider->MakeChannelArg());
// Modify args if needed.
if (!args_to_add.empty()) {
  grpc_channel_args* updated_args =
      grpc_channel_args_copy_and_add(args, args_to_add.data(), args_to_add.size());
  grpc_channel_args_destroy(args);
  args = updated_args;
}
return args;

src/core/ext/xds/xds_server_config_fetcher.cc, line 1086 at r8 (raw file):

      VirtualHostListIterator(virtual_hosts_), authority);
  if (!vhost_index.has_value()) {
    call_config.error = GRPC_ERROR_CREATE_FROM_CPP_STRING(

This error should set the status to UNAVAILABLE, since that will wind up being the status code for the RPC.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1098 at r8 (raw file):

    // Found the matching route
    if (route.inappropriate_action) {
      call_config.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(

This should also set the status code to UNAVAILABLE.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1099 at r8 (raw file):

    if (route.inappropriate_action) {
      call_config.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
          "Matching route has inappropriate_action");

This should probably say "unsupported action" instead of "inappropriate_action".


src/core/ext/xds/xds_server_config_fetcher.cc, line 1109 at r8 (raw file):

    return call_config;
  }
  call_config.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("No route matched");

This should also set the status code to UNAVAILABLE.


test/cpp/end2end/xds/xds_end2end_test.cc, line 731 at r8 (raw file):

        ->mutable_socket_address()
        ->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
    *http_connection_manager.mutable_route_config() =

I don't think we should set this here (nor should it be necessary), because we don't want to inline the route config in the listener resource by default. Instead, tests should use SetListenerAndRouteConfiguration() to dynamically determine whether to inline the route config in the listener or create a separate RDS resource, based on the TestType attribute.


test/cpp/end2end/xds/xds_end2end_test.cc, line 9789 at r8 (raw file):

      0, default_server_listener_, backends_[0]->port(), route_config);
  backends_[0]->Start();
  if (GetParam().enable_rds_testing()) {

Since this is such a common pattern, I suggest adding a helper method, similar to the existing RouteConfigurationResponseState() method:

bool WaitForRouteConfigNack(StatusCode expected_status = StatusCode::UNAVAILABLE) {
  if (GetParam().enable_rds_testing()) return WaitForRdsNack(expected_status);
  return WaitForLdsNack(expected_status);
}

Then the code in the individual tests can become:

ASSERT_TRUE(WaitForRouteConfigNack(StatusCode::DEADLINE_EXCEEDED))
    << "timed out waiting for NACK";
EXPECT_THAT(RouteConfigurationResponseState(0).error_message,
            ::testing::HasSubstr("Invalid domain pattern \"\""));

test/cpp/end2end/xds/xds_end2end_test.cc, line 9973 at r8 (raw file):

      absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()),
      grpc::StatusCode::OK);
  SendRpc([this]() { return CreateInsecureChannel(); }, {}, {});

Is there a reasonable way to test that different filter chains (and therefore different route configs) are selected for different incoming connections?


test/cpp/end2end/xds/xds_end2end_test.cc, line 12534 at r8 (raw file):

// We are only testing the server here.
// TODO(yashykt): Also add a test type with set_enable_rds_testing() once we

This TODO can go away now.

Copy link
Member Author

@yashykt yashykt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 22 of 27 files reviewed, 44 unresolved discussions (waiting on @markdroth and @yashykt)


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 334 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

explicit

Done.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 334 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Suggest making this parameter and the corresponding data member be pointers instead of references, so emphasize that there is external ownership.

Done.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 565 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Suggest handling the error case first, to keep the error condition and the error result next to each other, and to avoid unnecessary indentation for the rest of the function:

if (!route_index.has_value()) return CallConfig();

Done.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 566 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Can say *route_index here.

Done.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 748 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

No, I think this is the right place for it. If we ever need to use it somewhere else, we can consider moving it at that point.

Done.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 751 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

explicit

Done.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 752 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Suggest making this parameter and the corresponding data member be a pointer instead of a reference, to emphasize that it's externally owned.

Done.


src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc, line 785 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Can use *vhost_index here.

Done.


src/core/ext/xds/xds_routing.h, line 81 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Suggest moving these per-field comments to the line above the field they describe, since that should be more readable.

Done.


src/core/ext/xds/xds_routing.cc, line 98 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Please define these methods in the same order in which they are defined in the .h file, and put the helper functions used by each one right before the method it's used by.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 73 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This field also exists in the object pointed to by listener_watcher. Do we need it in both places?

Just saves some cpu cycles since the name we actually use for the watch is derived from the address and the template found in the bootstrap file, but given that CancelWatch will only be invoked when the server is shutdown, I think it's fine to repeat that modification.


src/core/ext/xds/xds_server_config_fetcher.cc, line 85 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

s/FilterChainMatchManager objects/a FilterChainMatchManager object/

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 87 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

s/referred/referenced/

Same thing throughout all of the comments in this file.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 129 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Doesn't look like this field is actually used anywhere, so I think it can be removed.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 190 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Suggest moving this comment to the line before the field, for better formatting.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 196 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Are these two fields also guarded by the mutex?

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 223 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Need to unref error before returning.

Done. Thanks!


src/core/ext/xds/xds_server_config_fetcher.cc, line 232 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This method doesn't seem that useful, since it's basically just delegating to another method. Why not just call the other method directly from the caller of this method?

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 234 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

std::move(rds_update)

outdated


src/core/ext/xds/xds_server_config_fetcher.cc, line 277 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

explicit

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 277 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Consider making this parameter and the corresponding data member be pointers instead of references, to emphasize the external ownership.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 294 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Consider making this parameter and the corresponding data member be pointers instead of references, to emphasize the external ownership.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 379 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Doesn't this need to hold a ref on its parent?

You're right. Now that the callbacks are invoked in a WorkSerializer, the updates can be delayed


src/core/ext/xds/xds_server_config_fetcher.cc, line 386 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Need to unref error before returning.

Thanks! Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 394 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Combining the logic of all three methods like this makes it fairly hard to understand the control flow. I think it would make more sense to just inline them:

void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) override {
  if (parent_->watcher_ == nullptr) return;
  parent_->watcher_->OnServerConfigSelectorUpdate(
      XdsServerConfigSelector::Create(std::move(route_config),
                                      parent_->http_filters_));
}

void OnError(grpc_error_handle error) override {
  if (parent_->watcher_ == nullptr) return;
  if (parent_->resource_.ok()) return;  // Prefer existing update, if any.
  parent_->watcher_->OnServerConfigSelectorUpdate(
      grpc_error_to_absl_status(error));
  GRPC_ERROR_UNREF(error);
}

void OnResourceDoesNotExist() override {
  if (parent_->watcher_ == nullptr) return;
  parent_->watcher_->OnServerConfigSelectorUpdate(
      absl::NotFoundError("Requested route config does not exist"));
}

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 619 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Instead of hard-coding 3, please use destination_ip.source_types_array.size().

Or better yet, I think you can just say:

for (const auto& source_type : destination_ip.source_types_array) {

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 277 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

The VirtualHostListIterator class is simple enough that it can be inlined in XdsServerConfigSelector.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 481 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This scope encompasses the whole body of the function, so I don't think it's needed.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 544 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Should we log this only if there's no serving status notifier?

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 565 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Suggest moving this down to right above FindFilterChainDataForSourceType(), since that's where this is actually used.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 653 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

I don't think this variable is actually needed. Instead, after releasing the lock, just check whether listener_watcher is null, since we always std::move() it away if lds_resource_ready is not set.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 760 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

I don't think this variable is needed; instead, after releasing the lock, we can just check whether listener_watcher is non-null.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 982 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

We've constructing new args both here and then again below to add the certificate provider. Instead, how about combining these, like this:

absl::InlinedVector<grpc_arg, 3> args_to_add;
if (XdsRbacEnabled()) {
  // ...construct server_config_selector_provider...
  args_to_add.emplace_back(server_config_selector_provider->MakeChannelArg());
  // ...construct channel_stack_modifier...
  args_to_add.emplace_back(channel_stack_modifier->MakeChannelArg());
}
// ...construct certificate provider...
args_to_add.emplace_back(xds_certificate_provider->MakeChannelArg());
// Modify args if needed.
if (!args_to_add.empty()) {
  grpc_channel_args* updated_args =
      grpc_channel_args_copy_and_add(args, args_to_add.data(), args_to_add.size());
  grpc_channel_args_destroy(args);
  args = updated_args;
}
return args;

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1086 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This error should set the status to UNAVAILABLE, since that will wind up being the status code for the RPC.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1098 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This should also set the status code to UNAVAILABLE.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1099 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This should probably say "unsupported action" instead of "inappropriate_action".

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 1109 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This should also set the status code to UNAVAILABLE.

Done.


test/cpp/end2end/xds/xds_end2end_test.cc, line 731 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

I don't think we should set this here (nor should it be necessary), because we don't want to inline the route config in the listener resource by default. Instead, tests should use SetListenerAndRouteConfiguration() to dynamically determine whether to inline the route config in the listener or create a separate RDS resource, based on the TestType attribute.

Done.


test/cpp/end2end/xds/xds_end2end_test.cc, line 9789 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Since this is such a common pattern, I suggest adding a helper method, similar to the existing RouteConfigurationResponseState() method:

bool WaitForRouteConfigNack(StatusCode expected_status = StatusCode::UNAVAILABLE) {
  if (GetParam().enable_rds_testing()) return WaitForRdsNack(expected_status);
  return WaitForLdsNack(expected_status);
}

Then the code in the individual tests can become:

ASSERT_TRUE(WaitForRouteConfigNack(StatusCode::DEADLINE_EXCEEDED))
    << "timed out waiting for NACK";
EXPECT_THAT(RouteConfigurationResponseState(0).error_message,
            ::testing::HasSubstr("Invalid domain pattern \"\""));

Done.


test/cpp/end2end/xds/xds_end2end_test.cc, line 9973 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Is there a reasonable way to test that different filter chains (and therefore different route configs) are selected for different incoming connections?

Hmm, so the properties that we can vary in the filter chain match are

    // - destination port (never matched, so not present in map)
    // - destination IP address
    // - server name (never matched, so not present in map)
    // - transport protocol (allows only "raw_buffer" or unset, prefers the
    //   former, so only one of those two types is present in map)
    // - application protocol (never matched, so not present in map)
    // - connection source type (any, local or external)
    // - source IP address
    // - source port

From these, the source port seems to be the only thing that we can vary for connections on localhost. If we could tell the channel to bind to a particular port, we could do it..


test/cpp/end2end/xds/xds_end2end_test.cc, line 12534 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This TODO can go away now.

Done.

Copy link
Member Author

@yashykt yashykt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 22 of 27 files reviewed, 44 unresolved discussions (waiting on @markdroth)


src/core/ext/xds/xds_server_config_fetcher.cc, line 186 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This parameter isn't very intuitive. Instead, I suggest splitting this method into three parts, one corresponding to each of the methods of the RouteConfigWatcher.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 294 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

explicit

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 295 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

The RouteListIterator class is simple enough that it can be inlined in XdsServerConfigSelector::VirtualHost.

Done.

Copy link
Member

@markdroth markdroth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking very good! Only a few comments left.

Please let me know if you have any questions. Thanks!

Reviewed 4 of 5 files at r9, 1 of 1 files at r10, all commit messages.
Reviewable status: all files reviewed, 8 unresolved discussions (waiting on @yashykt)


src/core/ext/xds/xds_routing.cc, line 98 at r7 (raw file):

Previously, yashykt (Yash Tibrewal) wrote…

Done.

Please also move HeadersMatch() and UnderFraction() to their own anonymous namespace that is located between FindVirtualHostForDomain() and GetRouteForRequest(), since those helper functions are only used by the latter method.


src/core/ext/xds/xds_server_config_fetcher.cc, line 73 at r7 (raw file):

Previously, yashykt (Yash Tibrewal) wrote…

Just saves some cpu cycles since the name we actually use for the watch is derived from the address and the template found in the bootstrap file, but given that CancelWatch will only be invoked when the server is shutdown, I think it's fine to repeat that modification.

Re-expanding the template seems wrong here. The value that you're storing in ListenerWatcher::listening_address_ is actually the expanded template already. I think re-expanding it will yield the wrong value.

Also, given that it's actually storing the expanded resource name, we should probably change the name of this field from listening_address to resource_name.


src/core/ext/xds/xds_server_config_fetcher.cc, line 186 at r7 (raw file):

Previously, yashykt (Yash Tibrewal) wrote…

Done.

To be clear, I didn't actually mean to move the code into the methods of RouteConfigWatcher; I just meant that there should be one method here corresponding to each of those methods. I think the methods of RouteConfigWatcher should just delegate to these methods, since they really belong here.

RouteConfigWatcher should be simple enough that you can inline it if you want. The other methods' definitions are long enough that they should be moved below.


src/core/ext/xds/xds_server_config_fetcher.cc, line 294 at r7 (raw file):

Previously, yashykt (Yash Tibrewal) wrote…

Done.

I don't see this change.


src/core/ext/xds/xds_server_config_fetcher.cc, line 399 at r9 (raw file):

    // Prefer existing update, if any.
    if (parent_->resource_.ok()) {
      return;

Need to unref the error before returning here.


src/core/ext/xds/xds_server_config_fetcher.cc, line 113 at r10 (raw file):

  // pending_filter_chain_match_manager_, it is promoted to be the
  // filter_chain_match_manager_ in use.
  void PendingFilterChainMatchManagerReady(

Might be useful to rename this to PendingFilterChainMatchManagerReadyLocked() and add a wrapper version without the Locked() suffix that grabs the lock for the caller. That way, we won't need to grab the lock externally.


test/cpp/end2end/xds/xds_end2end_test.cc, line 9973 at r8 (raw file):

Previously, yashykt (Yash Tibrewal) wrote…

Hmm, so the properties that we can vary in the filter chain match are

    // - destination port (never matched, so not present in map)
    // - destination IP address
    // - server name (never matched, so not present in map)
    // - transport protocol (allows only "raw_buffer" or unset, prefers the
    //   former, so only one of those two types is present in map)
    // - application protocol (never matched, so not present in map)
    // - connection source type (any, local or external)
    // - source IP address
    // - source port

From these, the source port seems to be the only thing that we can vary for connections on localhost. If we could tell the channel to bind to a particular port, we could do it..

That's unfortunate. For now, please add a TODO that we should add such a test once #24035 is resolved.


test/cpp/end2end/xds/xds_end2end_test.cc, line 9772 at r10 (raw file):

  }

  bool WaitForRouteConfigNack(

This should move into XdsEnd2endTest, right above the existing RouteConfigurationResponseState() method. It could be useful in client-side tests too.

Copy link
Member Author

@yashykt yashykt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 24 of 27 files reviewed, 8 unresolved discussions (waiting on @markdroth)


src/core/ext/xds/xds_routing.cc, line 98 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Please also move HeadersMatch() and UnderFraction() to their own anonymous namespace that is located between FindVirtualHostForDomain() and GetRouteForRequest(), since those helper functions are only used by the latter method.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 73 at r7 (raw file):

Re-expanding the template seems wrong here. The value that you're storing in ListenerWatcher::listening_address_ is actually the expanded template already. I think re-expanding it will yield the wrong value.

No, it's not.

  auto listener_watcher = MakeRefCounted<ListenerWatcher>(
      xds_client_, std::move(watcher), serving_status_notifier_,
      listening_address);
  auto* listener_watcher_ptr = listener_watcher.get();
  listening_address = absl::StrReplaceAll(
      xds_client_->bootstrap().server_listener_resource_name_template(),
      {{"%s", listening_address}});
  xds_client_->WatchListenerData(listening_address,
                                 std::move(listener_watcher));

We store the address before using the template.


src/core/ext/xds/xds_server_config_fetcher.cc, line 186 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

To be clear, I didn't actually mean to move the code into the methods of RouteConfigWatcher; I just meant that there should be one method here corresponding to each of those methods. I think the methods of RouteConfigWatcher should just delegate to these methods, since they really belong here.

RouteConfigWatcher should be simple enough that you can inline it if you want. The other methods' definitions are long enough that they should be moved below.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 294 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

I don't see this change.

This time for sure.


src/core/ext/xds/xds_server_config_fetcher.cc, line 399 at r9 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Need to unref the error before returning here.

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 113 at r10 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Might be useful to rename this to PendingFilterChainMatchManagerReadyLocked() and add a wrapper version without the Locked() suffix that grabs the lock for the caller. That way, we won't need to grab the lock externally.

Done.


test/cpp/end2end/xds/xds_end2end_test.cc, line 9973 at r8 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

That's unfortunate. For now, please add a TODO that we should add such a test once #24035 is resolved.

Done.


test/cpp/end2end/xds/xds_end2end_test.cc, line 9772 at r10 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

This should move into XdsEnd2endTest, right above the existing RouteConfigurationResponseState() method. It could be useful in client-side tests too.

Done.

Copy link
Member

@markdroth markdroth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks excellent! Just a couple of minor nits remaining.

Please let me know if you have any questions. Thanks!

Reviewed 3 of 3 files at r11, all commit messages.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on @yashykt)


src/core/ext/xds/xds_server_config_fetcher.cc, line 73 at r7 (raw file):

Previously, yashykt (Yash Tibrewal) wrote…

Re-expanding the template seems wrong here. The value that you're storing in ListenerWatcher::listening_address_ is actually the expanded template already. I think re-expanding it will yield the wrong value.

No, it's not.

  auto listener_watcher = MakeRefCounted<ListenerWatcher>(
      xds_client_, std::move(watcher), serving_status_notifier_,
      listening_address);
  auto* listener_watcher_ptr = listener_watcher.get();
  listening_address = absl::StrReplaceAll(
      xds_client_->bootstrap().server_listener_resource_name_template(),
      {{"%s", listening_address}});
  xds_client_->WatchListenerData(listening_address,
                                 std::move(listener_watcher));

We store the address before using the template.

Ah, okay. What confused me is that you're storing the resource name in a variable called listening_address. Can you please change that code to either create a new string variable called resource_name, or just side-step the issue and pass the result of absl::StrReplaceAll() directly to WatchListenerData() without storing it in a local variable at all?


src/core/ext/xds/xds_server_config_fetcher.cc, line 186 at r7 (raw file):

Previously, yashykt (Yash Tibrewal) wrote…

Done.

You made this change in DynamicXdsServerConfigSelectorProvider, but not here in FilterChainMatchManager.


src/core/ext/xds/xds_server_config_fetcher.cc, line 592 at r11 (raw file):

void XdsServerConfigFetcher::ListenerWatcher::
    PendingFilterChainMatchManagerReady(

The definition of this method is short enough that it can be inlined in the class definition above if you'd like.

Copy link
Member Author

@yashykt yashykt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 26 of 27 files reviewed, 3 unresolved discussions (waiting on @markdroth)


src/core/ext/xds/xds_server_config_fetcher.cc, line 73 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

Ah, okay. What confused me is that you're storing the resource name in a variable called listening_address. Can you please change that code to either create a new string variable called resource_name, or just side-step the issue and pass the result of absl::StrReplaceAll() directly to WatchListenerData() without storing it in a local variable at all?

Done.


src/core/ext/xds/xds_server_config_fetcher.cc, line 186 at r7 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

You made this change in DynamicXdsServerConfigSelectorProvider, but not here in FilterChainMatchManager.

Ah, DynamicXdsServerConfigSelectorProvider is where I thought the original comment was. It's good to be consistent anyway, so the change is now in both places.


src/core/ext/xds/xds_server_config_fetcher.cc, line 592 at r11 (raw file):

Previously, markdroth (Mark D. Roth) wrote…

The definition of this method is short enough that it can be inlined in the class definition above if you'd like.

Done.

Copy link
Member

@markdroth markdroth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fantastic!

Reviewed 1 of 1 files at r12, all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @yashykt)

@yashykt yashykt enabled auto-merge (squash) November 18, 2021 22:54
@yashykt
Copy link
Member Author

yashykt commented Nov 18, 2021

Known issues: #26886
Thanks for reviewing!

@yashykt yashykt merged commit 25446c4 into grpc:master Nov 19, 2021
@copybara-service copybara-service bot added the imported Specifies if the PR has been imported to the internal repository label Nov 19, 2021
krestofur added a commit to krestofur/grpc that referenced this pull request Nov 24, 2021
* Revert low Java throughput hotfix; implement permanent fix (grpc#27919)

* xds/interop: Completely disable principal-present authz test (grpc#27933)

A broken fix for the server-side bug is producing invalid configuration,
causing the server to reject all the configuration. Disable the
configuration and tests until fix is fixed.

* Add EventEngine::CancelConnect (grpc#27764)

* Fix crash in bloat diff if diff_size != 0 (grpc#27935)

* Update bloat_diff.py

* Automated change: Fix sanity tests (grpc#27936)

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* ugh (grpc#27937)

* [BinderTransport] Avoid depending on NdkBinder at compile time (grpc#27912)

* [BinderTransport] Avoid depending on NdkBinder at compile time

We would like to make it possible to use BinderTransport in a APK that
has min sdk version lower than 29 (NdkBinder was introduced at 29)

We copies constants and type definitions from Ndk headers, creates a
same name wrapper for every NdkBinder API we use in
grpc_binder::ndk_util namespace.

We will try to load libbinder_ndk.so and resolve the symbol when the
NdkBinder API wrappers are invoked.

* regenerate projects

* Add GRPC_NO_BINDER guard

* Appnet schema changes (grpc#27874)

* Add back references and scope field

* Set scope in router

* Reverse order of cleanup

* Add router_scope flag

* Use router_scope flag to create Router

* I apparently don't know how to brain

* Yapf

* Yeah, that can't be the default

* Remove debug print

* Remove impossible todos

* And another

* Switch from router-scope to config-scope

* Implement schema changes

* Use backend service URL

* Use CLH reference format to backend service

* I am an idiot

* *internal screaming*

* Try project number

* Why is this all awful

* Go back to trying project name

* Try cleaning things up

* Agh

* Address review comments

* Remove superfluous Optional type

* Tweak bloat thresholds (grpc#27942)

* Add Schedule and DrainQueue to WorkSerializer (grpc#27902)

* Add Schedule and DrainQueue to WorkSerializer

* Fix comments

* Reviewer comments

* Use acq_rel semantics instead of seq_cst

* Reviewer comments

* s/dummy/no-op

* Reviewer comments

* Fix

* Reviewer comments

* Reviewer comments

* xds_end2end_test: Only start backends when needed (grpc#27911)

* xds_end2end_test: Fix flakiness on WaitForLdsNack

* xds_end2end_test: Only start the server when we want

* Revert WaitForNack changes

* Fixes

* Fix CsdsShortAdsTimeoutTest

* Fix sanity

* Revert grpc#27780 (grpc#27944)

* bump version on master to 1.43-dev (grpc#27930)

* bump version on master to 1.43-dev

* bump core version

* update g_stands_for.md

* Add support for abstract unix domain sockets (grpc#27906)

* Add failing end2end test for inconsistent percent-decoding of URIs

* Add passing h2_local_abstract_uds end2end tests

* null-safe string_view

* mac doesn't UDS

* mac doesn't do *abstract* UDS

* Add an experimental binder transport API for pre-finding Java class (grpc#27939)

Due to limitation of JVM, when user want to create binder channel in
threads created in unmanaged native code, they will need to call this
new API first to make sure Java helper classes can correctly be found.

Unused code in jni_utils.cc are also cleaned up in this commit

* Add grpc-java 1.42.0 to client_matrix.py (grpc#27949)

* Early exit BackUp() on count == 0 (grpc#27946)

* First pass IWYU tooling (grpc#27857)

* First pass IWYU tooling

* fix

* Automated change: Fix sanity tests

* Update iwyu.sh

* Update iwyu.sh

* Update Dockerfile.template

* Update iwyu.sh

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* OpenCensus: Move metadata storage to arena (grpc#27948)

* fix LB policy call status notification interface, and other improvements (grpc#27947)

* fix LB policy call status notification interface, and other improvements

* fix build

* address review comments

* Use PUT not POST to avoid duplicate bloat labels (grpc#27952)

* tcp_client_custom: fix socket leak (grpc#27408)

* Delete happy-pancakes.yml (grpc#27955)

I'm not going to get a chance to finish this for a while, so delete for now.

* Address reviewer comments on grpc#27906 (grpc#27954)

* Address reviewer comments on grpc#27906

* fixes

* absl::ConsumePrefix FTW!

* Assert Android API >= v21 (grpc#27943)

* Assert Android API >= v21

This precedes a change that would otherwise break on older Android APIs,
but in a more obvious way.

* error if __ANDROID_API__ is not defined

* update all Andriod minSdkVersions to 21

* csharp experimental: android-19 to 21

* Api fuzzer extensions to support simulating traffic congestion (grpc#27820)

* adding api_fuzzer changes

* adding api fuzzer changes

* updating some typos

* updating api_fuzzer and corpus entries

* updating api_fuzzer to fix crash due to two successive receive_op batches

* adding some reverted fixes to api_fuzzer.cc

* updating api_fuzzer and corpus as per initial comments

* fix some typos

* fix memory leaks and timeout issues

* adding some comments and removing debug strings

* updating api_fuzzer to remove previous edits to always add recv initial metadata ops for client calls

* updating passthru endpoint to account for erroneous initialization when channel effects are not simulated

* tidying up code

* Migrate Infrastructure Scripts to Python 3 (grpc#27135)

* Run 2to3 on tools directory

* Delete github_stats_tracking

* Re-run 2to3

* Remove unused script

* Remove unused script

* Remove unused line count utility

* Yapf. Isort

* Remove accidentally included file

* Migrate tools/distrib directory to python 3

* Remove unnecessary shebang

* Restore line_count directory

* Immediately convert subprocess.check_output output to string

* Take care of Python 2 shebangs

* Invoke scripts using a Python 3 interpreter

* Yapf. Isort

* Try installing Python 3 first

* See if we have any Python 3 versions installed

* Add Python 3.7 to Windows path

* Try adding a symlink

* Try to symlink differently

* Install six for Python 3

* Run run_interop_tests with python 3

* Try installing six in python3.7 explicitly

* Revert "Try installing six in python3.7 explicitly"

This reverts commit 2cf60d7.

* And debug some more

* Fix issue with jobset.py

* Add debug for CI failure

* Revert microbenchmark changes

* Fix RBE upload (grpc#27969)

* Fix relative imports for Python 3 (grpc#27971)

* Fix relative imports for Python 3

* Remove space

* isort

* Revert "Api fuzzer extensions to support simulating traffic congestion (grpc#27820)" (grpc#27973)

This reverts commit c1089d2.

* Repo manager to Donna (grpc#27967)

* Remove `from . import` from benchmarking scripts. (grpc#27977)

* Remove non-loadbearing argument (grpc#27968)

* Reintroduce the EventEngine default factory (grpc#27920)

* Reintroduce the EventEngine default factory

An application can provide an EventEngine factory function that allows
gRPC internals to create EventEngines as needed. This factory would be
used when no EventEngine is provided for some given channel or server,
and where an EventEngine otherwise could not be provided by the
application. Note that there currently is no API to provide an
EventEngine per channel or per server.

I've also deleted some previous iterations on global EventEngine and
EventEngine factory ideas. This new code lives in a public API, and
coexists with iomgr instead of being isolated to an EventEngine-specific
iomgr implementation.

* add proper namespaces, and fix description

* put factory functions in their own file (for replaceability)

* add synchronization

* generate_projects.sh

* extract event_engine_base and event_engine_factory targets

Also separate iomgr/event_engine files in the BUILD, with comments

* gpr_platform

* move all EE factory declarations to event_engine_base

Makes internal hackery easier.

* add missing deps

* reorder dep alphabetically

* comment style change

* Fix rbe_upload SSL issue (grpc#27982)

* Attempt to fix rbe_upload SSL issue

* Fix comparison

* Rename the source files for ChannelArgsEndpointConfig (grpc#27972)

* Rename the source files for ChannelArgsEndpointConfig

Previous naming was non-descript

* generate_projects

* add missing file to BUILD, and generate_projects.sh

* correct include guards

* xds/interop: Delay to drain queued RPCs in authz test (grpc#27991)

The authz test flaked as no RPCs of the expected type had completed
within the sampling window. Server logs showed authz logs completing
batch of 276 RPCs back-to-back, without the expected 40 ms separation
(qps=25). It took a bit over 1 second to process through the backlog.
With the sample duration of 500 ms and there being a polling delay
between when the channel is READY and when the test driver polls
channelz, it makes sense that we can get lucky much of the time.

Obviously, adding a sleep isn't great either, but measuring the queue
length indirectly is more complex than really appropriate here. The real
solution is to stop using this continuous-qps test client.

```
Traceback (most recent call last):
  File "/tmp/work/grpc/tools/run_tests/xds_k8s_test_driver/tests/authz_test.py", line 252, in test_tls_allow
    grpc.StatusCode.OK)
  File "/tmp/work/grpc/tools/run_tests/xds_k8s_test_driver/tests/authz_test.py", line 183, in configure_and_assert
    method=rpc_type)
  File "/tmp/work/grpc/tools/run_tests/xds_k8s_test_driver/framework/xds_k8s_testcase.py", line 284, in assertRpcStatusCodes
    self.assertGreater(stats.result[status_code.value[0]], 0)
AssertionError: 0 not greater than 0
```

* Support Custom Post-handshake Verification in TlsCredentials (grpc#25631)

* custom verification refactoring - post-handshake verification

* Fix the packaging.version issue on newer Python (grpc#27999)

* Add PSM security to the list of xDS features in the grpc_xds_features.md file (grpc#28001)

* Fix python 3 encoding issues in release notes script (grpc#28002)

* Correct the wait time for url-map propagation (grpc#28004)

* Remove trickle benchmarks (grpc#28000)

* Remove trickle benchmarks

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* [BinderTransport] Lower some log level from ERROR to INFO (grpc#27988)

We also plan to introduce a new tracer for tracing binder wireformat
logic.

* New resource quota integration (grpc#27643)

* new resource quota integration

* Automated change: Fix sanity tests

* fix

* fix

* fixes

* fixes

* fixes

* Automated change: Fix sanity tests

* fixes

* fixes

* Automated change: Fix sanity tests

* fixes

* fix

* fixes

* windows-fix

* fixes

* fixes

* fix

* fix-asan

* banned

* banned

* fixes

* clang-tidy-fix

* Automated change: Fix sanity tests

* fix-cronet

* review feedback

* review feedback

* Automated change: Fix sanity tests

* fixes

* bug fix

* fixes

* compile fix

* exclude megabyte size payloads from 1byte tests

* windows fix

* start moving ios

* keep moving windows

* Get windows compilation working.

* Automated change: Fix sanity tests

* better

* fixes

* remove slice buffer from memory_allocator.h

* Revert "remove slice buffer from memory_allocator.h"

This reverts commit 234a63b.

* ugh

* #fixtests

* pthread tls fixes

* Automated change: Fix sanity tests

* fixfixfix

* xxx

* add reset

* review feedback

* fix

* fix

* fixes

* fix

* mac progress

* cpp-impl-of

* rename ptr

* Automated change: Fix sanity tests

* memory-owner-is-a-memory-allocator

* fixes

* fix

* fix from prod

* fix

* Fix issue leading to bad pointers being returned on Windows.

* Automated change: Fix sanity tests

* fix multislice bug

* argh

* hyrums law fixes

* hyrums law fixes

* clang-format

* hyrums law fixes

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* Start port server separately (grpc#28005)

* Label microbenchmark differences similarly to bloat (grpc#27998)

* benchmark differences as a label

* debug

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* fix AWS arm64 C++ build (grpc#27981)

* [Aio] Validate the input type for set_trailing_metadata and abort (grpc#27958)

* [Aio] Validate the input type for set_trailing_metadata and abort

* Correct the checking of sequence type

* Add feature examples with continuous integration (grpc#27917)

* Add failing end2end test for inconsistent percent-decoding of URIs

* Add passing h2_local_abstract_uds end2end tests

* Add basic abstract UDS example

* add test runner

* add proper bazel build path

* first attempt at CI configuration

* cleanup

* rename CI files for better readability

* Revert "New resource quota integration (grpc#27643)" (grpc#28014)

This reverts commit 39f0877.

* Allow API fuzzer to send multiple slices (grpc#27993)

* Allow API fuzzer to send multiple slices

* fixes

* Use strict buildifier in sanitize (grpc#28018)

Ensure that we use tools consistently everywhere!

* Fix typo (grpc#28019)

* Set BinderTransport connectivity state tracker initial state to READY (grpc#27979)

By default the state is set to IDLE, which is not desired because

1. The actual connectivity state when transport is created is READY
2. The binder tansport channel won't be able to recover from IDLE state
for some reason and cause the channel to stuck when used on multiple
thread. We have an internal bug tracking this issue.

* [BinderTransport] Add more info to class not found error msg (grpc#28009)

* Add note about starting port server out of band (grpc#28012)

* Increase the timeout of xds_k8s test to 180 (grpc#28027)

* Bloat reporting improvements (grpc#28013)

* Bloat reporting improvements

* typo

* fix

* fix

* fix

* XdsClient: fix resource timeout behavior (grpc#27860)

* XdsClient: fix resource timeout behavior

* fix clang-tidy

* more clang-tidy fixes

* yet more clang-tidy

* Fix name of feature example tests CI config file (grpc#28028)

* AVL implementation in C++ (grpc#27782)

* avl

* move-code,add-fuzzer

* done

* fix

* Automated change: Fix sanity tests

* buildifier

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* Revert "XdsClient: fix resource timeout behavior (grpc#27860)" (grpc#28032)

This reverts commit 7fdb40d.

* Use WorkSerializer in XdsClient to propagate updates in a synchronized manner (grpc#27975)

* Use WorkSerializer in XdsClient to propagate updates

* Fix breakage

* Add missing Drain

* More fixes

* Get around msvc issue

* Fix asan leak

* Reviewer comments

* Get around TSAN annotations

* Remove notes

* Clang-format

* Reviewer comments

* [BinderTransport] Send correct version to server and verify it (grpc#27990)

We support wireformat version 1.

* [BinderTransport] Print error message when API level is too low (grpc#27989)

Also removes an obsolete API

* Reland resource quota work (grpc#28017)

* Check if memory owner available prior to polling it

The transport may drop the memory owner during its destruction sequence

* tcp_fix

* Revert "Revert "New resource quota integration (grpc#27643)" (grpc#28014)"

This reverts commit 0ea2c37.

* clang-format

* fix-path

* fix

* Remove extra ';' after member function definition (grpc#28038)

Some user of gRPC library have [-Werror,-Wextra-semi] set and this extra
';' makes the code uncompilable

* fix missing header (grpc#28087)

* Revert "[BinderTransport] Send correct version to server and verify it (grpc#27990)" (grpc#28090)

This reverts commit 92c34b8.

* Exclude debug sections from bloat severity calculations (grpc#28089)

* Ensure JSON parser can consume dumped JSON (grpc#27994)

* Ensure JSON parser can consume dumped JSON

* fixes

* fixes

* Update fuzzer.cc

* internal_ci: rename grpc_xds_k8s to psm-security as part of tech-debt cleanup and name clarity (grpc#28034)

* Upgrade upb to 0e0de7d9 (grpc#27984)

* Remove upb first

* Squashed 'third_party/upb/' content from commit 0e0de7d9f9

git-subtree-dir: third_party/upb
git-subtree-split: 0e0de7d9f927aa888d9a0baeaf6576bbbb23bf0b

* Update bazel deps

* Regen upb files

* Fix build

* Second attempt: XdsClient: fix resource timeout behavior (grpc#28088)

* Revert "Revert "XdsClient: fix resource timeout behavior (grpc#27860)" (grpc#28032)"

This reverts commit 817eed0.

* use the right status code enum

* Tooling to remove redundant grpc_core:: namespace references (grpc#28030)

* Tooling to remove redundant grpc_core:: namespaces

These references tend to show up in our C++ code after C modules get
converted. Many get caught in review, many get missed.

* use it

* clang-format

* add gcr image for java release v1.42.1 (grpc#28094)

* add gcr image for java release v1.42.1

* replace java release v1.42.0 with v1.42.1

* Fix typo in bloat script (grpc#28104)

* setup-ios-bazel-test-to-run-c-core-ee-ut (grpc#28029)

* user-agent metadata trait, also: grpc_core::Slice is born (grpc#27770)

* new slice api

* storage-classes

* Automated change: Fix sanity tests

* tweaks

* refinement

* refinement

* compiles

* Automated change: Fix sanity tests

* better impl

* convert to gtest

* clean

* fixes

* tests

* Automated change: Fix sanity tests

* more-tests

* clarity

* comments

* comments

* fixes

* comment-updates

* fixes

* spam

* Automated change: Fix sanity tests

* move transport size into transport!

* mebbefix

* fix type

* x

* fix-merge

* review feedback

* review feedback

* Automated change: Fix sanity tests

* meh

* review feedback

* fix

* resolve compile issue

* Remove slice_refcount dependency on RefCounted

* update init for channel_data in http_client_filter

* Automated change: Fix sanity tests

* remove banned function

* fixes

* will it blend

* will it blend

* fix refcount init

* fix

* fix comment

* Fix typo in bloat script

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* Revert "user-agent metadata trait, also: grpc_core::Slice is born (grpc#27770)" (grpc#28108)

This reverts commit 7a40f50.

* Faster clang-format (grpc#28086)

* use parallelism to speed clang-format performance

* use parallelism to speed clang-format performance

* xDS: strip "type.googleapis.com/" prefix off of resource type constants (grpc#28024)

* Increase iOS test timeout from 1.5h to 2.0h (grpc#28110)

* Sync Protos with grpc-proto repo (grpc#27957)

* Sync with grpc_proto

* UPB gen

* Update csharp SDK to LTS versions (grpc#27966)

* update C# SDK

* regenerate dockerfiles

* install .NET6 and .NET Core 3.1

* regenerate dockerfiles

* change netcoreapp2.1 targets to netcoreapp3.1

* update installed SDKs in aarch64 C# job

* update run_tests scripts to use netcoreapp3.1 for C#

* use CppImplOf for grpc_server (grpc#28112)

* use CppImplOf for grpc_server

* fix build

* fix sanity

* enable clang-tidy readability-static-definition-in-anonymous-namespace check (grpc#28033)

* Passing repo manager to markdroth (grpc#28114)

* Passing repo manager to markdroth

* one more file

* Add Java v1.40.2 and v1.41.1 to the interop test client matrix. (grpc#27953)

* Adding prefix to authority map key (grpc#28106)

* Adding prefex to authority map key

* fixing according to code review suggestions

* fixing

* Guard against duplicate ops in the same batch (grpc#28118)

* Guard against duplicate ops in the same batch

* add test

* add fuzzer example

* better name

* Fix api_fuzzer found bug (grpc#28113)

* Don't limit bloaty output lines (grpc#28120)

* dont limit bloaty output lines

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* Reland user-agent metadata work (grpc#28109)

* Revert "Revert "user-agent metadata trait, also: grpc_core::Slice is born (grpc#27770)" (grpc#28108)"

This reverts commit 89d08da.

* will it blend

* will it blend

* will it blend

* lcnagfmt

* sanity

* will it blend

* sleep @ end

* will it blend

* Revert "sleep @ end"

This reverts commit d6bca8e.

* review feedback

* review feedback

* Remove BUILD.gn (again) (grpc#28121)

* Revert "Revert "Api fuzzer extensions to support simulating traffic congestion (grpc#27820)" (grpc#27973)" (grpc#27974)

* Revert "Revert "Api fuzzer extensions to support simulating traffic congestion (grpc#27820)" (grpc#27973)"

This reverts commit 879f97e.

* updating passthru_endpoint file to fix windows breakages

* Automated change: Fix sanity tests

Co-authored-by: Vignesh2208 <Vignesh2208@users.noreply.github.com>

* Add v1.42.0 release of grpc-go to interop matrix (grpc#27985)

* remove RDS and EDS resource deletion inside of XdsClient (grpc#28128)

* Reduce OSS benchmarks polling time to 5s. (grpc#28131)

This change reduces total run time from ~86min to ~74min.

* Add missing exec ctx to public api (grpc#28134)

* Revert "use CppImplOf for grpc_server (grpc#28112)" (grpc#28130)

This reverts commit 2ea8e50.

* Fix xds_end2end_test dyld (grpc#28133)

* Support RDS updates on the server (grpc#27851)

* Port changes from grpc#27388

* Reviewer comments

* Fix resource timeout issue

* Cleanup

* Fix clang-tidy

* Revert benchmark

* Restructure

* clang-tidy

* Automated change: Fix sanity tests

* Partial commit

* Reviewer comments

* Fixes

* Reviewer comments

* Reviewer comments

* Reviewer comments

* Reviewer comments

* clang-format

* Fix FaultInjection tests

* clang-tidy

Co-authored-by: yashykt <yashykt@users.noreply.github.com>

* To LTS 20211102.0 (grpc#27916)

* internal_ci: rename grpc_xds_k8s_python to psm-security-python as part of tech-debt cleanup and name clarity (grpc#28136)

* Roll-forward grpc#27780 (grpc#27951)

* Revert "Revert grpc#27780 (grpc#27944)"

This reverts commit 26e7560.

* Fix google_api_upbdefs

* use WorkSerializer for subchannel connectivity state notifications (grpc#28111)

* ignore dynamic linker segments in bloat severity calculations (grpc#28149)

* Revert "Revert "use CppImplOf for grpc_server (grpc#28112)" (grpc#28130)" (grpc#28144)

This reverts commit eec0ca9.

* Fix C# nuget package build. (grpc#28152)

* fix nuget build by removing deprecated packageIconUrl field

* react to dotnet pack output fix in .NET

* Arena allocated promise (grpc#28023)

* Arena allocated promise

* finish

* Automated change: Fix sanity tests

* test

* Remove unused names

* fix

* older compiler fix

* fiiixes

* windows fixes?

* clangfmt

* fix windows?

* Document more

* fix destructors

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* [App Net] Switch Router to Mesh and Add unique string to Scope (grpc#28145)

* Add unique suffix to scope

* Actually add suffix

* Switch from Router to Mesh

* Yapf

* Review

* Fix bad reference

* Break circular dependency

* Add a dash

* Introduce empty targets to ease the internal merge of grpc#25586  (grpc#28122)

* add empty targets

* fix format error

* fix build format error

* address reviewer's comments

* fix test build rules

* remove server_auth_fiter from grpc_secure

* Remove unused constants (grpc#28156)

* Api fuzzer overflow bug (grpc#28161)

* fixing overflow error in api fuzzer

* fixing some sanity checks

* fix code style

* change repo mgr to nicolasnoble (grpc#28117)

* Revert "Arena allocated promise (grpc#28023)" (grpc#28171)

This reverts commit 77b4ade.

* Revert "Introduce empty targets to ease the internal merge of grpc#25586  (grpc#28122)" (grpc#28172)

This reverts commit 171c64e.

* Revert "[App Net] Switch Router to Mesh and Add unique string to Scope (grpc#28145)" (grpc#28176)

This reverts commit 7ac79c2.

* Reland arena based promises (grpc#28174)

* Revert "Revert "Arena allocated promise (grpc#28023)" (grpc#28171)"

This reverts commit 9b07a81.

* fix

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* Update cxx docker images (grpc#28162)

* Channel args preconditioning (grpc#28132)

* Channel args preconditioning

* docs

* fixes

* Automated change: Fix sanity tests

* fix

* fix this again after merge error

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* Added workaround for gcc 6.3.0 (grpc#28184)

* Remove unused override, and the static metadata that supports it (grpc#28193)

* Fix cronet tests (grpc#28189)

* add --log_metadata_and_status feature to interop_client (grpc#28021)

* Boringssl update to 4fb1589 (grpc#28194)

* update submodule boringssl-with-bazel with origin/main-with-bazel

* update boringssl dependency to main-with-bazel commit SHA

* regenerate files

* generate boringssl prefix headers

* Increment podspec version

* Use more parallelism to windows portability tests (grpc#28179)

* Use more parallelism to windows portability tests

* Added /MP

* Changed it to gRPC_BUILD_MSVC_MP_COUNT

* Move a bunch of slice typed metadata to new system (grpc#28107)

* Eliminate most of grpc_message metadata handling

* Eliminate most of host metadata handling

* Remove more callouts without fixing code

* fiiixes

* typo

* Automated change: Fix sanity tests

* try-shrink

* Automated change: Fix sanity tests

* size tweaks

* less tricks

* deunique

* commonize

* commonize

* Automated change: Fix sanity tests

* size tuning, fixes

* Automated change: Fix sanity tests

* fix

* size tuning, fixes

* remove constexpr

* fix

* reuse code

* fix

* tweak code

* more tweaks

* tell no lies

* fixes

* fixes

* Automated change: Fix sanity tests

* fix

* fix

* fix

* fix

* fix?

* fix binder

* fix

* fix

* fixes

* Automated change: Fix sanity tests

* fix

Co-authored-by: ctiller <ctiller@users.noreply.github.com>

* Revert "use WorkSerializer for subchannel connectivity state notifications (grpc#28111)" (grpc#28206)

This reverts commit cfca3e5.

* maybe fixed merge?

* fix merge

Co-authored-by: brandonpaiz <brandonpaiz@users.noreply.github.com>
Co-authored-by: Eric Anderson <ejona@google.com>
Co-authored-by: AJ Heller <hork@google.com>
Co-authored-by: Craig Tiller <ctiller@google.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: ctiller <ctiller@users.noreply.github.com>
Co-authored-by: Ming-Chuan <mingcl@google.com>
Co-authored-by: Richard Belleville <rbellevi@google.com>
Co-authored-by: Yash Tibrewal <yashkt@google.com>
Co-authored-by: Esun Kim <veblush@google.com>
Co-authored-by: Mark D. Roth <roth@google.com>
Co-authored-by: Sergii Tkachenko <sergiitk@google.com>
Co-authored-by: Nayef Ghattas <nayef.ghattas@gmail.com>
Co-authored-by: Vignesh Babu <vigneshbabu@google.com>
Co-authored-by: Paulo Castello da Costa <6579971+paulosjca@users.noreply.github.com>
Co-authored-by: ZhenLian <zhenlian@google.com>
Co-authored-by: Lidi Zheng <lidiz@google.com>
Co-authored-by: sanjaypujare <sanjaypujare@users.noreply.github.com>
Co-authored-by: Jan Tattermusch <jtattermusch@users.noreply.github.com>
Co-authored-by: yifeizhuang <yifeizhuang@gmail.com>
Co-authored-by: Hannah Shi <hannahshisfb@gmail.com>
Co-authored-by: donnadionne <donnadionne@google.com>
Co-authored-by: Terry Wilson <tmwilson@google.com>
Co-authored-by: Vignesh2208 <Vignesh2208@users.noreply.github.com>
Co-authored-by: Zach Reyes <39203661+zasweq@users.noreply.github.com>
Co-authored-by: yashykt <yashykt@users.noreply.github.com>
Co-authored-by: yihuaz <yihuaz@google.com>
@yashykt yashykt deleted the XdsRdsSupport branch May 18, 2023 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bloat/medium imported Specifies if the PR has been imported to the internal repository lang/c++ lang/core perf-change/none release notes: yes Indicates if PR needs to be in release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants