Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/upstream/upstream_impl.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <array>
4
#include <atomic>
5
#include <chrono>
6
#include <cstdint>
7
#include <functional>
8
#include <list>
9
#include <memory>
10
#include <string>
11
#include <utility>
12
#include <variant>
13
#include <vector>
14
15
#include "envoy/common/callback.h"
16
#include "envoy/common/optref.h"
17
#include "envoy/common/time.h"
18
#include "envoy/config/cluster/v3/cluster.pb.h"
19
#include "envoy/config/core/v3/address.pb.h"
20
#include "envoy/config/core/v3/base.pb.h"
21
#include "envoy/config/core/v3/health_check.pb.h"
22
#include "envoy/config/core/v3/protocol.pb.h"
23
#include "envoy/config/endpoint/v3/endpoint_components.pb.h"
24
#include "envoy/config/typed_metadata.h"
25
#include "envoy/event/timer.h"
26
#include "envoy/local_info/local_info.h"
27
#include "envoy/network/dns.h"
28
#include "envoy/network/filter.h"
29
#include "envoy/runtime/runtime.h"
30
#include "envoy/secret/secret_manager.h"
31
#include "envoy/server/filter_config.h"
32
#include "envoy/server/transport_socket_config.h"
33
#include "envoy/ssl/context_manager.h"
34
#include "envoy/stats/scope.h"
35
#include "envoy/thread_local/thread_local.h"
36
#include "envoy/upstream/cluster_factory.h"
37
#include "envoy/upstream/cluster_manager.h"
38
#include "envoy/upstream/health_checker.h"
39
#include "envoy/upstream/load_balancer.h"
40
#include "envoy/upstream/locality.h"
41
#include "envoy/upstream/outlier_detection.h"
42
#include "envoy/upstream/upstream.h"
43
44
#include "source/common/common/callback_impl.h"
45
#include "source/common/common/empty_string.h"
46
#include "source/common/common/enum_to_int.h"
47
#include "source/common/common/logger.h"
48
#include "source/common/common/packed_struct.h"
49
#include "source/common/common/thread.h"
50
#include "source/common/config/metadata.h"
51
#include "source/common/config/well_known_names.h"
52
#include "source/common/http/filter_chain_helper.h"
53
#include "source/common/http/http1/codec_stats.h"
54
#include "source/common/http/http2/codec_stats.h"
55
#include "source/common/http/http3/codec_stats.h"
56
#include "source/common/init/manager_impl.h"
57
#include "source/common/network/utility.h"
58
#include "source/common/shared_pool/shared_pool.h"
59
#include "source/common/stats/isolated_store_impl.h"
60
#include "source/common/upstream/load_balancer_impl.h"
61
#include "source/common/upstream/resource_manager_impl.h"
62
#include "source/common/upstream/transport_socket_match_impl.h"
63
#include "source/common/upstream/upstream_factory_context_impl.h"
64
#include "source/extensions/upstreams/http/config.h"
65
#include "source/extensions/upstreams/tcp/config.h"
66
#include "source/server/transport_socket_config_impl.h"
67
68
#include "absl/container/node_hash_set.h"
69
#include "absl/synchronization/mutex.h"
70
71
namespace Envoy {
72
namespace Upstream {
73
74
using ClusterProto = envoy::config::cluster::v3::Cluster;
75
76
using UpstreamNetworkFilterConfigProviderManager =
77
    Filter::FilterConfigProviderManager<Network::FilterFactoryCb,
78
                                        Server::Configuration::UpstreamFactoryContext>;
79
80
class LegacyLbPolicyConfigHelper {
81
public:
82
  struct Result {
83
    TypedLoadBalancerFactory* factory;
84
    LoadBalancerConfigPtr config;
85
  };
86
87
  static absl::StatusOr<Result>
88
  getTypedLbConfigFromLegacyProtoWithoutSubset(const ClusterProto& cluster,
89
                                               ProtobufMessage::ValidationVisitor& visitor);
90
91
  static absl::StatusOr<Result>
92
  getTypedLbConfigFromLegacyProto(const ClusterProto& cluster,
93
                                  ProtobufMessage::ValidationVisitor& visitor);
94
};
95
96
/**
97
 * Class for LBPolicies
98
 * Uses a absl::variant to store pointers for the LBPolicy
99
 */
100
class LBPolicyConfig {
101
public:
102
  LBPolicyConfig(const envoy::config::cluster::v3::Cluster& config);
103
104
0
  OptRef<const envoy::config::cluster::v3::Cluster::RoundRobinLbConfig> lbRoundRobinConfig() const {
105
0
    return getConfig<envoy::config::cluster::v3::Cluster::RoundRobinLbConfig>();
106
0
  }
107
108
  OptRef<const envoy::config::cluster::v3::Cluster::LeastRequestLbConfig>
109
0
  lbLeastRequestConfig() const {
110
0
    return getConfig<envoy::config::cluster::v3::Cluster::LeastRequestLbConfig>();
111
0
  }
112
113
0
  OptRef<const envoy::config::cluster::v3::Cluster::RingHashLbConfig> lbRingHashConfig() const {
114
0
    return getConfig<envoy::config::cluster::v3::Cluster::RingHashLbConfig>();
115
0
  }
116
117
0
  OptRef<const envoy::config::cluster::v3::Cluster::MaglevLbConfig> lbMaglevConfig() const {
118
0
    return getConfig<envoy::config::cluster::v3::Cluster::MaglevLbConfig>();
119
0
  }
120
121
  OptRef<const envoy::config::cluster::v3::Cluster::OriginalDstLbConfig>
122
0
  lbOriginalDstConfig() const {
123
0
    return getConfig<envoy::config::cluster::v3::Cluster::OriginalDstLbConfig>();
124
0
  }
125
126
private:
127
0
  template <typename T> OptRef<const T> getConfig() const {
128
    // Condition checks for the type of LbConfig, it also checks that the value is not nullptr
129
    // The Round Robin config being set to nullptr is the default value of the variant
130
0
    if (const auto lbPtr = absl::get_if<std::unique_ptr<const T>>(&lb_policy_); lbPtr && *lbPtr) {
131
0
      return *(*lbPtr);
132
0
    } else {
133
0
      return absl::nullopt;
134
0
    }
135
0
  }
Unexecuted instantiation: Envoy::OptRef<envoy::config::cluster::v3::Cluster_RoundRobinLbConfig const> Envoy::Upstream::LBPolicyConfig::getConfig<envoy::config::cluster::v3::Cluster_RoundRobinLbConfig>() const
Unexecuted instantiation: Envoy::OptRef<envoy::config::cluster::v3::Cluster_LeastRequestLbConfig const> Envoy::Upstream::LBPolicyConfig::getConfig<envoy::config::cluster::v3::Cluster_LeastRequestLbConfig>() const
Unexecuted instantiation: Envoy::OptRef<envoy::config::cluster::v3::Cluster_RingHashLbConfig const> Envoy::Upstream::LBPolicyConfig::getConfig<envoy::config::cluster::v3::Cluster_RingHashLbConfig>() const
Unexecuted instantiation: Envoy::OptRef<envoy::config::cluster::v3::Cluster_MaglevLbConfig const> Envoy::Upstream::LBPolicyConfig::getConfig<envoy::config::cluster::v3::Cluster_MaglevLbConfig>() const
Unexecuted instantiation: Envoy::OptRef<envoy::config::cluster::v3::Cluster_OriginalDstLbConfig const> Envoy::Upstream::LBPolicyConfig::getConfig<envoy::config::cluster::v3::Cluster_OriginalDstLbConfig>() const
136
137
  absl::variant<std::unique_ptr<const envoy::config::cluster::v3::Cluster::RoundRobinLbConfig>,
138
                std::unique_ptr<const envoy::config::cluster::v3::Cluster::LeastRequestLbConfig>,
139
                std::unique_ptr<const envoy::config::cluster::v3::Cluster::RingHashLbConfig>,
140
                std::unique_ptr<const envoy::config::cluster::v3::Cluster::MaglevLbConfig>,
141
                std::unique_ptr<const envoy::config::cluster::v3::Cluster::OriginalDstLbConfig>>
142
      lb_policy_;
143
};
144
145
/**
146
 * Null implementation of HealthCheckHostMonitor.
147
 */
148
class HealthCheckHostMonitorNullImpl : public HealthCheckHostMonitor {
149
public:
150
  // Upstream::HealthCheckHostMonitor
151
0
  void setUnhealthy(UnhealthyType) override {}
152
};
153
154
/**
155
 * Implementation of LoadMetricStats.
156
 */
157
class LoadMetricStatsImpl : public LoadMetricStats {
158
public:
159
  void add(const absl::string_view key, double value) override;
160
  StatMapPtr latch() override;
161
162
private:
163
  absl::Mutex mu_;
164
  StatMapPtr map_ ABSL_GUARDED_BY(mu_);
165
};
166
167
/**
168
 * Null host monitor implementation.
169
 */
170
class DetectorHostMonitorNullImpl : public Outlier::DetectorHostMonitor {
171
public:
172
  // Upstream::Outlier::DetectorHostMonitor
173
0
  uint32_t numEjections() override { return 0; }
174
2.22k
  void putHttpResponseCode(uint64_t) override {}
175
2.39k
  void putResult(Outlier::Result, absl::optional<uint64_t>) override {}
176
1.08k
  void putResponseTime(std::chrono::milliseconds) override {}
177
0
  const absl::optional<MonotonicTime>& lastEjectionTime() override { return time_; }
178
0
  const absl::optional<MonotonicTime>& lastUnejectionTime() override { return time_; }
179
0
  double successRate(SuccessRateMonitorType) const override { return -1; }
180
181
private:
182
  const absl::optional<MonotonicTime> time_{};
183
};
184
185
/**
186
 * Implementation of Upstream::HostDescription.
187
 */
188
class HostDescriptionImpl : virtual public HostDescription,
189
                            protected Logger::Loggable<Logger::Id::upstream> {
190
public:
191
  HostDescriptionImpl(
192
      ClusterInfoConstSharedPtr cluster, const std::string& hostname,
193
      Network::Address::InstanceConstSharedPtr dest_address, MetadataConstSharedPtr metadata,
194
      const envoy::config::core::v3::Locality& locality,
195
      const envoy::config::endpoint::v3::Endpoint::HealthCheckConfig& health_check_config,
196
      uint32_t priority, TimeSource& time_source);
197
198
47.8k
  Network::UpstreamTransportSocketFactory& transportSocketFactory() const override {
199
47.8k
    absl::ReaderMutexLock lock(&metadata_mutex_);
200
47.8k
    return socket_factory_;
201
47.8k
  }
202
203
4.49k
  bool canary() const override { return canary_; }
204
0
  void canary(bool is_canary) override { canary_ = is_canary; }
205
206
  // Metadata getter/setter.
207
  //
208
  // It's possible that the lock that guards the metadata will become highly contended (e.g.:
209
  // endpoints churning during a deploy of a large cluster). A possible improvement
210
  // would be to use TLS and post metadata updates from the main thread. This model would
211
  // possibly benefit other related and expensive computations too (e.g.: updating subsets).
212
0
  MetadataConstSharedPtr metadata() const override {
213
0
    absl::ReaderMutexLock lock(&metadata_mutex_);
214
0
    return metadata_;
215
0
  }
216
0
  void metadata(MetadataConstSharedPtr new_metadata) override {
217
0
    auto& new_socket_factory = resolveTransportSocketFactory(address_, new_metadata.get());
218
0
    {
219
0
      absl::WriterMutexLock lock(&metadata_mutex_);
220
0
      metadata_ = new_metadata;
221
      // Update data members dependent on metadata.
222
0
      socket_factory_ = new_socket_factory;
223
0
    }
224
0
  }
225
226
155k
  const ClusterInfo& cluster() const override { return *cluster_; }
227
0
  HealthCheckHostMonitor& healthChecker() const override {
228
0
    if (health_checker_) {
229
0
      return *health_checker_;
230
0
    }
231
232
0
    static HealthCheckHostMonitorNullImpl* null_health_checker =
233
0
        new HealthCheckHostMonitorNullImpl();
234
0
    return *null_health_checker;
235
0
  }
236
237
1.32k
  bool canCreateConnection(Upstream::ResourcePriority priority) const override {
238
1.32k
    if (stats().cx_active_.value() >= cluster().resourceManager(priority).maxConnectionsPerHost()) {
239
0
      return false;
240
0
    }
241
1.32k
    return cluster().resourceManager(priority).connections().canCreate();
242
1.32k
  }
243
244
5.69k
  Outlier::DetectorHostMonitor& outlierDetector() const override {
245
5.69k
    if (outlier_detector_) {
246
0
      return *outlier_detector_;
247
0
    }
248
249
5.69k
    static DetectorHostMonitorNullImpl* null_outlier_detector = new DetectorHostMonitorNullImpl();
250
5.69k
    return *null_outlier_detector;
251
5.69k
  }
252
64.2M
  HostStats& stats() const override { return stats_; }
253
0
  LoadMetricStats& loadMetricStats() const override { return load_metric_stats_; }
254
19.3k
  const std::string& hostnameForHealthChecks() const override { return health_checks_hostname_; }
255
0
  const std::string& hostname() const override { return hostname_; }
256
7.02k
  Network::Address::InstanceConstSharedPtr address() const override { return address_; }
257
1.32k
  const std::vector<Network::Address::InstanceConstSharedPtr>& addressList() const override {
258
1.32k
    return address_list_;
259
1.32k
  }
260
23.3k
  Network::Address::InstanceConstSharedPtr healthCheckAddress() const override {
261
23.3k
    return health_check_address_;
262
23.3k
  }
263
3.26k
  const envoy::config::core::v3::Locality& locality() const override { return locality_; }
264
3.36k
  Stats::StatName localityZoneStatName() const override {
265
3.36k
    return locality_zone_stat_name_.statName();
266
3.36k
  }
267
14
  uint32_t priority() const override { return priority_; }
268
0
  void priority(uint32_t priority) override { priority_ = priority; }
269
  Network::UpstreamTransportSocketFactory&
270
  resolveTransportSocketFactory(const Network::Address::InstanceConstSharedPtr& dest_address,
271
                                const envoy::config::core::v3::Metadata* metadata) const;
272
82.2M
  absl::optional<MonotonicTime> lastHcPassTime() const override { return last_hc_pass_time_; }
273
274
0
  void setAddressList(const std::vector<Network::Address::InstanceConstSharedPtr>& address_list) {
275
0
    address_list_ = address_list;
276
0
    ASSERT(address_list_.empty() || *address_list_.front() == *address_);
277
0
  }
278
279
protected:
280
0
  void setAddress(Network::Address::InstanceConstSharedPtr address) { address_ = address; }
281
282
0
  void setHealthCheckAddress(Network::Address::InstanceConstSharedPtr address) {
283
0
    health_check_address_ = address;
284
0
  }
285
286
3.89k
  void setHealthCheckerImpl(HealthCheckHostMonitorPtr&& health_checker) {
287
3.89k
    health_checker_ = std::move(health_checker);
288
3.89k
  }
289
290
0
  void setOutlierDetectorImpl(Outlier::DetectorHostMonitorPtr&& outlier_detector) {
291
0
    outlier_detector_ = std::move(outlier_detector);
292
0
  }
293
294
89.9k
  void setLastHcPassTimeImpl(MonotonicTime last_hc_pass_time) {
295
89.9k
    last_hc_pass_time_.emplace(std::move(last_hc_pass_time));
296
89.9k
  }
297
298
private:
299
  ClusterInfoConstSharedPtr cluster_;
300
  const std::string hostname_;
301
  const std::string health_checks_hostname_;
302
  Network::Address::InstanceConstSharedPtr address_;
303
  // The first entry in the address_list_ should match the value in address_.
304
  std::vector<Network::Address::InstanceConstSharedPtr> address_list_;
305
  Network::Address::InstanceConstSharedPtr health_check_address_;
306
  std::atomic<bool> canary_;
307
  mutable absl::Mutex metadata_mutex_;
308
  MetadataConstSharedPtr metadata_ ABSL_GUARDED_BY(metadata_mutex_);
309
  const envoy::config::core::v3::Locality locality_;
310
  Stats::StatNameDynamicStorage locality_zone_stat_name_;
311
  mutable HostStats stats_;
312
  mutable LoadMetricStatsImpl load_metric_stats_;
313
  Outlier::DetectorHostMonitorPtr outlier_detector_;
314
  HealthCheckHostMonitorPtr health_checker_;
315
  std::atomic<uint32_t> priority_;
316
  std::reference_wrapper<Network::UpstreamTransportSocketFactory>
317
      socket_factory_ ABSL_GUARDED_BY(metadata_mutex_);
318
  const MonotonicTime creation_time_;
319
  absl::optional<MonotonicTime> last_hc_pass_time_;
320
};
321
322
/**
323
 * Implementation of Upstream::Host.
324
 */
325
class HostImpl : public HostDescriptionImpl,
326
                 public Host,
327
                 public std::enable_shared_from_this<HostImpl> {
328
public:
329
  HostImpl(ClusterInfoConstSharedPtr cluster, const std::string& hostname,
330
           Network::Address::InstanceConstSharedPtr address, MetadataConstSharedPtr metadata,
331
           uint32_t initial_weight, const envoy::config::core::v3::Locality& locality,
332
           const envoy::config::endpoint::v3::Endpoint::HealthCheckConfig& health_check_config,
333
           uint32_t priority, const envoy::config::core::v3::HealthStatus health_status,
334
           TimeSource& time_source)
335
      : HostDescriptionImpl(cluster, hostname, address, metadata, locality, health_check_config,
336
                            priority, time_source),
337
207k
        disable_active_health_check_(health_check_config.disable_active_health_check()) {
338
    // This EDS flags setting is still necessary for stats, configuration dump, canonical
339
    // coarseHealth() etc.
340
207k
    HostImpl::setEdsHealthStatus(health_status);
341
207k
    HostImpl::weight(initial_weight);
342
207k
  }
Unexecuted instantiation: Envoy::Upstream::HostImpl::HostImpl(std::__1::shared_ptr<Envoy::Upstream::ClusterInfo const>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<Envoy::Network::Address::Instance const>, std::__1::shared_ptr<envoy::config::core::v3::Metadata const>, unsigned int, envoy::config::core::v3::Locality const&, envoy::config::endpoint::v3::Endpoint_HealthCheckConfig const&, unsigned int, envoy::config::core::v3::HealthStatus, Envoy::TimeSource&)
Envoy::Upstream::HostImpl::HostImpl(std::__1::shared_ptr<Envoy::Upstream::ClusterInfo const>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<Envoy::Network::Address::Instance const>, std::__1::shared_ptr<envoy::config::core::v3::Metadata const>, unsigned int, envoy::config::core::v3::Locality const&, envoy::config::endpoint::v3::Endpoint_HealthCheckConfig const&, unsigned int, envoy::config::core::v3::HealthStatus, Envoy::TimeSource&)
Line
Count
Source
337
207k
        disable_active_health_check_(health_check_config.disable_active_health_check()) {
338
    // This EDS flags setting is still necessary for stats, configuration dump, canonical
339
    // coarseHealth() etc.
340
207k
    HostImpl::setEdsHealthStatus(health_status);
341
207k
    HostImpl::weight(initial_weight);
342
207k
  }
343
344
3.89k
  bool disableActiveHealthCheck() const override { return disable_active_health_check_; }
345
0
  void setDisableActiveHealthCheck(bool disable_active_health_check) override {
346
0
    disable_active_health_check_ = disable_active_health_check;
347
0
  }
348
349
  // Upstream::Host
350
  std::vector<std::pair<absl::string_view, Stats::PrimitiveCounterReference>>
351
0
  counters() const override {
352
0
    return stats().counters();
353
0
  }
354
  CreateConnectionData createConnection(
355
      Event::Dispatcher& dispatcher, const Network::ConnectionSocket::OptionsSharedPtr& options,
356
      Network::TransportSocketOptionsConstSharedPtr transport_socket_options) const override;
357
  CreateConnectionData createHealthCheckConnection(
358
      Event::Dispatcher& dispatcher,
359
      Network::TransportSocketOptionsConstSharedPtr transport_socket_options,
360
      const envoy::config::core::v3::Metadata* metadata) const override;
361
362
  std::vector<std::pair<absl::string_view, Stats::PrimitiveGaugeReference>>
363
0
  gauges() const override {
364
0
    return stats().gauges();
365
0
  }
366
683k
  void healthFlagClear(HealthFlag flag) override { health_flags_ &= ~enumToInt(flag); }
367
73.9k
  bool healthFlagGet(HealthFlag flag) const override { return health_flags_ & enumToInt(flag); }
368
249k
  void healthFlagSet(HealthFlag flag) final { health_flags_ |= enumToInt(flag); }
369
0
  uint32_t healthFlagsGetAll() const override { return health_flags_; }
370
0
  void healthFlagsSetAll(uint32_t bits) override { health_flags_ |= bits; }
371
372
3.89k
  void setHealthChecker(HealthCheckHostMonitorPtr&& health_checker) override {
373
3.89k
    setHealthCheckerImpl(std::move(health_checker));
374
3.89k
  }
375
0
  void setOutlierDetector(Outlier::DetectorHostMonitorPtr&& outlier_detector) override {
376
0
    setOutlierDetectorImpl(std::move(outlier_detector));
377
0
  }
378
379
89.9k
  void setLastHcPassTime(MonotonicTime last_hc_pass_time) override {
380
89.9k
    setLastHcPassTimeImpl(std::move(last_hc_pass_time));
381
89.9k
  }
382
383
0
  Host::HealthStatus healthStatus() const override {
384
    // Evaluate active health status first.
385
386
    // Active unhealthy.
387
0
    if (healthFlagsGet(enumToInt(HealthFlag::FAILED_ACTIVE_HC) |
388
0
                       enumToInt(HealthFlag::FAILED_OUTLIER_CHECK))) {
389
0
      return HealthStatus::UNHEALTHY;
390
0
    }
391
392
    // Eds unhealthy.
393
0
    if (eds_health_status_ == envoy::config::core::v3::UNHEALTHY ||
394
0
        eds_health_status_ == envoy::config::core::v3::DRAINING ||
395
0
        eds_health_status_ == envoy::config::core::v3::TIMEOUT) {
396
0
      return eds_health_status_;
397
0
    }
398
399
    // Active degraded.
400
0
    if (healthFlagGet(HealthFlag::DEGRADED_ACTIVE_HC)) {
401
0
      return HealthStatus::DEGRADED;
402
0
    }
403
404
    // Eds degraded or healthy.
405
0
    return eds_health_status_;
406
0
  }
407
408
39.5M
  Host::Health coarseHealth() const override {
409
    // If any of the unhealthy flags are set, host is unhealthy.
410
39.5M
    if (healthFlagsGet(enumToInt(HealthFlag::FAILED_ACTIVE_HC) |
411
39.5M
                       enumToInt(HealthFlag::FAILED_OUTLIER_CHECK) |
412
39.5M
                       enumToInt(HealthFlag::FAILED_EDS_HEALTH))) {
413
68.8k
      return Host::Health::Unhealthy;
414
68.8k
    }
415
416
    // If any of the degraded flags are set, host is degraded.
417
39.4M
    if (healthFlagsGet(enumToInt(HealthFlag::DEGRADED_ACTIVE_HC) |
418
39.4M
                       enumToInt(HealthFlag::DEGRADED_EDS_HEALTH))) {
419
127k
      return Host::Health::Degraded;
420
127k
    }
421
422
    // The host must have no flags or be pending removal.
423
39.3M
    ASSERT(health_flags_ == 0 || healthFlagGet(HealthFlag::PENDING_DYNAMIC_REMOVAL));
424
39.3M
    return Host::Health::Healthy;
425
39.3M
  }
426
427
207k
  void setEdsHealthStatus(envoy::config::core::v3::HealthStatus eds_health_status) override {
428
207k
    eds_health_status_ = eds_health_status;
429
207k
    setEdsHealthFlag(eds_health_status);
430
207k
  }
431
0
  Host::HealthStatus edsHealthStatus() const override {
432
0
    return Host::HealthStatus(eds_health_status_.load());
433
0
  }
434
435
72.1M
  uint32_t weight() const override { return weight_; }
436
  void weight(uint32_t new_weight) override;
437
0
  bool used() const override { return handle_count_ > 0; }
438
1.32k
  HostHandlePtr acquireHandle() const override {
439
1.32k
    return std::make_unique<HostHandleImpl>(shared_from_this());
440
1.32k
  }
441
442
protected:
443
  static CreateConnectionData
444
  createConnection(Event::Dispatcher& dispatcher, const ClusterInfo& cluster,
445
                   const Network::Address::InstanceConstSharedPtr& address,
446
                   const std::vector<Network::Address::InstanceConstSharedPtr>& address_list,
447
                   Network::UpstreamTransportSocketFactory& socket_factory,
448
                   const Network::ConnectionSocket::OptionsSharedPtr& options,
449
                   Network::TransportSocketOptionsConstSharedPtr transport_socket_options,
450
                   HostDescriptionConstSharedPtr host);
451
452
private:
453
  // Helper function to check multiple health flags at once.
454
79.0M
  bool healthFlagsGet(uint32_t flags) const { return health_flags_ & flags; }
455
456
  void setEdsHealthFlag(envoy::config::core::v3::HealthStatus health_status);
457
458
  std::atomic<uint32_t> health_flags_{};
459
  std::atomic<uint32_t> weight_;
460
  bool disable_active_health_check_;
461
  // TODO(wbpcode): should we store the EDS health status to health_flags_ to get unified status or
462
  // flag access? May be we could refactor HealthFlag to contain all these statuses and flags in the
463
  // future.
464
  std::atomic<Host::HealthStatus> eds_health_status_{};
465
466
  struct HostHandleImpl : HostHandle {
467
1.32k
    HostHandleImpl(const std::shared_ptr<const HostImpl>& parent) : parent_(parent) {
468
1.32k
      parent->handle_count_++;
469
1.32k
    }
470
1.32k
    ~HostHandleImpl() override {
471
1.32k
      if (const auto host = parent_.lock()) {
472
1.32k
        ASSERT(host->handle_count_ > 0);
473
1.32k
        host->handle_count_--;
474
1.32k
      }
475
1.32k
    }
476
    const std::weak_ptr<const HostImpl> parent_;
477
  };
478
  mutable std::atomic<uint32_t> handle_count_{};
479
};
480
481
class HostsPerLocalityImpl : public HostsPerLocality {
482
public:
483
216k
  HostsPerLocalityImpl() : HostsPerLocalityImpl(std::vector<HostVector>(), false) {}
484
485
  // Single locality constructor
486
  //
487
  // Parameter requirements:
488
  // 1. All entries in hosts must have the same locality.
489
  // 2. If has_local_locality is true, then the locality of all entries in hosts
490
  //    must be equal to the current envoy's locality.
491
  HostsPerLocalityImpl(const HostVector& hosts, bool has_local_locality = false)
492
0
      : HostsPerLocalityImpl(std::vector<HostVector>({hosts}), has_local_locality) {}
493
494
  // Multiple localities constructor
495
  //
496
  // locality_hosts must adhere to the following ordering constraints:
497
  // 1. All hosts within a single HostVector bucket must have the same locality
498
  // 2. No hosts in different HostVector buckets can have the same locality
499
  // 3. If has_local_locality is true, then the locality of all hosts in the first HostVector bucket
500
  //    must be equal to the current envoy's locality.
501
  // 4. All non-local HostVector buckets must be sorted in ascending order by the LocalityLess
502
  // comparator
503
  HostsPerLocalityImpl(std::vector<HostVector>&& locality_hosts, bool has_local_locality)
504
257k
      : local_(has_local_locality), hosts_per_locality_(std::move(locality_hosts)) {
505
257k
    ASSERT(!has_local_locality || !hosts_per_locality_.empty());
506
257k
  }
507
508
0
  bool hasLocalLocality() const override { return local_; }
509
249k
  const std::vector<HostVector>& get() const override { return hosts_per_locality_; }
510
  std::vector<HostsPerLocalityConstSharedPtr>
511
  filter(const std::vector<std::function<bool(const Host&)>>& predicate) const override;
512
513
  // The const shared pointer for the empty HostsPerLocalityImpl.
514
39.5k
  static HostsPerLocalityConstSharedPtr empty() {
515
39.5k
    static HostsPerLocalityConstSharedPtr empty = std::make_shared<HostsPerLocalityImpl>();
516
39.5k
    return empty;
517
39.5k
  }
518
519
private:
520
  // Does an entry exist for the local locality?
521
  bool local_{};
522
  // The first entry is for local hosts in the local locality.
523
  std::vector<HostVector> hosts_per_locality_;
524
};
525
526
/**
527
 * A class for management of the set of hosts for a given priority level.
528
 */
529
class HostSetImpl : public HostSet {
530
public:
531
  HostSetImpl(uint32_t priority, absl::optional<bool> weighted_priority_health,
532
              absl::optional<uint32_t> overprovisioning_factor)
533
      : priority_(priority), overprovisioning_factor_(overprovisioning_factor.has_value()
534
                                                          ? overprovisioning_factor.value()
535
                                                          : kDefaultOverProvisioningFactor),
536
        weighted_priority_health_(weighted_priority_health.value_or(false)),
537
        hosts_(new HostVector()), healthy_hosts_(new HealthyHostVector()),
538
9.89k
        degraded_hosts_(new DegradedHostVector()), excluded_hosts_(new ExcludedHostVector()) {}
539
540
  /**
541
   * Install a callback that will be invoked when the host set membership changes.
542
   * @param callback supplies the callback to invoke.
543
   * @return Common::CallbackHandlePtr the callback handle.
544
   */
545
  ABSL_MUST_USE_RESULT Common::CallbackHandlePtr
546
9.89k
  addPriorityUpdateCb(PrioritySet::PriorityUpdateCb callback) const {
547
9.89k
    return member_update_cb_helper_.add(callback);
548
9.89k
  }
549
550
  // Upstream::HostSet
551
55.5k
  const HostVector& hosts() const override { return *hosts_; }
552
3.26k
  HostVectorConstSharedPtr hostsPtr() const override { return hosts_; }
553
31.7k
  const HostVector& healthyHosts() const override { return healthy_hosts_->get(); }
554
3.26k
  HealthyHostVectorConstSharedPtr healthyHostsPtr() const override { return healthy_hosts_; }
555
22.8k
  const HostVector& degradedHosts() const override { return degraded_hosts_->get(); }
556
3.26k
  DegradedHostVectorConstSharedPtr degradedHostsPtr() const override { return degraded_hosts_; }
557
22.8k
  const HostVector& excludedHosts() const override { return excluded_hosts_->get(); }
558
3.26k
  ExcludedHostVectorConstSharedPtr excludedHostsPtr() const override { return excluded_hosts_; }
559
2.04k
  const HostsPerLocality& hostsPerLocality() const override { return *hosts_per_locality_; }
560
3.26k
  HostsPerLocalityConstSharedPtr hostsPerLocalityPtr() const override {
561
3.26k
    return hosts_per_locality_;
562
3.26k
  }
563
26.1k
  const HostsPerLocality& healthyHostsPerLocality() const override {
564
26.1k
    return *healthy_hosts_per_locality_;
565
26.1k
  }
566
3.26k
  HostsPerLocalityConstSharedPtr healthyHostsPerLocalityPtr() const override {
567
3.26k
    return healthy_hosts_per_locality_;
568
3.26k
  }
569
26.1k
  const HostsPerLocality& degradedHostsPerLocality() const override {
570
26.1k
    return *degraded_hosts_per_locality_;
571
26.1k
  }
572
3.26k
  HostsPerLocalityConstSharedPtr degradedHostsPerLocalityPtr() const override {
573
3.26k
    return degraded_hosts_per_locality_;
574
3.26k
  }
575
0
  const HostsPerLocality& excludedHostsPerLocality() const override {
576
0
    return *excluded_hosts_per_locality_;
577
0
  }
578
3.26k
  HostsPerLocalityConstSharedPtr excludedHostsPerLocalityPtr() const override {
579
3.26k
    return excluded_hosts_per_locality_;
580
3.26k
  }
581
3.26k
  LocalityWeightsConstSharedPtr localityWeights() const override { return locality_weights_; }
582
  absl::optional<uint32_t> chooseHealthyLocality() override;
583
  absl::optional<uint32_t> chooseDegradedLocality() override;
584
14.5k
  uint32_t priority() const override { return priority_; }
585
16.3k
  uint32_t overprovisioningFactor() const override { return overprovisioning_factor_; }
586
9.80k
  bool weightedPriorityHealth() const override { return weighted_priority_health_; }
587
588
  static PrioritySet::UpdateHostsParams
589
  updateHostsParams(HostVectorConstSharedPtr hosts,
590
                    HostsPerLocalityConstSharedPtr hosts_per_locality,
591
                    HealthyHostVectorConstSharedPtr healthy_hosts,
592
                    HostsPerLocalityConstSharedPtr healthy_hosts_per_locality,
593
                    DegradedHostVectorConstSharedPtr degraded_hosts,
594
                    HostsPerLocalityConstSharedPtr degraded_hosts_per_locality,
595
                    ExcludedHostVectorConstSharedPtr excluded_hosts,
596
                    HostsPerLocalityConstSharedPtr excluded_hosts_per_locality);
597
  static PrioritySet::UpdateHostsParams updateHostsParams(const HostSet& host_set);
598
  static PrioritySet::UpdateHostsParams
599
  partitionHosts(HostVectorConstSharedPtr hosts, HostsPerLocalityConstSharedPtr hosts_per_locality);
600
601
  void updateHosts(PrioritySet::UpdateHostsParams&& update_hosts_params,
602
                   LocalityWeightsConstSharedPtr locality_weights, const HostVector& hosts_added,
603
                   const HostVector& hosts_removed,
604
                   absl::optional<bool> weighted_priority_health = absl::nullopt,
605
                   absl::optional<uint32_t> overprovisioning_factor = absl::nullopt);
606
607
protected:
608
10.9k
  virtual void runUpdateCallbacks(const HostVector& hosts_added, const HostVector& hosts_removed) {
609
10.9k
    member_update_cb_helper_.runCallbacks(priority_, hosts_added, hosts_removed);
610
10.9k
  }
611
612
private:
613
  // Weight for a locality taking into account health status using the provided eligible hosts per
614
  // locality.
615
  static double effectiveLocalityWeight(uint32_t index,
616
                                        const HostsPerLocality& eligible_hosts_per_locality,
617
                                        const HostsPerLocality& excluded_hosts_per_locality,
618
                                        const HostsPerLocality& all_hosts_per_locality,
619
                                        const LocalityWeights& locality_weights,
620
                                        uint32_t overprovisioning_factor);
621
622
  uint32_t priority_;
623
  uint32_t overprovisioning_factor_;
624
  bool weighted_priority_health_;
625
  HostVectorConstSharedPtr hosts_;
626
  HealthyHostVectorConstSharedPtr healthy_hosts_;
627
  DegradedHostVectorConstSharedPtr degraded_hosts_;
628
  ExcludedHostVectorConstSharedPtr excluded_hosts_;
629
  HostsPerLocalityConstSharedPtr hosts_per_locality_{HostsPerLocalityImpl::empty()};
630
  HostsPerLocalityConstSharedPtr healthy_hosts_per_locality_{HostsPerLocalityImpl::empty()};
631
  HostsPerLocalityConstSharedPtr degraded_hosts_per_locality_{HostsPerLocalityImpl::empty()};
632
  HostsPerLocalityConstSharedPtr excluded_hosts_per_locality_{HostsPerLocalityImpl::empty()};
633
  // TODO(mattklein123): Remove mutable.
634
  mutable Common::CallbackManager<uint32_t, const HostVector&, const HostVector&>
635
      member_update_cb_helper_;
636
  // Locality weights (used to build WRR locality_scheduler_);
637
  LocalityWeightsConstSharedPtr locality_weights_;
638
  // WRR locality scheduler state.
639
  struct LocalityEntry {
640
    LocalityEntry(uint32_t index, double effective_weight)
641
0
        : index_(index), effective_weight_(effective_weight) {}
642
    const uint32_t index_;
643
    const double effective_weight_;
644
  };
645
646
  // Rebuilds the provided locality scheduler with locality entries based on the locality weights
647
  // and eligible hosts.
648
  //
649
  // @param locality_scheduler the locality scheduler to rebuild. Will be set to nullptr if no
650
  // localities are eligible.
651
  // @param locality_entries the vector that holds locality entries. Will be reset and populated
652
  // with entries corresponding to the new scheduler.
653
  // @param eligible_hosts_per_locality eligible hosts for this scheduler grouped by locality.
654
  // @param eligible_hosts all eligible hosts for this scheduler.
655
  // @param all_hosts_per_locality all hosts for this HostSet grouped by locality.
656
  // @param locality_weights the weighting of each locality.
657
  // @param overprovisioning_factor the overprovisioning factor to use when computing the effective
658
  // weight of a locality.
659
  static void rebuildLocalityScheduler(
660
      std::unique_ptr<EdfScheduler<LocalityEntry>>& locality_scheduler,
661
      std::vector<std::shared_ptr<LocalityEntry>>& locality_entries,
662
      const HostsPerLocality& eligible_hosts_per_locality, const HostVector& eligible_hosts,
663
      HostsPerLocalityConstSharedPtr all_hosts_per_locality,
664
      HostsPerLocalityConstSharedPtr excluded_hosts_per_locality,
665
      LocalityWeightsConstSharedPtr locality_weights, uint32_t overprovisioning_factor);
666
667
  static absl::optional<uint32_t> chooseLocality(EdfScheduler<LocalityEntry>* locality_scheduler);
668
669
  std::vector<std::shared_ptr<LocalityEntry>> healthy_locality_entries_;
670
  std::unique_ptr<EdfScheduler<LocalityEntry>> healthy_locality_scheduler_;
671
  std::vector<std::shared_ptr<LocalityEntry>> degraded_locality_entries_;
672
  std::unique_ptr<EdfScheduler<LocalityEntry>> degraded_locality_scheduler_;
673
};
674
675
using HostSetImplPtr = std::unique_ptr<HostSetImpl>;
676
677
/**
678
 * A class for management of the set of hosts in a given cluster.
679
 */
680
class PrioritySetImpl : public PrioritySet {
681
public:
682
9.89k
  PrioritySetImpl() : batch_update_(false) {}
683
  // From PrioritySet
684
  ABSL_MUST_USE_RESULT Common::CallbackHandlePtr
685
9.80k
  addMemberUpdateCb(MemberUpdateCb callback) const override {
686
9.80k
    return member_update_cb_helper_.add(callback);
687
9.80k
  }
688
  ABSL_MUST_USE_RESULT Common::CallbackHandlePtr
689
26.2k
  addPriorityUpdateCb(PriorityUpdateCb callback) const override {
690
26.2k
    return priority_update_cb_helper_.add(callback);
691
26.2k
  }
692
186k
  const std::vector<std::unique_ptr<HostSet>>& hostSetsPerPriority() const override {
693
186k
    return host_sets_;
694
186k
  }
695
  // Get the host set for this priority level, creating it if necessary.
696
  const HostSet&
697
  getOrCreateHostSet(uint32_t priority,
698
                     absl::optional<bool> weighted_priority_health = absl::nullopt,
699
                     absl::optional<uint32_t> overprovisioning_factor = absl::nullopt);
700
701
  void updateHosts(uint32_t priority, UpdateHostsParams&& update_hosts_params,
702
                   LocalityWeightsConstSharedPtr locality_weights, const HostVector& hosts_added,
703
                   const HostVector& hosts_removed,
704
                   absl::optional<bool> weighted_priority_health = absl::nullopt,
705
                   absl::optional<uint32_t> overprovisioning_factor = absl::nullopt,
706
                   HostMapConstSharedPtr cross_priority_host_map = nullptr) override;
707
708
  void batchHostUpdate(BatchUpdateCb& callback) override;
709
710
2.39k
  HostMapConstSharedPtr crossPriorityHostMap() const override {
711
2.39k
    return const_cross_priority_host_map_;
712
2.39k
  }
713
714
protected:
715
  // Allows subclasses of PrioritySetImpl to create their own type of HostSetImpl.
716
  virtual HostSetImplPtr createHostSet(uint32_t priority,
717
                                       absl::optional<bool> weighted_priority_health,
718
9.89k
                                       absl::optional<uint32_t> overprovisioning_factor) {
719
9.89k
    return std::make_unique<HostSetImpl>(priority, weighted_priority_health,
720
9.89k
                                         overprovisioning_factor);
721
9.89k
  }
722
723
protected:
724
10.9k
  virtual void runUpdateCallbacks(const HostVector& hosts_added, const HostVector& hosts_removed) {
725
10.9k
    member_update_cb_helper_.runCallbacks(hosts_added, hosts_removed);
726
10.9k
  }
727
  virtual void runReferenceUpdateCallbacks(uint32_t priority, const HostVector& hosts_added,
728
10.9k
                                           const HostVector& hosts_removed) {
729
10.9k
    priority_update_cb_helper_.runCallbacks(priority, hosts_added, hosts_removed);
730
10.9k
  }
731
  // This vector will generally have at least one member, for priority level 0.
732
  // It will expand as host sets are added but currently does not shrink to
733
  // avoid any potential lifetime issues.
734
  std::vector<std::unique_ptr<HostSet>> host_sets_;
735
736
  // Read only all host map for fast host searching. This will never be null.
737
  mutable HostMapConstSharedPtr const_cross_priority_host_map_{std::make_shared<HostMap>()};
738
739
private:
740
  // This is a matching vector to store the callback handles for host_sets_. It is kept separately
741
  // because host_sets_ is directly returned so we avoid translation.
742
  std::vector<Common::CallbackHandlePtr> host_sets_priority_update_cbs_;
743
  // TODO(mattklein123): Remove mutable.
744
  mutable Common::CallbackManager<const HostVector&, const HostVector&> member_update_cb_helper_;
745
  mutable Common::CallbackManager<uint32_t, const HostVector&, const HostVector&>
746
      priority_update_cb_helper_;
747
  bool batch_update_ : 1;
748
749
  // Helper class to maintain state as we perform multiple host updates. Keeps track of all hosts
750
  // that have been added/removed throughout the batch update, and ensures that we properly manage
751
  // the batch_update_ flag.
752
  class BatchUpdateScope : public HostUpdateCb {
753
  public:
754
14
    explicit BatchUpdateScope(PrioritySetImpl& parent) : parent_(parent) {
755
14
      ASSERT(!parent_.batch_update_);
756
14
      parent_.batch_update_ = true;
757
14
    }
758
14
    ~BatchUpdateScope() override { parent_.batch_update_ = false; }
759
760
    void updateHosts(uint32_t priority, PrioritySet::UpdateHostsParams&& update_hosts_params,
761
                     LocalityWeightsConstSharedPtr locality_weights, const HostVector& hosts_added,
762
                     const HostVector& hosts_removed, absl::optional<bool> weighted_priority_health,
763
                     absl::optional<uint32_t> overprovisioning_factor) override;
764
765
    absl::node_hash_set<HostSharedPtr> all_hosts_added_;
766
    absl::node_hash_set<HostSharedPtr> all_hosts_removed_;
767
768
  private:
769
    PrioritySetImpl& parent_;
770
    absl::node_hash_set<uint32_t> priorities_;
771
  };
772
};
773
774
/**
775
 * Specialized PrioritySetImpl designed for the main thread. It will update and maintain the read
776
 * only cross priority host map when the host set changes.
777
 */
778
class MainPrioritySetImpl : public PrioritySetImpl, public Logger::Loggable<Logger::Id::upstream> {
779
public:
780
  // PrioritySet
781
  void updateHosts(uint32_t priority, UpdateHostsParams&& update_hosts_params,
782
                   LocalityWeightsConstSharedPtr locality_weights, const HostVector& hosts_added,
783
                   const HostVector& hosts_removed,
784
                   absl::optional<bool> weighted_priority_health = absl::nullopt,
785
                   absl::optional<uint32_t> overprovisioning_factor = absl::nullopt,
786
                   HostMapConstSharedPtr cross_priority_host_map = nullptr) override;
787
  HostMapConstSharedPtr crossPriorityHostMap() const override;
788
789
protected:
790
  void updateCrossPriorityHostMap(const HostVector& hosts_added, const HostVector& hosts_removed);
791
792
  mutable HostMapSharedPtr mutable_cross_priority_host_map_;
793
};
794
795
/**
796
 * Implementation of ClusterInfo that reads from JSON.
797
 */
798
class ClusterInfoImpl : public ClusterInfo,
799
                        public Event::DispatcherThreadDeletable,
800
                        protected Logger::Loggable<Logger::Id::upstream> {
801
public:
802
  using HttpProtocolOptionsConfigImpl =
803
      Envoy::Extensions::Upstreams::Http::ProtocolOptionsConfigImpl;
804
  using TcpProtocolOptionsConfigImpl = Envoy::Extensions::Upstreams::Tcp::ProtocolOptionsConfigImpl;
805
  ClusterInfoImpl(Init::Manager& info, Server::Configuration::ServerFactoryContext& server_context,
806
                  const envoy::config::cluster::v3::Cluster& config,
807
                  const absl::optional<envoy::config::core::v3::BindConfig>& bind_config,
808
                  Runtime::Loader& runtime, TransportSocketMatcherPtr&& socket_matcher,
809
                  Stats::ScopeSharedPtr&& stats_scope, bool added_via_api,
810
                  Server::Configuration::TransportSocketFactoryContext&);
811
812
  static DeferredCreationCompatibleClusterTrafficStats
813
  generateStats(Stats::ScopeSharedPtr scope, const ClusterTrafficStatNames& cluster_stat_names,
814
                bool defer_creation);
815
  static ClusterLoadReportStats
816
  generateLoadReportStats(Stats::Scope& scope, const ClusterLoadReportStatNames& stat_names);
817
  static ClusterCircuitBreakersStats
818
  generateCircuitBreakersStats(Stats::Scope& scope, Stats::StatName prefix, bool track_remaining,
819
                               const ClusterCircuitBreakersStatNames& stat_names);
820
  static ClusterRequestResponseSizeStats
821
  generateRequestResponseSizeStats(Stats::Scope&,
822
                                   const ClusterRequestResponseSizeStatNames& stat_names);
823
  static ClusterTimeoutBudgetStats
824
  generateTimeoutBudgetStats(Stats::Scope&, const ClusterTimeoutBudgetStatNames& stat_names);
825
826
  // Upstream::ClusterInfo
827
6.52k
  bool addedViaApi() const override { return added_via_api_; }
828
3.26k
  OptRef<const LoadBalancerConfig> loadBalancerConfig() const override {
829
3.26k
    return makeOptRefFromPtr<const LoadBalancerConfig>(load_balancer_config_.get());
830
3.26k
  }
831
6.53k
  TypedLoadBalancerFactory* loadBalancerFactory() const override { return load_balancer_factory_; }
832
16.3k
  const envoy::config::cluster::v3::Cluster::CommonLbConfig& lbConfig() const override {
833
16.3k
    return *common_lb_config_;
834
16.3k
  }
835
1.32k
  std::chrono::milliseconds connectTimeout() const override { return connect_timeout_; }
836
837
  // `OptionalTimeouts` manages various `optional` values. We pack them in a separate data
838
  // structure for memory efficiency -- avoiding overhead of `absl::optional` per variable, and
839
  // avoiding overhead of storing unset timeouts.
840
  enum class OptionalTimeoutNames { IdleTimeout = 0, TcpPoolIdleTimeout, MaxConnectionDuration };
841
  using OptionalTimeouts = PackedStruct<std::chrono::milliseconds, 3, OptionalTimeoutNames>;
842
843
1.32k
  const absl::optional<std::chrono::milliseconds> idleTimeout() const override {
844
1.32k
    auto timeout = optional_timeouts_.get<OptionalTimeoutNames::IdleTimeout>();
845
1.32k
    if (timeout.has_value()) {
846
1.32k
      return *timeout;
847
1.32k
    }
848
0
    return absl::nullopt;
849
1.32k
  }
850
0
  const absl::optional<std::chrono::milliseconds> tcpPoolIdleTimeout() const override {
851
0
    auto timeout = optional_timeouts_.get<OptionalTimeoutNames::TcpPoolIdleTimeout>();
852
0
    if (timeout.has_value()) {
853
0
      return *timeout;
854
0
    }
855
0
    return absl::nullopt;
856
0
  }
857
1.31k
  const absl::optional<std::chrono::milliseconds> maxConnectionDuration() const override {
858
1.31k
    auto timeout = optional_timeouts_.get<OptionalTimeoutNames::MaxConnectionDuration>();
859
1.31k
    if (timeout.has_value()) {
860
0
      return *timeout;
861
0
    }
862
1.31k
    return absl::nullopt;
863
1.31k
  }
864
865
3.73k
  float perUpstreamPreconnectRatio() const override { return per_upstream_preconnect_ratio_; }
866
2.39k
  float peekaheadRatio() const override { return peekahead_ratio_; }
867
1.32k
  uint32_t perConnectionBufferLimitBytes() const override {
868
1.32k
    return per_connection_buffer_limit_bytes_;
869
1.32k
  }
870
8.92k
  uint64_t features() const override { return features_; }
871
53
  const Http::Http1Settings& http1Settings() const override {
872
53
    return http_protocol_options_->http1_settings_;
873
53
  }
874
3.81k
  const envoy::config::core::v3::Http2ProtocolOptions& http2Options() const override {
875
3.81k
    return http_protocol_options_->http2_options_;
876
3.81k
  }
877
0
  const envoy::config::core::v3::Http3ProtocolOptions& http3Options() const override {
878
0
    return http_protocol_options_->http3_options_;
879
0
  }
880
2.32k
  const envoy::config::core::v3::HttpProtocolOptions& commonHttpProtocolOptions() const override {
881
2.32k
    return http_protocol_options_->common_http_protocol_options_;
882
2.32k
  }
883
  void configureLbPolicies(const envoy::config::cluster::v3::Cluster& config,
884
                           Server::Configuration::ServerFactoryContext& context);
885
  ProtocolOptionsConfigConstSharedPtr
886
  extensionProtocolOptions(const std::string& name) const override;
887
26.1k
  LoadBalancerType lbType() const override { return lb_type_; }
888
0
  envoy::config::cluster::v3::Cluster::DiscoveryType type() const override { return type_; }
889
890
  OptRef<const envoy::config::cluster::v3::Cluster::CustomClusterType>
891
0
  clusterType() const override {
892
0
    if (cluster_type_ == nullptr) {
893
0
      return absl::nullopt;
894
0
    }
895
0
    return *cluster_type_;
896
0
  }
897
  OptRef<const envoy::config::cluster::v3::Cluster::RoundRobinLbConfig>
898
0
  lbRoundRobinConfig() const override {
899
0
    if (lb_policy_config_ == nullptr) {
900
0
      return {};
901
0
    }
902
903
0
    return lb_policy_config_->lbRoundRobinConfig();
904
0
  }
905
  OptRef<const envoy::config::cluster::v3::Cluster::LeastRequestLbConfig>
906
0
  lbLeastRequestConfig() const override {
907
0
    if (lb_policy_config_ == nullptr) {
908
0
      return {};
909
0
    }
910
911
0
    return lb_policy_config_->lbLeastRequestConfig();
912
0
  }
913
  OptRef<const envoy::config::cluster::v3::Cluster::RingHashLbConfig>
914
0
  lbRingHashConfig() const override {
915
0
    if (lb_policy_config_ == nullptr) {
916
0
      return {};
917
0
    }
918
919
0
    return lb_policy_config_->lbRingHashConfig();
920
0
  }
921
  OptRef<const envoy::config::cluster::v3::Cluster::MaglevLbConfig>
922
0
  lbMaglevConfig() const override {
923
0
    if (lb_policy_config_ == nullptr) {
924
0
      return {};
925
0
    }
926
927
0
    return lb_policy_config_->lbMaglevConfig();
928
0
  }
929
  OptRef<const envoy::config::cluster::v3::Cluster::OriginalDstLbConfig>
930
0
  lbOriginalDstConfig() const override {
931
0
    if (lb_policy_config_ == nullptr) {
932
0
      return {};
933
0
    }
934
935
0
    return lb_policy_config_->lbOriginalDstConfig();
936
0
  }
937
2.39k
  OptRef<const envoy::config::core::v3::TypedExtensionConfig> upstreamConfig() const override {
938
2.39k
    if (upstream_config_ == nullptr) {
939
2.39k
      return absl::nullopt;
940
2.39k
    }
941
0
    return *upstream_config_;
942
2.39k
  }
943
  bool maintenanceMode() const override;
944
2.59k
  uint64_t maxRequestsPerConnection() const override { return max_requests_per_connection_; }
945
1.32k
  uint32_t maxResponseHeadersCount() const override { return max_response_headers_count_; }
946
54.6k
  const std::string& name() const override { return name_; }
947
0
  const std::string& observabilityName() const override {
948
0
    if (observability_name_ != nullptr) {
949
0
      return *observability_name_;
950
0
    }
951
0
    return name_;
952
0
  }
953
  ResourceManager& resourceManager(ResourcePriority priority) const override;
954
3.26k
  TransportSocketMatcher& transportSocketMatcher() const override { return *socket_matcher_; }
955
22.4k
  DeferredCreationCompatibleClusterTrafficStats& trafficStats() const override {
956
22.4k
    return traffic_stats_;
957
22.4k
  }
958
9.80k
  ClusterConfigUpdateStats& configUpdateStats() const override { return config_update_stats_; }
959
6.53k
  ClusterLbStats& lbStats() const override { return lb_stats_; }
960
16.3k
  ClusterEndpointStats& endpointStats() const override { return endpoint_stats_; }
961
6.64k
  Stats::Scope& statsScope() const override { return *stats_scope_; }
962
963
2.39k
  ClusterRequestResponseSizeStatsOptRef requestResponseSizeStats() const override {
964
2.39k
    if (optional_cluster_stats_ == nullptr ||
965
2.39k
        optional_cluster_stats_->request_response_size_stats_ == nullptr) {
966
2.39k
      return absl::nullopt;
967
2.39k
    }
968
969
0
    return std::ref(*(optional_cluster_stats_->request_response_size_stats_));
970
2.39k
  }
971
972
0
  ClusterLoadReportStats& loadReportStats() const override { return load_report_stats_; }
973
974
3.57k
  ClusterTimeoutBudgetStatsOptRef timeoutBudgetStats() const override {
975
3.57k
    if (optional_cluster_stats_ == nullptr ||
976
3.57k
        optional_cluster_stats_->timeout_budget_stats_ == nullptr) {
977
3.57k
      return absl::nullopt;
978
3.57k
    }
979
980
0
    return std::ref(*(optional_cluster_stats_->timeout_budget_stats_));
981
3.57k
  }
982
983
6.55k
  bool perEndpointStatsEnabled() const override { return per_endpoint_stats_; }
984
985
1.32k
  UpstreamLocalAddressSelectorConstSharedPtr getUpstreamLocalAddressSelector() const override {
986
1.32k
    return upstream_local_address_selector_;
987
1.32k
  }
988
6.53k
  const LoadBalancerSubsetInfo& lbSubsetInfo() const override {
989
6.53k
    if (lb_subset_ != nullptr) {
990
0
      return *lb_subset_;
991
0
    }
992
6.53k
    return DefaultLoadBalancerSubsetInfoImpl::get();
993
6.53k
  }
994
  using DefaultMetadata = ConstSingleton<envoy::config::core::v3::Metadata>;
995
0
  const envoy::config::core::v3::Metadata& metadata() const override {
996
0
    if (metadata_ != nullptr) {
997
0
      return *metadata_;
998
0
    }
999
0
    return DefaultMetadata::get();
1000
0
  }
1001
  using ClusterTypedMetadata = Envoy::Config::TypedMetadataImpl<ClusterTypedMetadataFactory>;
1002
0
  const Envoy::Config::TypedMetadata& typedMetadata() const override {
1003
0
    if (typed_metadata_ != nullptr) {
1004
0
      return *typed_metadata_;
1005
0
    }
1006
0
    CONSTRUCT_ON_FIRST_USE(ClusterTypedMetadata, DefaultMetadata::get());
1007
0
  }
1008
1009
0
  bool drainConnectionsOnHostRemoval() const override { return drain_connections_on_host_removal_; }
1010
2.39k
  bool connectionPoolPerDownstreamConnection() const override {
1011
2.39k
    return connection_pool_per_downstream_connection_;
1012
2.39k
  }
1013
0
  bool warmHosts() const override { return warm_hosts_; }
1014
1.32k
  bool setLocalInterfaceNameOnUpstreamConnections() const override {
1015
1.32k
    return set_local_interface_name_on_upstream_connections_;
1016
1.32k
  }
1017
  const absl::optional<envoy::config::core::v3::UpstreamHttpProtocolOptions>&
1018
2.39k
  upstreamHttpProtocolOptions() const override {
1019
2.39k
    return http_protocol_options_->upstream_http_protocol_options_;
1020
2.39k
  }
1021
1022
  const absl::optional<const envoy::config::core::v3::AlternateProtocolsCacheOptions>&
1023
2.39k
  alternateProtocolsCacheOptions() const override {
1024
2.39k
    return http_protocol_options_->alternate_protocol_cache_options_;
1025
2.39k
  }
1026
1027
28
  const std::string& edsServiceName() const override {
1028
28
    return eds_service_name_ != nullptr ? *eds_service_name_ : EMPTY_STRING;
1029
28
  }
1030
1031
  void createNetworkFilterChain(Network::Connection&) const override;
1032
  std::vector<Http::Protocol>
1033
  upstreamHttpProtocol(absl::optional<Http::Protocol> downstream_protocol) const override;
1034
1035
  // Http::FilterChainFactory
1036
  bool createFilterChain(Http::FilterChainManager& manager, bool only_create_if_configured,
1037
4.78k
                         const Http::FilterChainOptions&) const override {
1038
4.78k
    if (!has_configured_http_filters_ && only_create_if_configured) {
1039
2.39k
      return false;
1040
2.39k
    }
1041
2.39k
    Http::FilterChainUtility::createFilterChainForFactories(
1042
2.39k
        manager, Http::EmptyFilterChainOptions{}, http_filter_factories_);
1043
2.39k
    return true;
1044
4.78k
  }
1045
  bool createUpgradeFilterChain(absl::string_view, const UpgradeMap*,
1046
0
                                Http::FilterChainManager&) const override {
1047
    // Upgrade filter chains not yet supported for upstream HTTP filters.
1048
0
    return false;
1049
0
  }
1050
1051
  Http::Http1::CodecStats& http1CodecStats() const override;
1052
  Http::Http2::CodecStats& http2CodecStats() const override;
1053
  Http::Http3::CodecStats& http3CodecStats() const override;
1054
  Http::ClientHeaderValidatorPtr makeHeaderValidator(Http::Protocol protocol) const override;
1055
1056
protected:
1057
  // Gets the retry budget percent/concurrency from the circuit breaker thresholds. If the retry
1058
  // budget message is specified, defaults will be filled in if either params are unspecified.
1059
  static std::pair<absl::optional<double>, absl::optional<uint32_t>>
1060
  getRetryBudgetParams(const envoy::config::cluster::v3::CircuitBreakers::Thresholds& thresholds);
1061
1062
private:
1063
  std::shared_ptr<UpstreamNetworkFilterConfigProviderManager>
1064
  createSingletonUpstreamNetworkFilterConfigProviderManager(
1065
      Server::Configuration::ServerFactoryContext& context);
1066
1067
  struct ResourceManagers {
1068
    ResourceManagers(const envoy::config::cluster::v3::Cluster& config, Runtime::Loader& runtime,
1069
                     const std::string& cluster_name, Stats::Scope& stats_scope,
1070
                     const ClusterCircuitBreakersStatNames& circuit_breakers_stat_names);
1071
    ResourceManagerImplPtr load(const envoy::config::cluster::v3::Cluster& config,
1072
                                Runtime::Loader& runtime, const std::string& cluster_name,
1073
                                Stats::Scope& stats_scope,
1074
                                const envoy::config::core::v3::RoutingPriority& priority);
1075
1076
    using Managers = std::array<ResourceManagerImplPtr, NumResourcePriorities>;
1077
1078
    Managers managers_;
1079
    const ClusterCircuitBreakersStatNames& circuit_breakers_stat_names_;
1080
  };
1081
1082
  struct OptionalClusterStats {
1083
    OptionalClusterStats(const envoy::config::cluster::v3::Cluster& config,
1084
                         Stats::Scope& stats_scope, const ClusterManager& manager);
1085
    const ClusterTimeoutBudgetStatsPtr timeout_budget_stats_;
1086
    const ClusterRequestResponseSizeStatsPtr request_response_size_stats_;
1087
  };
1088
1089
#ifdef ENVOY_ENABLE_UHV
1090
  ::Envoy::Http::HeaderValidatorStats& getHeaderValidatorStats(Http::Protocol protocol) const;
1091
#endif
1092
1093
  Runtime::Loader& runtime_;
1094
  const std::string name_;
1095
  std::unique_ptr<const std::string> observability_name_;
1096
  std::unique_ptr<const std::string> eds_service_name_;
1097
  const absl::flat_hash_map<std::string, ProtocolOptionsConfigConstSharedPtr>
1098
      extension_protocol_options_;
1099
  const std::shared_ptr<const HttpProtocolOptionsConfigImpl> http_protocol_options_;
1100
  const std::shared_ptr<const TcpProtocolOptionsConfigImpl> tcp_protocol_options_;
1101
  const uint64_t max_requests_per_connection_;
1102
  const std::chrono::milliseconds connect_timeout_;
1103
  OptionalTimeouts optional_timeouts_;
1104
  const float per_upstream_preconnect_ratio_;
1105
  const float peekahead_ratio_;
1106
  TransportSocketMatcherPtr socket_matcher_;
1107
  Stats::ScopeSharedPtr stats_scope_;
1108
  mutable DeferredCreationCompatibleClusterTrafficStats traffic_stats_;
1109
  mutable ClusterConfigUpdateStats config_update_stats_;
1110
  mutable ClusterLbStats lb_stats_;
1111
  mutable ClusterEndpointStats endpoint_stats_;
1112
  Stats::IsolatedStoreImpl load_report_stats_store_;
1113
  mutable ClusterLoadReportStats load_report_stats_;
1114
  const std::unique_ptr<OptionalClusterStats> optional_cluster_stats_;
1115
  const uint64_t features_;
1116
  mutable ResourceManagers resource_managers_;
1117
  const std::string maintenance_mode_runtime_key_;
1118
  UpstreamLocalAddressSelectorConstSharedPtr upstream_local_address_selector_;
1119
  std::unique_ptr<const LBPolicyConfig> lb_policy_config_;
1120
  std::unique_ptr<envoy::config::core::v3::TypedExtensionConfig> upstream_config_;
1121
  std::unique_ptr<LoadBalancerSubsetInfoImpl> lb_subset_;
1122
  std::unique_ptr<const envoy::config::core::v3::Metadata> metadata_;
1123
  std::unique_ptr<ClusterTypedMetadata> typed_metadata_;
1124
  LoadBalancerConfigPtr load_balancer_config_;
1125
  TypedLoadBalancerFactory* load_balancer_factory_ = nullptr;
1126
  const std::shared_ptr<const envoy::config::cluster::v3::Cluster::CommonLbConfig>
1127
      common_lb_config_;
1128
  std::unique_ptr<const envoy::config::cluster::v3::Cluster::CustomClusterType> cluster_type_;
1129
  // TODO(ohadvano): http_filter_config_provider_manager_ and
1130
  // network_filter_config_provider_manager_ should be maintained in the ClusterManager object as a
1131
  // singleton. This is currently not possible due to circular dependency (filter config provider
1132
  // manager depends on the ClusterManager object). The circular dependency can be resolved when the
1133
  // following issue is resolved: https://github.com/envoyproxy/envoy/issues/26653.
1134
  std::shared_ptr<Http::UpstreamFilterConfigProviderManager> http_filter_config_provider_manager_;
1135
  std::shared_ptr<UpstreamNetworkFilterConfigProviderManager>
1136
      network_filter_config_provider_manager_;
1137
  Filter::NetworkFilterFactoriesList filter_factories_;
1138
  Http::FilterChainUtility::FilterFactoriesList http_filter_factories_;
1139
  mutable Http::Http1::CodecStats::AtomicPtr http1_codec_stats_;
1140
  mutable Http::Http2::CodecStats::AtomicPtr http2_codec_stats_;
1141
  mutable Http::Http3::CodecStats::AtomicPtr http3_codec_stats_;
1142
  UpstreamFactoryContextImpl upstream_context_;
1143
1144
  // Keep small values like bools and enums at the end of the class to reduce
1145
  // overhead via alignment
1146
  const uint32_t per_connection_buffer_limit_bytes_;
1147
  const uint32_t max_response_headers_count_;
1148
  LoadBalancerType lb_type_;
1149
  const envoy::config::cluster::v3::Cluster::DiscoveryType type_;
1150
  const bool drain_connections_on_host_removal_ : 1;
1151
  const bool connection_pool_per_downstream_connection_ : 1;
1152
  const bool warm_hosts_ : 1;
1153
  const bool set_local_interface_name_on_upstream_connections_ : 1;
1154
  const bool added_via_api_ : 1;
1155
  // true iff the cluster proto specified upstream http filters.
1156
  bool has_configured_http_filters_ : 1;
1157
  const bool per_endpoint_stats_ : 1;
1158
};
1159
1160
/**
1161
 * Function that creates a Network::UpstreamTransportSocketFactoryPtr
1162
 * given a cluster configuration and transport socket factory
1163
 * context.
1164
 */
1165
Network::UpstreamTransportSocketFactoryPtr
1166
createTransportSocketFactory(const envoy::config::cluster::v3::Cluster& config,
1167
                             Server::Configuration::TransportSocketFactoryContext& factory_context);
1168
1169
/**
1170
 * Base class all primary clusters.
1171
 */
1172
class ClusterImplBase : public Cluster, protected Logger::Loggable<Logger::Id::upstream> {
1173
1174
public:
1175
  // Upstream::Cluster
1176
26.1k
  PrioritySet& prioritySet() override { return priority_set_; }
1177
0
  const PrioritySet& prioritySet() const override { return priority_set_; }
1178
1179
  /**
1180
   * Optionally set the health checker for the primary cluster. This is done after cluster
1181
   * creation since the health checker assumes that the cluster has already been fully initialized
1182
   * so there is a cyclic dependency. However we want the cluster to own the health checker.
1183
   */
1184
  void setHealthChecker(const HealthCheckerSharedPtr& health_checker);
1185
1186
  /**
1187
   * Optionally set the outlier detector for the primary cluster. Done for the same reason as
1188
   * documented in setHealthChecker().
1189
   */
1190
  void setOutlierDetector(const Outlier::DetectorSharedPtr& outlier_detector);
1191
1192
  /**
1193
   * Wrapper around Network::Address::resolveProtoAddress() that provides improved error message
1194
   * based on the cluster's type.
1195
   * @param address supplies the address proto to resolve.
1196
   * @return Network::Address::InstanceConstSharedPtr the resolved address.
1197
   */
1198
  const Network::Address::InstanceConstSharedPtr
1199
  resolveProtoAddress(const envoy::config::core::v3::Address& address);
1200
1201
  // Partitions the provided list of hosts into three new lists containing the healthy, degraded
1202
  // and excluded hosts respectively.
1203
  static std::tuple<HealthyHostVectorConstSharedPtr, DegradedHostVectorConstSharedPtr,
1204
                    ExcludedHostVectorConstSharedPtr>
1205
  partitionHostList(const HostVector& hosts);
1206
1207
  // Partitions the provided list of hosts per locality into three new lists containing the healthy,
1208
  // degraded and excluded hosts respectively.
1209
  static std::tuple<HostsPerLocalityConstSharedPtr, HostsPerLocalityConstSharedPtr,
1210
                    HostsPerLocalityConstSharedPtr>
1211
  partitionHostsPerLocality(const HostsPerLocality& hosts);
1212
0
  Config::ConstMetadataSharedPoolSharedPtr constMetadataSharedPool() {
1213
0
    return const_metadata_shared_pool_;
1214
0
  }
1215
1216
  // Upstream::Cluster
1217
3.26k
  HealthChecker* healthChecker() override { return health_checker_.get(); }
1218
55.5k
  ClusterInfoConstSharedPtr info() const override { return info_; }
1219
3.26k
  Outlier::Detector* outlierDetector() override { return outlier_detector_.get(); }
1220
0
  const Outlier::Detector* outlierDetector() const override { return outlier_detector_.get(); }
1221
  void initialize(std::function<void()> callback) override;
1222
1223
protected:
1224
  ClusterImplBase(const envoy::config::cluster::v3::Cluster& cluster,
1225
                  ClusterFactoryContext& cluster_context);
1226
1227
  /**
1228
   * Overridden by every concrete cluster. The cluster should do whatever pre-init is needed. E.g.,
1229
   * query DNS, contact EDS, etc.
1230
   */
1231
  virtual void startPreInit() PURE;
1232
1233
  /**
1234
   * Called by every concrete cluster when pre-init is complete. At this point,
1235
   * shared init starts init_manager_ initialization and determines if there
1236
   * is an initial health check pass needed, etc.
1237
   */
1238
  void onPreInitComplete();
1239
1240
  /**
1241
   * Called by every concrete cluster after all targets registered at init manager are
1242
   * initialized. At this point, shared init takes over and determines if there is an initial health
1243
   * check pass needed, etc.
1244
   */
1245
  void onInitDone();
1246
1247
  virtual void reloadHealthyHostsHelper(const HostSharedPtr& host);
1248
1249
  // This init manager is shared via TransportSocketFactoryContext. The initialization targets that
1250
  // register with this init manager are expected to be for implementations of SdsApi (see
1251
  // SdsApi::init_target_).
1252
  Init::ManagerImpl init_manager_;
1253
1254
  // Once all targets are initialized (i.e. once all dynamic secrets are loaded), this watcher calls
1255
  // onInitDone() above.
1256
  Init::WatcherImpl init_watcher_;
1257
1258
  Runtime::Loader& runtime_;
1259
  ClusterInfoConstSharedPtr info_; // This cluster info stores the stats scope so it must be
1260
                                   // initialized first and destroyed last.
1261
  HealthCheckerSharedPtr health_checker_;
1262
  Outlier::DetectorSharedPtr outlier_detector_;
1263
  const bool wait_for_warm_on_init_;
1264
1265
  Server::Configuration::TransportSocketFactoryContextImplPtr transport_factory_context_{};
1266
1267
protected:
1268
  TimeSource& time_source_;
1269
  MainPrioritySetImpl priority_set_;
1270
1271
  void validateEndpointsForZoneAwareRouting(
1272
      const envoy::config::endpoint::v3::LocalityLbEndpoints& endpoints) const;
1273
1274
private:
1275
  static const absl::string_view DoNotValidateAlpnRuntimeKey;
1276
1277
  void finishInitialization();
1278
  void reloadHealthyHosts(const HostSharedPtr& host);
1279
1280
  bool initialization_started_{};
1281
  std::function<void()> initialization_complete_callback_;
1282
  uint64_t pending_initialize_health_checks_{};
1283
  const bool local_cluster_;
1284
  Config::ConstMetadataSharedPoolSharedPtr const_metadata_shared_pool_;
1285
  Common::CallbackHandlePtr priority_update_cb_;
1286
};
1287
1288
using ClusterImplBaseSharedPtr = std::shared_ptr<ClusterImplBase>;
1289
1290
/**
1291
 * Manages PriorityState of a cluster. PriorityState is a per-priority binding of a set of hosts
1292
 * with its corresponding locality weight map. This is useful to store priorities/hosts/localities
1293
 * before updating the cluster priority set.
1294
 */
1295
class PriorityStateManager : protected Logger::Loggable<Logger::Id::upstream> {
1296
public:
1297
  PriorityStateManager(ClusterImplBase& cluster, const LocalInfo::LocalInfo& local_info,
1298
                       PrioritySet::HostUpdateCb* update_cb);
1299
1300
  // Initializes the PriorityState vector based on the priority specified in locality_lb_endpoint.
1301
  void initializePriorityFor(
1302
      const envoy::config::endpoint::v3::LocalityLbEndpoints& locality_lb_endpoint);
1303
1304
  // Registers a host based on its address to the PriorityState based on the specified priority (the
1305
  // priority is specified by locality_lb_endpoint.priority()).
1306
  //
1307
  // The specified health_checker_flag is used to set the registered-host's health-flag when the
1308
  // lb_endpoint health status is unhealthy, draining or timeout.
1309
  void registerHostForPriority(
1310
      const std::string& hostname, Network::Address::InstanceConstSharedPtr address,
1311
      const std::vector<Network::Address::InstanceConstSharedPtr>& address_list,
1312
      const envoy::config::endpoint::v3::LocalityLbEndpoints& locality_lb_endpoint,
1313
      const envoy::config::endpoint::v3::LbEndpoint& lb_endpoint, TimeSource& time_source);
1314
1315
  void registerHostForPriority(
1316
      const HostSharedPtr& host,
1317
      const envoy::config::endpoint::v3::LocalityLbEndpoints& locality_lb_endpoint);
1318
1319
  void
1320
  updateClusterPrioritySet(const uint32_t priority, HostVectorSharedPtr&& current_hosts,
1321
                           const absl::optional<HostVector>& hosts_added,
1322
                           const absl::optional<HostVector>& hosts_removed,
1323
                           const absl::optional<Upstream::Host::HealthFlag> health_checker_flag,
1324
                           absl::optional<bool> weighted_priority_health = absl::nullopt,
1325
                           absl::optional<uint32_t> overprovisioning_factor = absl::nullopt);
1326
1327
  // Returns the saved priority state.
1328
3.26k
  PriorityState& priorityState() { return priority_state_; }
1329
1330
private:
1331
  ClusterImplBase& parent_;
1332
  PriorityState priority_state_;
1333
  const envoy::config::core::v3::Node& local_info_node_;
1334
  PrioritySet::HostUpdateCb* update_cb_;
1335
};
1336
1337
using PriorityStateManagerPtr = std::unique_ptr<PriorityStateManager>;
1338
1339
/**
1340
 * Base for all dynamic cluster types.
1341
 */
1342
class BaseDynamicClusterImpl : public ClusterImplBase {
1343
protected:
1344
  using ClusterImplBase::ClusterImplBase;
1345
1346
  /**
1347
   * Updates the host list of a single priority by reconciling the list of new hosts
1348
   * with existing hosts.
1349
   *
1350
   * @param new_hosts the full lists of hosts in the new configuration.
1351
   * @param current_priority_hosts the full lists of hosts for the priority to be updated. The list
1352
   * will be modified to contain the updated list of hosts.
1353
   * @param hosts_added_to_current_priority will be populated with hosts added to the priority.
1354
   * @param hosts_removed_from_current_priority will be populated with hosts removed from the
1355
   * priority.
1356
   * @param all_hosts all known hosts prior to this host update across all priorities.
1357
   * @param all_new_hosts addresses of all hosts in the new configuration across all priorities.
1358
   * @return whether the hosts for the priority changed.
1359
   */
1360
  bool updateDynamicHostList(const HostVector& new_hosts, HostVector& current_priority_hosts,
1361
                             HostVector& hosts_added_to_current_priority,
1362
                             HostVector& hosts_removed_from_current_priority,
1363
                             const HostMap& all_hosts,
1364
                             const absl::flat_hash_set<std::string>& all_new_hosts);
1365
};
1366
1367
/**
1368
 * Utility function to get Dns from cluster/enum.
1369
 */
1370
Network::DnsLookupFamily
1371
getDnsLookupFamilyFromCluster(const envoy::config::cluster::v3::Cluster& cluster);
1372
1373
/**
1374
 * Utility function to report upstream cx destroy metrics
1375
 */
1376
void reportUpstreamCxDestroy(const Upstream::HostDescriptionConstSharedPtr& host,
1377
                             Network::ConnectionEvent event);
1378
1379
/**
1380
 * Utility function to report upstream cx destroy active request metrics
1381
 */
1382
void reportUpstreamCxDestroyActiveRequest(const Upstream::HostDescriptionConstSharedPtr& host,
1383
                                          Network::ConnectionEvent event);
1384
1385
/**
1386
 * Utility function to resolve health check address.
1387
 */
1388
Network::Address::InstanceConstSharedPtr resolveHealthCheckAddress(
1389
    const envoy::config::endpoint::v3::Endpoint::HealthCheckConfig& health_check_config,
1390
    Network::Address::InstanceConstSharedPtr host_address);
1391
1392
} // namespace Upstream
1393
} // namespace Envoy